[SOLVED] PIC18 SMBus Read Word (16bits) Issue

Status
Not open for further replies.

firoz3321

Newbie level 5
Joined
Oct 3, 2008
Messages
9
Helped
0
Reputation
0
Reaction score
0
Trophy points
1,281
Visit site
Activity points
1,350
Hi ,

I am very new to PIC controllers.

I am using PIC18LF43k22 controller, and i have configured the I2C as SMBus.
I having issue reading 16 Bit data from the slave.
Kindly help me.

ISSUE:

I am able to write BYTE and write WORD (2 bytes) to the Slave, But i am not able to READ from the slave. I am sure i am doing it wrong, but i cant understand which part am i missing.

I am either getting both LOWer Byte and Higher Byte same

example :
Expected 16 bit data is : 0X0002
I am recieving :
Data_Low : 0x02
Data_High : 0x02
Data : 0x0202

I followed this protocol :



I am pasting my Read routines Below:

Code:
void I2C1_init(void) // init I2C1 as master 
 { 
     TRISCbits.TRISC3 = 1;              // LT4100 SCK, Smart battery SCK 
     TRISCbits.TRISC4 = 1;              // LT4100 SDA, Smart battery SDA 
     PIE1bits.SSP1IE = 1; 
     SSPCON1 = 0x28;                    //enable serial port and configure SDA and SCL 
     SSP1STATbits.SMP = 0;              //slew rate disable and configered to input level to I2C (< 100k) 
     SSP1STATbits.CKE = 1;              // Enable input logic thresholds to SMBus compatable 
     SSPADD = 39;                               // baud rate fixed to 50kHz with 8 MHz crystal frequency 
     SSPCON2 = 0x00; 
     //SSPCON2bits.ACKEN = 1; 
 } 
 void I2C1Ack(void) 
 { 
     SSPCON2bits.ACKDT = 0;      /* Acknowledge data bit, 0 = ACK */ 
     SSPCON2bits.ACKEN = 1;      /* Ack data enabled */ 
     while(SSPCON2bits.ACKEN);   /* wait for ack data to send on bus */ 
 } 
 void I2C1Nak(void) 
 { 
     SSPCON2bits.ACKDT = 1;      /* Acknowledge data bit, 1 = NAK */ 
     SSPCON2bits.ACKEN = 1;      /* Ack data enabled */ 
     while(SSPCON2bits.ACKEN);   /* wait for ack data to send on bus */ 
 } 
 void I2C1RecieveEnable(void) 
 { 
     SSPCON2bits.RCEN = 1;               //enable receive enable bit 
     while (PIR1bits.SSPIF != 1); 
     PIR1bits.SSPIF = 0; 
 } 
 void I2C1SSPIFWait(void) 
 { 
     while (PIR1bits.SSPIF != 1); 
     PIR1bits.SSPIF = 0; 
 } 
 void I2C1_Idle(void) 
 { 
     //while (SSP1STATbits.BF);           // Wait for bus Idle (BF - is high while transmission in progress) 
     while ((SSP1CON2 & 0x1F) | (SSP1STATbits.R_W)); 
 } 
 void I2C1_start(void) 
 { 
     I2C1_Idle();                        // Wait for Bus Idle 
      
     SSPCON2bits.SEN = 1; 
     while (PIR1bits.SSPIF != 1);        //START CONDITION and wait for  SSPIF flag 
     PIR1bits.SSPIF = 0; 
 } 
 void I2C1_repeated_start(void) 
 { 
     SSPCON2bits.RSEN = 1; 
     while (PIR1bits.SSPIF != 1);        //REPEATED START CONDITION 
     PIR1bits.SSPIF = 0; 
 } 
 void I2C1_stop(void) 
 { 
     SSPCON2bits.PEN = 1; // STOP condition 
     while (PIR1bits.SSPIF != 1); //REPEATED START CONDITION 
     PIR1bits.SSPIF = 0; 
 } 
 unsigned char I2C1_byte_read(unsigned char dev_add, unsigned char loc_add) 
 { 
     unsigned char read_dat = 0; 
     unsigned char temp_add = (dev_add | 0x01); 
     I2C1_start();                       // SMBus START 
     SSPBUF = dev_add;                   // Slave Address with Write Bit 
     I2C1SSPIFWait(); 
     //pointing to specific location 
     SSPBUF = loc_add;                   //Command Code / add location 
     I2C1SSPIFWait(); 
     //I2C1_repeated_start(); 
     SSPBUF = temp_add;                  //Slave Address + Read Bit 
     I2C1SSPIFWait(); 
      
     read_dat = SSPBUF;                  //saving data into some register 
 //    SSPCON2bits.ACKDT = 0;            // Send an ack bit 
 //    SSPCON2bits.ACKEN = 1; 
 //    while (SSPCON2bits.ACKEN);        // Wait for ack to finish 
     I2C1_stop();                        // SMBus STOP 
     return (read_dat); 
 } 
 unsigned int I2C1_Word_read(unsigned char dev_add, unsigned char loc_add) 
 { 
     unsigned int read_dat_msb = 0, read_dat_lsb = 0, read_dat = 0; 
     unsigned char temp_add = (dev_add | 0x01); //((dev_add << 1) | 0x01); //Fz_Mod 
     I2C1_start();                       // SMBus START 
     SSPBUF = dev_add;                   // Slave Address with Write Bit 
     I2C1SSPIFWait(); 
     //I2C1Ack();                          // ACK 
     //pointing to specific location 
     SSPBUF = loc_add;                   //Command Code / add location 
     I2C1SSPIFWait(); 
     //I2C1Ack();                          // ACK 
     I2C1_repeated_start(); 
      
     SSPBUF = temp_add;                  //Slave Address + Read Bit 
     I2C1SSPIFWait(); 
     //I2C1RecieveEnable(); 
     //I2C1Ack();                          // ACK 
     read_dat_lsb = SSPBUF;              //saving data into some register 
     I2C1Ack();                          // ACK 
     read_dat_msb = SSPBUF;              //saving data into some register 
     I2C1Nak();                          // NACK 
     I2C1_stop(); // SMBus STOP 
     read_dat_msb = read_dat_msb << 8; 
     read_dat = read_dat_msb | read_dat_lsb; 
     return (read_dat); 
 }

--------------------------------------------------------------------------

2. One more query i have is :

Which of the following 2 codes are right ?

Code:
void I2C1_start(void)
 {
     I2C1_Idle();                        // Wait for Bus Idle
      SSPCON2bits.SEN = 1;
     while (SSPCON2bits.SEN);
 }


or

Code:
  void I2C1_start(void)
 {
     I2C1_Idle();                        // Wait for Bus Idle
     
     SSPCON2bits.SEN = 1;
     while (PIR1bits.SSPIF != 1);        //START CONDITION and wait for  SSPIF flag
     PIR1bits.SSPIF = 0;
 }

Second one ( while (PIR1bits.SSPIF != 1); ) is working for me, but all the example codes i have see seem to be using the first part.
 

Status
Not open for further replies.

Similar threads

Cookies are required to use this site. You must accept them to continue using the site. Learn more…