Hi all,
I am facing a big problem in communicate with bq27441(battery management) by I2C protocol (I use F28335 I2C module) . Write or read registers of these chip is really strange. Sometime got right results but sometime i got wrong result again and again. Such as: when i try reading a register many time (for example designed capacity) i get many different values (of course true value is one of them). Please help me if you know why.
Below is my program config I2C:
// Initial for I2C
// Initial for I2C module void init_I2C(void) { EALLOW; /* Enable internal pull-up for the selected pins */ // Pull-ups can be enabled or disabled disabled by the user. // Comment out other unwanted lines. GpioCtrlRegs.GPBPUD.bit.GPIO32 = 1; // Disable pull-up for GPIO32 (SDAA) GpioCtrlRegs.GPBPUD.bit.GPIO33 = 1; // Disnable pull-up for GPIO33 (SCLA) /* Set qualification for selected pins to asynch only */ // This will select asynch (no qualification) for the selected pins. // Comment out other unwanted lines. GpioCtrlRegs.GPBQSEL1.bit.GPIO32 = 3; // Asynch input GPIO32 (SDAA) GpioCtrlRegs.GPBQSEL1.bit.GPIO33 = 3; // Asynch input GPIO33 (SCLA) /* Configure SCI pins using GPIO regs*/ // This specifies which of the possible GPIO pins will be I2C functional pins. // Comment out other unwanted lines. GpioCtrlRegs.GPBMUX1.bit.GPIO32 = 1; // Configure GPIO32 for SDAA operation GpioCtrlRegs.GPBMUX1.bit.GPIO33 = 1; // Configure GPIO33 for SCLA operation EDIS; I2caRegs.I2CPSC.all = 14; // Prescaler - need 7-12 Mhz on module clk (150/15 = 10MHz) I2caRegs.I2CCLKL = 12; // NOTE: must be non zero 1.7us I2caRegs.I2CCLKH = 5; // NOTE: must be non zero 1us --> I2C freq: 370KHz I2caRegs.I2CIER.all = 0x24; // Enable SCD & ARDY interrupts I2caRegs.I2CMDR.all = 0x0020; // Take I2C out of reset // Stop I2C when suspended I2caRegs.I2CFFTX.all = 0x6000; // Enable FIFO mode and TXFIFO I2caRegs.I2CFFRX.all = 0x2040; // Enable RXFIFO, clear RXFFINT // Interrupts that are used in this example are re-mapped to // ISR functions found within this file. EALLOW; // This is needed to write to EALLOW protected registers PieVectTable.I2CINT1A = &i2c_rxa_isr; EDIS; // This is needed to disable write to EALLOW protected registers // PieCtrlRegs.PIECTRL.bit.ENPIE = 1; // Use in init_Sci_B // Enable I2C interrupt 1 in the PIE: Group 8 PieCtrlRegs.PIEIER8.bit.INTx1 = 1; // Enable CPU INT8 which is connected to PIE group 8 IER |= M_INT8; }
// Write function
// write i2c function void I2C_write_data(unsigned int slave_addr, unsigned int length) { unsigned int jdex; while(I2caRegs.I2CMDR.bit.STP == 1); // Check if bus busy while(I2caRegs.I2CSTR.bit.BB == 1); // Setup slave address I2caRegs.I2CSAR = slave_addr; // Setup number of bytes to send // MsgBuffer + Address I2caRegs.I2CCNT = length; // Setup data to send for (jdex=0; jdex<length; jdex++) { I2caRegs.I2CDXR = *(i2c_write_buff+jdex); // i2c_write_buff[] data will be write } // Send start as master transmitter I2caRegs.I2CMDR.all = 0x6E20; }
// Function read from I2C
// I2C read function void I2C_read_data(unsigned int slave_addr, unsigned int cmd_length) { unsigned int jdex; // Wait until the STP bit is cleared from any previous master communication. // Clearing of this bit by the module is delayed until after the SCD bit is // set. If this bit is not checked prior to initiating a new message, the // I2C could get confused. while(I2caRegs.I2CMDR.bit.STP == 1); // Check if bus busy while(I2caRegs.I2CSTR.bit.BB == 1); I2caRegs.I2CSAR = slave_addr; I2caRegs.I2CCNT = cmd_length; // Setup data to send for (jdex=0; jdex<cmd_length; jdex++) { I2caRegs.I2CDXR = i2c_cmd[jdex]; // start address will be read } I2caRegs.I2CMDR.all = 0x2620; // Send cmd with no stop user_delay(10000); --> delay 940us I2caRegs.I2CCNT = i2c_receive_length; // Setup how many bytes to expect I2caRegs.I2CMDR.all = 0x2C20; // Send restart as master receiver }
// Program read data from bq27441:
// Read from address 0x43 and 0x44 (slave return 2 byte 0x43 MSB, 0x44 LSB) i2c_write_buff[0] = 0x43; // buffer i2c master write to slave I2C_write_data(0x55, 1); // write user_delay(1000); --> delay 94us > 66us i2c_cmd[0] = 0x43; // adress master read from slave i2c_receive_length = 1; // global variable: length of data I2c master will receive I2C_read_data(0x55, 1); user_delay(1000); temp[0] = i2c_read_buff[0]; // data received from I2c will store in i2c_read_buff i2c_write_buff[0] = 0x43; // I2C_write_data(0x55, 1); user_delay(1000); --> delay 94us > 66us i2c_cmd[0] = 0x44; i2c_receive_length = 1; // global variable: length of data I2c master will receive I2C_read_data(0x55, 1); user_delay(1000); temp[1] = i2c_read_buff[0]; // designed capacity = temp[1]+ temp[0]*256
This is the best code that i can communicate with bqxx chip (got more right result).
Thanks for reading.
Best Regards.
Phien Nguyen