Part Number: BQ27441EVM-G1A
I am trying to update the nominal battery capacity, and everything is working fine, but when I request address 0x60 to get the current checksum, I always get back 0. (Note, I request 2 bytes due to programming limitations). Without this checksum, I can not calculate a new checksum, and thus can not update the battery capacity.
What is going wrong? Can I calculate the checksum myself?
My code is below. The part where I get the checksum is around line 204.
/*
* FuelGauge.c
*
* Created on: Jan 6, 2017
* Author: amorg
*/
// BQ27441 Library
#include <BQ27441_Definitions.h>
// Fuel Gauge Includes
#include <FuelGauge.h>
// Driver Library
#include <driverlib.h>
// Standard Library Includes
#include <stdbool.h>
#include <string.h>
// Global Variables
int NUM_OF_REC_BYTES = 0; // Holds the number of bytes to be received from the Fuel Gauge
uint8_t RXData[maxNumOfRXBytes]; // Array of unsigned 8 bit commands received from the Fuel Gauge
volatile uint8_t rxFlag = 0; // Receive interrupt marker
static volatile uint32_t xferIndex; // RXData index
// I2C Master Configuration Parameter
const eUSCI_I2C_MasterConfig i2cConfig =
{
EUSCI_B_I2C_CLOCKSOURCE_SMCLK, // SMCLK Clock Source
8000000, // SMCLK = 8MHz
EUSCI_B_I2C_SET_DATA_RATE_100KBPS, // Desired I2C Clock of 100khz
0, // No byte counter threshold
EUSCI_B_I2C_NO_AUTO_STOP // No Auto-stop
};
void FuelGauge_Setup()
{
// Select Port 6 for I2C - Set Pin 4, 5 to input Primary Module Function, (UCB1SIMO/UCB1SDA, UCB1SOMI/UCB1SCL).
#if SDApin == GPIO_PIN6 && I2Cport == GPIO_PORT_P6
MAP_GPIO_setAsPeripheralModuleFunctionInputPin(I2Cport, SDApin + SCLpin, GPIO_SECONDARY_MODULE_FUNCTION);
#else
MAP_GPIO_setAsPeripheralModuleFunctionInputPin(I2Cport, SDApin + SCLpin, GPIO_PRIMARY_MODULE_FUNCTION);
#endif
// Initializing I2C Master to SMCLK at 100kbs with no auto-stop
MAP_I2C_initMaster(EUSCI_module, &i2cConfig);
// Specify slave address
MAP_I2C_setSlaveAddress(EUSCI_module, BQ27441_I2C_ADDRESS);
// Set Master in transmit mode
MAP_I2C_setMode(EUSCI_module, EUSCI_B_I2C_TRANSMIT_MODE);
// Enable I2C Module to start operations
MAP_I2C_enableModule(EUSCI_module);
// Enable and clear the interrupt flags todo make transmit interrupts in the define page
MAP_I2C_clearInterruptFlag(EUSCI_module, EUSCI_B_I2C_TRANSMIT_INTERRUPT0 + EUSCI_B_I2C_RECEIVE_INTERRUPT0);
//Enable master Receive interrupt
MAP_Interrupt_enableInterrupt(EUSCI_moduleINT);
}
void getStatus(){
int redo = 0;
//GET DEVICE STATUS
//------------- Transmit ---------------
do{
EUSCI_TXBuffer &= 0x00; // Clear Transmit Buffer
redo += MAP_I2C_masterSendMultiByteStartWithTimeout(EUSCI_module, BQ27441_COMMAND_CONTROL,1000);
redo += MAP_I2C_masterSendMultiByteNextWithTimeout(EUSCI_module, BQ27441_CONTROL_STATUS,1000);
redo += MAP_I2C_masterSendMultiByteNextWithTimeout(EUSCI_module, 0x00,1000);
redo += MAP_I2C_masterSendMultiByteStopWithTimeout(EUSCI_module,1000);
}while(redo != 4);
//------------- Receive ----------------
NUM_OF_REC_BYTES = 2;
MAP_I2C_setMode(EUSCI_module, EUSCI_B_I2C_RECEIVE_MODE); // Set to Receive mode
MAP_I2C_masterReceiveStart(EUSCI_module); // Start Receiving
MAP_I2C_enableInterrupt(EUSCI_module, EUSCI_B_I2C_RECEIVE_INTERRUPT0); // Enable Receive Interrupt
xferIndex = 0; // Set RXData index to 0
while(rxFlag != 1); // Wait until receive interrupt flag is received
rxFlag = 0;
}
void getFlags(){
//get current flag register
//------------- Transmit ---------------
EUSCI_TXBuffer &= 0x00; // Clear Transmit Buffer
MAP_I2C_masterSendSingleByte(EUSCI_module,BQ27441_COMMAND_FLAGS); //send the byte (the low one) to read
//------------- Receive ----------------
NUM_OF_REC_BYTES = 2;
MAP_I2C_setMode(EUSCI_module, EUSCI_B_I2C_RECEIVE_MODE); // Set to Receive mode
MAP_I2C_masterReceiveStart(EUSCI_module); // Start Receiving
MAP_I2C_enableInterrupt(EUSCI_module, EUSCI_B_I2C_RECEIVE_INTERRUPT0); // Enable Receive Interrupt
xferIndex = 0; // Set RXData index to 0
while(rxFlag != 1); // Wait until receive interrupt flag is received
rxFlag = 0;
}
void setUpdateMode(){
//Set CONFIG UPDATE MODE
//------------- Transmit ---------------
EUSCI_TXBuffer &= 0x00; // Clear Transmit Buffer
MAP_I2C_masterSendMultiByteStart(EUSCI_module, BQ27441_COMMAND_CONTROL);
MAP_I2C_masterSendMultiByteNext(EUSCI_module, BQ27441_CONTROL_SET_CFGUPDATE);
MAP_I2C_masterSendMultiByteNext(EUSCI_module, 0x00);
MAP_I2C_masterSendMultiByteStop(EUSCI_module);
//Make sure that CFGUPMODE is enabled. May take upto 1 second
while(1) //todo poor practice // Poll the Flags register using flags() (0x06) until
{ // the CFG_mode flag is HIGH
//------------- Transmit ---------------
EUSCI_TXBuffer &= 0x00; // Clear Transmit Buffer
MAP_I2C_masterSendSingleByte(EUSCI_module,BQ27441_COMMAND_FLAGS); //send the byte (the low one) to read
//------------- Receive ----------------
NUM_OF_REC_BYTES = 2;
MAP_I2C_setMode(EUSCI_module, EUSCI_B_I2C_RECEIVE_MODE); // Set to Receive mode
MAP_I2C_masterReceiveStart(EUSCI_module); // Start Receiving
MAP_I2C_enableInterrupt(EUSCI_module, EUSCI_B_I2C_RECEIVE_INTERRUPT0); // Enable Receive Interrupt
xferIndex = 0; // Set RXData index to 0
while(rxFlag != 1); // Wait until receive interrupt flag is received
rxFlag = 0;
if(((RXData[0] & BQ27441_FLAG_CFGUPMODE) >> 4) == 1) break; // Check CFG mode flag
}
}
void getDeviceType(){
//GET DEVICE TYPE (0X0421)
//------------- Transmit ---------------
EUSCI_TXBuffer &= 0x00; // Clear Transmit Buffer
MAP_I2C_masterSendMultiByteStart(EUSCI_module, BQ27441_COMMAND_CONTROL);
MAP_I2C_masterSendMultiByteNext(EUSCI_module, BQ27441_CONTROL_DEVICE_TYPE);
MAP_I2C_masterSendMultiByteNext(EUSCI_module, 0x00);
MAP_I2C_masterSendMultiByteStop(EUSCI_module);
EUSCI_TXBuffer &= 0x00; // Clear Transmit Buffer
MAP_I2C_masterSendSingleByte(EUSCI_module,0x00);
//------------- Receive ---------------- //************************NOTE*************************
NUM_OF_REC_BYTES = 2; // NUM_OF_REC_BYTES accepts values of 2 or greater only
MAP_I2C_setMode(EUSCI_module, EUSCI_B_I2C_RECEIVE_MODE); // Set to Receive mode
MAP_I2C_masterReceiveStart(EUSCI_module); // Start Receiving
MAP_I2C_enableInterrupt(EUSCI_module, EUSCI_B_I2C_RECEIVE_INTERRUPT0); // Enable Receive Interrupt
xferIndex = 0; // Set RXData index to 0
while(rxFlag != 1); // Wait until receive interrupt flag is received
rxFlag = 0;
}
//TODO EXIT ON FAILURE
void FuelGauge_SetBatteryCap(uint16_t batCap)
{
// //Module Reset
// EUSCI_TXBuffer &= 0x00; // Clear Transmit Buffer
// MAP_I2C_masterSendMultiByteStart(EUSCI_module, BQ27441_COMMAND_CONTROL);
// MAP_I2C_masterSendMultiByteNext(EUSCI_module, BQ27441_CONTROL_RESET);
// MAP_I2C_masterSendMultiByteNext(EUSCI_module, 0x00);
// MAP_I2C_masterSendMultiByteStop(EUSCI_module);
//------------- Transmit ---------------
EUSCI_TXBuffer &= 0x00;
MAP_I2C_masterSendSingleByte(EUSCI_module,0x0A);
//------------- Receive ----------------
NUM_OF_REC_BYTES = 2;
MAP_I2C_setMode(EUSCI_module, EUSCI_B_I2C_RECEIVE_MODE); // Set to Receive mode
MAP_I2C_masterReceiveStart(EUSCI_module); // Start Receiving
MAP_I2C_enableInterrupt(EUSCI_module, EUSCI_B_I2C_RECEIVE_INTERRUPT0); // Enable Receive Interrupt
xferIndex = 0; // Set RXData index to 0
while(rxFlag != 1); // Wait until receive interrupt flag is received
rxFlag = 0;
getStatus();
getFlags();
setUpdateMode();
//Enable block data memory control (enable RAM access)
//------------- Transmit ---------------
EUSCI_TXBuffer &= 0x00; // Clear Transmit Buffer
MAP_I2C_masterSendMultiByteStart(EUSCI_module, BQ27441_EXTENDED_CONTROL);
MAP_I2C_masterSendMultiByteNext(EUSCI_module, 0x00);
MAP_I2C_masterSendMultiByteStop(EUSCI_module);
//access the state subclass
EUSCI_TXBuffer &= 0x00; // Clear Transmit Buffer
MAP_I2C_masterSendMultiByteStart(EUSCI_module, BQ27441_EXTENDED_DATACLASS);
MAP_I2C_masterSendMultiByteNext(EUSCI_module, 0x52);
MAP_I2C_masterSendMultiByteStop(EUSCI_module);
//Set the datablock to be accessed
EUSCI_TXBuffer &= 0x00; // Clear Transmit Buffer
MAP_I2C_masterSendMultiByteStart(EUSCI_module, BQ27441_EXTENDED_DATABLOCK);
MAP_I2C_masterSendMultiByteNext(EUSCI_module, 0x00);
MAP_I2C_masterSendMultiByteStop(EUSCI_module);
//send block checksum command to check the checksum
EUSCI_TXBuffer &= 0x00; // Clear Transmit Buffer
MAP_I2C_masterSendSingleByte(EUSCI_module, BQ27441_EXTENDED_CHECKSUM);
//todo receive a checksum, should be 1 byte. It appears that this isnt being received.
//------------- Receive ----------------
NUM_OF_REC_BYTES = 2;
MAP_I2C_setMode(EUSCI_module, EUSCI_B_I2C_RECEIVE_MODE); // Set to Receive mode
MAP_I2C_masterReceiveStart(EUSCI_module); // Start Receiving
MAP_I2C_enableInterrupt(EUSCI_module, EUSCI_B_I2C_RECEIVE_INTERRUPT0); // Enable Receive Interrupt
xferIndex = 0; // Set RXData index to 0
while(rxFlag != 1); // Wait until receive interrupt flag is received
rxFlag = 0;
uint8_t OLD_Csum = RXData[1]; // Store old check sum value for calculation
//todo we should be looking to read just 2 bytes not 32. As per the manual we can get battery data from just 2 we don't have to read the entire block
//------------- Transmit ---------------
EUSCI_TXBuffer &= 0x00; // Clear Transmit Buffer
MAP_I2C_masterSendSingleByte(EUSCI_module, 0x4A);//BQ27441_EXTENDED_BLOCKDATA); // Command returns a 32 byte memory block
//------------- Receive ----------------
NUM_OF_REC_BYTES = 2; //32; // Set to receive 32 bytes
MAP_I2C_setMode(EUSCI_module, EUSCI_B_I2C_RECEIVE_MODE); // Set to Receive mode
MAP_I2C_masterReceiveStart(EUSCI_module); // Start Receiving
MAP_I2C_enableInterrupt(EUSCI_module, EUSCI_B_I2C_RECEIVE_INTERRUPT0); // Enable Receive Interrupt
xferIndex = 0; // Set RXData index to 0
while(rxFlag != 1); // Wait until receive interrupt flag is received
rxFlag = 0;
uint8_t OLD_DesCap_MSB = RXData[0]; // Store old battery capacity most significant byte value for calculation
uint8_t OLD_DesCap_LSB = RXData[1];
//--------------------------------------
uint8_t batCap_MSB = batCap >> 8; // Shift input batCap to the right 8 bits to obtain the MSByte
uint8_t batCap_LSB = batCap; // Truncate batCap to obtain the LSByte
//SET NEW BATTERY LEVEL
//------------- Transmit ---------------
EUSCI_TXBuffer &= 0x00; // Clear Transmit Buffer
MAP_I2C_masterSendMultiByteStart(EUSCI_module, 0x4A); // Memory Location where battery Capacity MSByte is stored
MAP_I2C_masterSendMultiByteNext(EUSCI_module, batCap_MSB); // todo this does not actually set battery capacity, it just sets it to what it was!!!! New MSByte for Bat Capacity
MAP_I2C_masterSendMultiByteStop(EUSCI_module);
EUSCI_TXBuffer &= 0x00; // Clear Transmit Buffer
MAP_I2C_masterSendMultiByteStart(EUSCI_module, 0x4B); // Memory Location where battery Capacity LSByte is stored
MAP_I2C_masterSendMultiByteNext(EUSCI_module, batCap_LSB); // todo this does not actually set battery capacity, it just sets it to what it was!!!! New LSByte for Bat Capacity
MAP_I2C_masterSendMultiByteStop(EUSCI_module);
//calculate new checksum
//todo you should be able to do this without getting all of the bytes, just the replaced ones.
//------------- Transmit ---------------
EUSCI_TXBuffer &= 0x00; // Clear Transmit Buffer
MAP_I2C_masterSendSingleByte(EUSCI_module,BQ27441_EXTENDED_BLOCKDATA); // Command returns a 32 byte memory block
//------------- Receive ----------------
NUM_OF_REC_BYTES = 32; // Set to receive 32 bytes
MAP_I2C_setMode(EUSCI_module, EUSCI_B_I2C_RECEIVE_MODE); // Set to Receive mode
MAP_I2C_masterReceiveStart(EUSCI_module); // Start Receiving
MAP_I2C_enableInterrupt(EUSCI_module, EUSCI_B_I2C_RECEIVE_INTERRUPT0); // Enable Receive Interrupt
xferIndex = 0; // Set RXData index to 0
while(rxFlag != 1); // Wait until receive interrupt flag is received
rxFlag = 0;
//--------------------------------------
uint8_t temp = (255 - OLD_Csum - OLD_DesCap_MSB - OLD_DesCap_LSB) % 256; // Calculate new checksum
uint8_t NEW_Csum = 255 - ((temp + batCap_MSB + batCap_LSB) % 256);
//------------- Transmit ---------------
EUSCI_TXBuffer &= 0x00; // Clear Transmit Buffer
MAP_I2C_masterSendMultiByteStart(EUSCI_module, BQ27441_EXTENDED_CHECKSUM);
MAP_I2C_masterSendMultiByteNext(EUSCI_module, NEW_Csum);
MAP_I2C_masterSendMultiByteStop(EUSCI_module);
getStatus();
getFlags();
//soft reset
EUSCI_TXBuffer &= 0x00; // Clear Transmit Buffer
MAP_I2C_masterSendMultiByteStart(EUSCI_module, BQ27441_COMMAND_CONTROL);
MAP_I2C_masterSendMultiByteNext(EUSCI_module, BQ27441_CONTROL_SOFT_RESET);
MAP_I2C_masterSendMultiByteNext(EUSCI_module, 0x00);
MAP_I2C_masterSendMultiByteStop(EUSCI_module);
while(1) // Poll the Flags register using flags() (0x06) until
{ // the CFG_mode flag is HIGH
//------------- Transmit ---------------
EUSCI_TXBuffer &= 0x00; // Clear Transmit Buffer
MAP_I2C_masterSendSingleByte(EUSCI_module,BQ27441_COMMAND_FLAGS);
//------------- Receive ----------------
NUM_OF_REC_BYTES = 2;
MAP_I2C_setMode(EUSCI_module, EUSCI_B_I2C_RECEIVE_MODE); // Set to Receive mode
MAP_I2C_masterReceiveStart(EUSCI_module); // Start Receiving
MAP_I2C_enableInterrupt(EUSCI_module, EUSCI_B_I2C_RECEIVE_INTERRUPT0); // Enable Receive Interrupt
xferIndex = 0; // Set RXData index to 0
while(rxFlag != 1); // Wait until receive interrupt flag is received
rxFlag = 0;
if(((RXData[0] & BQ27441_FLAG_CFGUPMODE) >> 4) == 0) break; // Check CFG mode flag
}
getStatus();
getFlags();
}
int FuelGauge_GetBatteryCap(void)
{
//------------- Transmit ---------------
EUSCI_TXBuffer &= 0x00;
MAP_I2C_masterSendSingleByte(EUSCI_module,0x08);
//------------- Receive ----------------
NUM_OF_REC_BYTES = 2;
MAP_I2C_setMode(EUSCI_module, EUSCI_B_I2C_RECEIVE_MODE); // Set to Receive mode
MAP_I2C_masterReceiveStart(EUSCI_module); // Start Receiving
MAP_I2C_enableInterrupt(EUSCI_module, EUSCI_B_I2C_RECEIVE_INTERRUPT0); // Enable Receive Interrupt
xferIndex = 0; // Set RXData index to 0
while(rxFlag != 1); // Wait until receive interrupt flag is received
rxFlag = 0;
//------------- Transmit ---------------
EUSCI_TXBuffer &= 0x00;
MAP_I2C_masterSendSingleByte(EUSCI_module,BQ27441_COMMAND_FULL_CAPACITY);
//------------- Receive ----------------
NUM_OF_REC_BYTES = 2;
MAP_I2C_setMode(EUSCI_module, EUSCI_B_I2C_RECEIVE_MODE); // Set to Receive mode
MAP_I2C_masterReceiveStart(EUSCI_module); // Start Receiving
MAP_I2C_enableInterrupt(EUSCI_module, EUSCI_B_I2C_RECEIVE_INTERRUPT0); // Enable Receive Interrupt
xferIndex = 0; // Set RXData index to 0
while(rxFlag != 1); // Wait until receive interrupt flag is received
rxFlag = 0;
uint8_t batCap_LSB = RXData[0];
uint16_t batCap_MSB = RXData[1];
uint16_t OUT = (batCap_MSB << 8) | batCap_LSB;
return OUT;
}
int FuelGauge_GetStateOfCharge(void)
{
//------------- Transmit ---------------
EUSCI_TXBuffer &= 0x00;
MAP_I2C_masterSendSingleByte(EUSCI_module,BQ27441_COMMAND_SOC);
//------------- Receive ----------------
NUM_OF_REC_BYTES = 2;
MAP_I2C_setMode(EUSCI_module, EUSCI_B_I2C_RECEIVE_MODE); // Set to Receive mode
MAP_I2C_masterReceiveStart(EUSCI_module); // Start Receiving
MAP_I2C_enableInterrupt(EUSCI_module, EUSCI_B_I2C_RECEIVE_INTERRUPT0); // Enable Receive Interrupt
xferIndex = 0; // Set RXData index to 0
while(rxFlag != 1); // Wait until receive interrupt flag is received
rxFlag = 0;
uint8_t charge_LSB = RXData[0];
uint16_t charge_MSB = RXData[1];
uint16_t OUT = (charge_MSB << 8) | charge_LSB;
return OUT;
}
int FuelGauge_GetVoltage(void)
{
//------------- Transmit ---------------
EUSCI_TXBuffer &= 0x00;
MAP_I2C_masterSendSingleByte(EUSCI_module,BQ27441_COMMAND_VOLTAGE);
//------------- Receive ----------------
NUM_OF_REC_BYTES = 2;
MAP_I2C_setMode(EUSCI_module, EUSCI_B_I2C_RECEIVE_MODE); // Set to Receive mode
MAP_I2C_masterReceiveStart(EUSCI_module); // Start Receiving
MAP_I2C_enableInterrupt(EUSCI_module, EUSCI_B_I2C_RECEIVE_INTERRUPT0); // Enable Receive Interrupt
xferIndex = 0; // Set RXData index to 0
while(rxFlag != 1); // Wait until receive interrupt flag is received
rxFlag = 0;
uint8_t voltage_LSB = RXData[0];
uint16_t voltage_MSB = RXData[1];
uint16_t OUT = (voltage_MSB << 8) | voltage_LSB;
return OUT;
}
void EUSCIB3_Receive(void)
{
uint_fast16_t status; // Flag status
status = MAP_I2C_getEnabledInterruptStatus(EUSCI_module); // Grab any flags that are triggered
MAP_I2C_clearInterruptFlag(EUSCI_module, status); // Clear interrupt flags that are triggered
if (status & EUSCI_B_I2C_RECEIVE_INTERRUPT0) // If the interrupt flag for receive has been triggered
{
if(NUM_OF_REC_BYTES > 1) // If number of receive bytes has been set to a value over 1
{
if(xferIndex == NUM_OF_REC_BYTES - 2) // When xferIndex is on the third to last byte
{
MAP_I2C_masterReceiveMultiByteStop(EUSCI_module);
RXData[xferIndex++] = MAP_I2C_masterReceiveMultiByteNext(EUSCI_module); // Receive and store byte into RXData
}
else if(xferIndex == NUM_OF_REC_BYTES - 1) // When xferIndex is on the second to last byte
{
RXData[xferIndex++] = MAP_I2C_masterReceiveMultiByteNext(EUSCI_module); // Receive and store byte into RXData
MAP_I2C_disableInterrupt(EUSCI_module, EUSCI_B_I2C_RECEIVE_INTERRUPT0); // Disable receive interrupt
MAP_I2C_setMode(EUSCI_module, EUSCI_B_I2C_TRANSMIT_MODE); // Set I2C mode to transmit
xferIndex = 0; // Clear the RXData index
rxFlag = 1; // Set receive interrupt flag high
NUM_OF_REC_BYTES = 0; // Clear NUM_OF_REC_BYTES
}
else // Executed until xferIndex is within 2 from the length of NUM_OF_REC_BYTES
{
RXData[xferIndex++] = MAP_I2C_masterReceiveMultiByteNext(EUSCI_module);
}
}
}
}