AnsweredAssumed Answered

Function not using passed value

Question asked by Kas Lewis on Dec 26, 2014
Latest reply on Dec 28, 2014 by Butcher

I have two functions to send I2C data and two to receive I2C data, one is for only one data byte and the other is for multiple data bytes. The issue is the single data byte function does not appear to be using the passed in values and I cannot work out why this would be. As you can see I have set the values of device_address and device_register in the functions to see if this prevents the I2C from hanging and it does. If I do not add these explicit declarations the code hangs at the first i2c_Data_Transmit_Delay(); in each of the one byte functions. Checking the passed in values of device_address and device_register they are both incorrect and appear  to be 0x98 which does not appear in my code and neither does 0x4C which would be 0x98 shifted right once. I have also attached a copy of the full code for further reference.

 

Any help would be very much appreciated.

 

Here is the write function that uses accepts only one data byte

void i2c_Write(char device_address, char device_register, char data){   device_address = 0x4B;                                              //TODO: Fix addressing issue   device_register = 0x03;   data = 0x12;       I2C0_C1 |= I2C_C1_MST_MASK | I2C_C1_TX_MASK;                        //Send start bit     // I2C0_C1 &= ~I2C_C1_TXAK_MASK;      I2C0_D = (device_address << 1) | I2C_MASTER_WRITE;                  //Device address with write bit set     while ((I2C0_S & I2C_S_IICIF_MASK) == 0){     //Wait for data to transmit   }   I2C0_S |= I2C_S_IICIF_MASK; //    i2c_Data_Trasmit_Delay();       I2C0_D = device_register;                                           //Device register to write to     while ((I2C0_S & I2C_S_IICIF_MASK) == 0){     //Wait for data to transmit   }   I2C0_S |= I2C_S_IICIF_MASK; //    i2c_Data_Trasmit_Delay();       I2C0_D = data;                                                      //Write to register     while ((I2C0_S & I2C_S_IICIF_MASK) == 0){     //Wait for data to transmit   }   I2C0_S |= I2C_S_IICIF_MASK; //    i2c_Data_Trasmit_Delay();       I2C0_S |= I2C_S_IICIF_MASK;     I2C0_C1 &= ~I2C_C1_MST_MASK;       while((I2C0_FLT & I2C_FLT_STOPF_MASK) == 0){                        //Delay for stop bit         //Wait for stop bit to transmit     }     I2C0_FLT &= ~I2C_FLT_STOPF_MASK; }   

 

Here is the write function that accepts multiple data bytes

void i2c_Write_Multi(char device_address, char device_register, char* data_array, unsigned char length){     int i = 0;       I2C0_C1 |= I2C_C1_MST_MASK | I2C_C1_TX_MASK | I2C_C1_IICEN_MASK;       I2C0_C1 |= I2C_C1_MST_MASK | I2C_C1_TX_MASK;                        //Send start bit     I2C0_C1 &= ~I2C_C1_TXAK_MASK;      I2C0_D = (device_address << 1) | I2C_MASTER_WRITE;                  //Device address with write bit set     i2c_Data_Trasmit_Delay();      I2C0_D = device_register;                                           //Device register to write to     i2c_Data_Trasmit_Delay();       for(i = 0; i < length; i++){                                        //Write n bytes         I2C0_D = data_array[i];         i2c_Data_Trasmit_Delay();     }       I2C0_S |= I2C_S_IICIF_MASK;     I2C0_C1 &= ~I2C_C1_MST_MASK;       while((I2C0_FLT & I2C_FLT_STOPF_MASK) == 0){                        //Delay for stop bit         //Wait for stop bit to transmit     }     I2C0_FLT &= ~I2C_FLT_STOPF_MASK; }   

 

 

Here are the two write functions

char i2c_Read(uint8_t device_address, char device_register){     char temp;     device_address = 0x4B;                                              //TODO: Fix addressing issue     device_register = 0x0B;       I2C0_C1 |= I2C_C1_MST_MASK | I2C_C1_TX_MASK;                        //Send start bit     // I2C0_C1 &= ~I2C_C1_TXAK_MASK;       I2C0_D = (device_address << 1) | I2C_MASTER_WRITE;                  //Device address with write bit set     i2c_Data_Trasmit_Delay();       I2C0_D = device_register;                                           //Device register to read from     i2c_Data_Trasmit_Delay();       I2C0_C1 |= I2C_C1_RSTA_MASK;                                        //Send restart      I2C0_D = (device_address << 1) | I2C_MASTER_READ;                   //Device address with read bit set     i2c_Data_Trasmit_Delay();       I2C0_C1 &= ~I2C_C1_TX_MASK;                                         //Change to Rx mode       I2C0_C1 |= I2C_C1_TXAK_MASK;                                        //Set NACK     temp = I2C0_D;                                                      //Receive data byte     i2c_Data_Trasmit_Delay();       I2C0_C1 &= ~I2C_C1_MST_MASK;                                        //Set stop bit     I2C0_C1 |= I2C_C1_TX_MASK;                                          //Change to Tx mode       return I2C0_D; }   void i2c_Read_Multi(char device_address, char device_register, char* data_array, unsigned char length){     int i = 0;     char temp;       I2C0_C1 |= I2C_C1_MST_MASK | I2C_C1_TX_MASK | I2C_C1_IICEN_MASK;       I2C0_C1 |= I2C_C1_MST_MASK | I2C_C1_TX_MASK;                        //Send start bit     // I2C0_C1 &= ~I2C_C1_TXAK_MASK;       I2C0_D = (device_address << 1) | I2C_MASTER_WRITE;                  //Device address with write bit set     i2c_Data_Trasmit_Delay();      I2C0_D = device_register;                                           //Device register to read from     i2c_Data_Trasmit_Delay();      I2C0_C1 |= I2C_C1_RSTA_MASK;                                        //Send restart      I2C0_D = (device_address << 1) | I2C_MASTER_READ;                   //Device address with read bit set     i2c_Data_Trasmit_Delay();    

 

 

void i2c_Read_Multi(char device_address, char device_register, char* data_array, unsigned char length){     int i = 0;     char temp;       I2C0_C1 |= I2C_C1_MST_MASK | I2C_C1_TX_MASK | I2C_C1_IICEN_MASK;       I2C0_C1 |= I2C_C1_MST_MASK | I2C_C1_TX_MASK;                        //Send start bit     // I2C0_C1 &= ~I2C_C1_TXAK_MASK;       I2C0_D = (device_address << 1) | I2C_MASTER_WRITE;                  //Device address with write bit set     i2c_Data_Trasmit_Delay();      I2C0_D = device_register;                                           //Device register to read from     i2c_Data_Trasmit_Delay();      I2C0_C1 |= I2C_C1_RSTA_MASK;                                        //Send restart      I2C0_D = (device_address << 1) | I2C_MASTER_READ;                   //Device address with read bit set     i2c_Data_Trasmit_Delay();      I2C0_C1 &= ~I2C_C1_TX_MASK;                                         //Change to Rx mode     temp = I2C0_D;     i2c_Data_Trasmit_Delay();       for (i = 0; i < length - 2; i ++){                                  //Receive first n - 1 bytes         data_array[i] = I2C0_D;         i2c_Data_Trasmit_Delay();     }       I2C0_C1 |= I2C_C1_TXAK_MASK;                                        //Receive last byte     data_array[i] = I2C0_D;     i2c_Data_Trasmit_Delay();       I2C0_C1 &= ~I2C_C1_MST_MASK;                                        //Set stop bit     I2C0_C1 |= I2C_C1_TX_MASK;                                          //Change to Tx mode     data_array[i + 1] = I2C0_D;                                         //Read final byte }                 

 

For clarity here is the i2c_Data_Transmit_Delay() function

void i2c_Data_Trasmit_Delay(){             while ((I2C0_S & I2C_S_IICIF_MASK) == 0){             //Wait for data to transmit         }         I2C0_S |= I2C_S_IICIF_MASK; }   

 

Lastly here is the call from main

int main(void) {     char temp;     char i2cReadArray[] = {0,0,0,0,0,0,0,0,0};     char i2cWriteArray[] = {0,0,0,0,0,0,0,0,0};       clk_Init();     i2c_Init();       i2cWriteArray[0] = 0x12;     i2cWriteArray[1] = 0x34;     i2cWriteArray[2] = 0x56;     i2cWriteArray[3] = 0x78;       i2c_Write_Multi(0x4B, 0x04, i2cWriteArray, 2);     i2c_Read_Multi(0x4B, 0x04, i2cReadArray, 2);      while(1){         i2c_Write_Multi(0x4B, 0x04, i2cWriteArray, 2);         i2c_Read_Multi(0x4B, 0x04, i2cReadArray, 2);               i2c_Write_Multi(0x4B, 0x04, i2cWriteArray, 4);         i2c_Read_Multi(0x4B, 0x04, i2cReadArray, 4);           temp = i2c_Read(0x4B, 0x0B);         i2c_Write(0x4B, 0x03, 0x12);     } }            

 

Point in the code where the i2c_wite() hangs and the values of the 3 passed values:

device_address value (same in both places)

2014-12-26 11_45_23-Debug - Car_Window_Control_Sources_main.c - CodeWarrior Development Studio.jpg

 

device_register value (different from hover to watch window)

2014-12-26 11_44_29-Debug - Car_Window_Control_Sources_main.c - CodeWarrior Development Studio.jpg

data register value (different from hover to watch window)

2014-12-26 11_45_54-Debug - Car_Window_Control_Sources_main.c - CodeWarrior Development Studio.jpg

 

 

Looking into it further (using a logic analyzer) I can call i2c_write() or i2c_read() once before I get a hang on the calling either of these again. Any combination of i2c_write() and i2c_read() leads to a hang up on the second function call.

i2c_write() -> i2c_read()            Hangs in i2c_read()

i2c_write() -> i2c_write()           Hangs in i2c_write()

i2c_read() -> i2c_read()             Hangs in i2c_read()

i2c_read() -> i2c_write()            Hangs in i2c_write()

 

Evan adding a i2c_write_multi() or i2c_read_multi() between the two calls does not help anything but the multi calls work with no issue.

 

If there is at all any suggestions I would be happy to hear them as this is holding up my project, if there is any more information that is needed I will haphappilyswer what you need if it helps resolve this odd issue.

 

Kas

Original Attachment has been moved to: main.c.txt.zip

Outcomes