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); } } } }