CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

I2C 18F2550 Master reader from Atmega 328P Slave

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
eng.mohamedtoumi



Joined: 13 Jan 2018
Posts: 23
Location: Tun

View user's profile Send private message Visit poster's website

I2C 18F2550 Master reader from Atmega 328P Slave
PostPosted: Sat Mar 17, 2018 7:43 am     Reply with quote

Hello I'm trying to write data via I2C
from the Atmega MCU to the 18F2550 MCU.
I need to set the 18F2550 AS A MASTER
and the Atmega 328P as a Slave.
Since Atmega works with 7-bit addressing i have managed
to set the slave address to (0x88 in the Atmega code)
and (0x10 in the 18F2550 code ).
[address in 18F code=2*address in Atmega code] ...
But still the data received on the PIC MCU is wrong.
code of ATMEGA 328P SLAVE :

Code:
#include <LiquidCrystal.h>
#include <Wire.h>
const int rs = 10, en = 11, d4 = 5, d5 = 4, d6 = 3, d7 = 2; //16*2 LCD PINS
LiquidCrystal lcd(rs, en, d4, d5, d6, d7); //16*2 LCD

long cm;  //distance of Usound 1 in centimeters
long cm2;  //distance of Usound 2 in centimeters

int trigf= A1;  // ultrasound sensor pins connected to arduino
int echof=13 ;   // ultrasound sensor pins connected to arduino
int trigl = A0;   // ultrasound sensor pins connected to arduino
int echol=12 ;  // ultrasound sensor pins connected to arduino

long look (int trigm , int echom) // function to calculate the distance of ultrasound
{               
  long cmm ;
  long temps;
  digitalWrite(trigm, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigm, LOW);
  pinMode(echom, INPUT);
  temps = pulseIn(echom, HIGH);
  cmm = temps/58;
  return (cmm) ;
}

void setup() {
  Wire.onReceive(receiveEvent); 
  Wire.begin(0x88);  //ADRESS GIVEN To THE ATMEGA 328P AS SLAVE
  lcd.begin(16, 2);
  Serial.begin(9600);
}

void loop() {
lcd.setCursor(0, 1);
cm=look(trigf,echof); //CALCULATE FIRST DISTANCE
cm2=look(trigl,echol); //CALCULATE 2nd DISTANCE
Serial.write(cm);          //DISPLAY THE 1st DIStance
}

void receiveEvent(int bytes) {
Wire.write(cm);  // SEND THE distance FROM ATMEGA328p to the 18F2550 via I2C
}


Code of 18F2550 MASTER
Code:
#include <18F2550.h>
#fuses HSPLL,PROTECT,NOLVP,NOWDT,NODEBUG,PLL1,CPUDIV1,NOMCLR
#use delay (internal=8M)
#use I2C(MASTER, SDA=PIN_B6, SCL=PIN_B7, FAST=450000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)
#include "lcd.c"
int  r;
void main(){
 lcd_init(); // LCD initialisation
 setup_oscillator(OSC_8MHZ);
while(true){                   
i2c_start();
i2c_write(0x10); //CONNECT TO SLAVE 0X10 (adress given by PCM Program of the ATMEGA 328p used as a slave
delay_ms(10) ;
i2c_start();  // I2C restart
i2c_write(0x10 + 1); // adress of slave in write mode
r = i2c_read(1);      // get the distance (cm = r) form the ATMEGA 328P
i2c_stop();             //I2c Stop communication
delay_ms(1000);
printf(" %d  ",r);         // display the distance on Virtual terminal               
}
}

ANY Solution ?


Last edited by eng.mohamedtoumi on Sat Mar 17, 2018 8:35 am; edited 1 time in total
temtronic



Joined: 01 Jul 2010
Posts: 9221
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Sat Mar 17, 2018 8:16 am     Reply with quote

is this line of code..
i2c_write(0x10);

the slave address ??

if so, 0x10 != 0x88 !

it would help, me, other, and you if you add comments at the end of lines of code. While you know what you wrote and why, we don't have a clear understanding of your code.

also

what are the I2C bus pullups? what distance are the chips from each other?
I'd actually make the I2C bus SLOW NOT fast !! At least for testing purposes as it makes it easier to scope out.

and
does the PCM P's I2C scanner program see the 'slave' at address 0x88 ? That test needs to be done first to confirm both basic hardware and software.

Jay
eng.mohamedtoumi



Joined: 13 Jan 2018
Posts: 23
Location: Tun

View user's profile Send private message Visit poster's website

PostPosted: Sat Mar 17, 2018 8:26 am     Reply with quote

