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