thank you for your response ...
1) yes the I2C communication is working correctly when i tried to send
data from the 18F2550 to Atmega And i verified that it is correct So i don't think that it is a hardware problem ...(PULLUPS 4.7k on both SDA and SCL)
2) I've used PCM P's I2C scanner program :
I've Set the Slave address to 0x88 (in the Arduino Code as mentioned)
and the PCM gave me 0x10 !!! (Arduino is on 7 bit addressing while 18F2550 on 8 bit addressing )
3)i2c_write(0x10) IS A LINE OF THE CODE it is the slave address given by the PCM P' I2C Scanner program
PS : I VE added some comments to the codes if you want to check them
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sat Mar 17, 2018 10:13 am     Reply with quote

Arduino uses 7-bit i2c addressing, so 0x88 is not correct. 0x88 is using
8-bits. In 7-bit addressing, the top bit is not used.

So your 0x88 slave address really becomes 0x08. Then to convert it to
8-bit mode, multiply it by 2 and you get 0x10. This explains why it works.

Get rid of the 0x88 in the Arduino code. Change it to:
Quote:
Wire.begin(0x08);

It will work the same way, but it won't be confusing.
eng.mohamedtoumi



Joined: 13 Jan 2018
Posts: 23
Location: Tun

View user's profile Send private message Visit poster's website

PostPosted: Sat Mar 17, 2018 3:06 pm     Reply with quote

hello I've changed it but i still same problem ... master can't read data from slave ...
Ttelmah



Joined: 11 Mar 2010
Posts: 19499

View user's profile Send private message

PostPosted: Sat Mar 17, 2018 3:16 pm     Reply with quote

You have the distance declared as a long int. int32. So the wire.write handler will be trying to write four bytes.
Your master needs to issue four reads, with only the last one having a NACK.
Currently you will only be reading the MSB of the cm distance.
eng.mohamedtoumi



Joined: 13 Jan 2018
Posts: 23
Location: Tun

View user's profile Send private message Visit poster's website

PostPosted: Sat Mar 17, 2018 3:39 pm     Reply with quote

Ttelmah wrote:
You have the distance declared as a long int. int32.

Even when i tried to send only data of type int the code didn't work.

Atmega 328p code:
Code:
void receiveEvent(int bytes) {
Wire.write(5); 
}

and the pic code is
Code:
 while(true){                   
        i2c_start();
        delay_ms(10);
        i2c_write(0x10);  /* Device Address */
        delay_ms(10);
        i2c_start();   // restart condition
        delay_ms(10);
        i2c_write(0x10 + 1);
        delay_ms(10);
        r = i2c_read(0);
        delay_ms(10); 
        i2c_stop();
        printf ("r = 0x%2.2X\r\n", r);

}
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sun Mar 18, 2018 1:32 am     Reply with quote

Quote:
void receiveEvent(int bytes) {
Wire.write(5);
}
I think your Arduino slave code is wrong. You are using the
receiveEvent() to write. None of the Arduino examples that I looked
do this. They all use requestEvent() to write.

Look at the box on "Basic Algorithm":
http://www.berryjam.eu/2014/07/advanced-arduino-i2c-communication/

This forum is not the place to trouble-shoot your Arduino slave code.
You need to do that on an Arduino forum. Get it working with an Arduino
master. Then ask us how to use a PIC master with it.
Ttelmah



Joined: 11 Mar 2010
Posts: 19499

View user's profile Send private message

PostPosted: Sun Mar 18, 2018 6:33 am     Reply with quote

Also an 'int' on an Arduino is a 16 bit integer. To send a single byte, requires the byte data type.
Ttelmah



Joined: 11 Mar 2010
Posts: 19499

View user's profile Send private message

PostPosted: Sun Mar 18, 2018 8:32 am     Reply with quote

You need to do things one step at a time.

Though Arduino code is 'off topic', I'm sure some of the other posters here will be involved in stuff that talks between the PIC and the Arduino at some point, so will post a couple of hints:

The Arduino does not receive. It is being asked to transmit.
Code:

//rest from the existing code
byte cm; // one byte type.

void setup(void)
{
  Wire.begin(0x08);  //ADDRESS GIVEN To THE ATMEGA 328P AS SLAVE
  Wire.onRequest(requestEvent); //On event

  lcd.begin(16, 2);
  Serial.begin(9600);
}

void requestEvent(void)
{ //master requests data from slave
  Wire.write(cm); // one byte as PIC code expects
}


However I'd test your PIC master first, reading bytes from a know working hardware slave device. Only once you have this end working, switch to trying to link the two devices.

and as a further comment:
Code:

 while(true){                   
        i2c_start();
        delay_ms(10);
        i2c_write(0x10);  /* Device Address */
        delay_ms(10);
        i2c_start();   // restart condition
        delay_ms(10);
        i2c_write(0x10 + 1);
        delay_ms(10);
        r = i2c_read(0);
        delay_ms(10);
        i2c_stop();
        printf ("r = 0x%2.2X\r\n", r);

}

You don't have to do the restart for the slave code as shown.
You can just directly send the read address.

The point about 'restarting' on a master, is so you can _write_ a register address, and then turn the bus round to read from this address. If you are just doing a device that returns a value always starting from the same point, there is no need for the restart.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group