ZHDA116 April 2026 BQ25856-Q1





int main(void) {
SYSCFG_DL_init(); // Initialize the I2C and the timer via SuperCapHealth.sysconfig
__NVIC_EnableIRQ(I2C_0_INST_INT_IRQN); // Initialize the I2C interrupt routine for I2C communication
__NVIC_EnableIRQ(TIMER_0_INST_INT_IRQN); // Initialize the timer interrupt routine.
timer_exp = 0; // Initialize the timer flag.
// I2C Settings
uint8_t DIS_WD[1] = {0x05}; // Disable Watchdog timer
uint8_t EN_CHG[1] = {0xC9}; // 0x09 for BQ25858-Q1
uint8_t DIS_CHG[1] = {0xC8}; // 0x08 for BQ25858-Q1
uint8_t DIS_PRECHG[1] = {0x06}; // Disable Precharge and Termination
uint8_t EN_ADC[1] = {0xE0}; // One shot conversion mode to control when ADC Reads
uint8_t VOUT_ADC[1] = {0xEF}; // Set only the VOUT ADC to read (shortens conversion time)
uint8_t DIS_INT_MASK[3] = {0x7F, 0xFF, 0xFF}; // Set only the ADC interrupt for the best results
// Current Parameter
uint8_t CHG_CURRENT[2] = {0x50, 0x00}; // 1 A IOUT setting
volatile uint16_t ICHG = 0x0000; // 16 bit variable for charge current volatile
double_t current_conv = 0.05; // 50 mA per bit on BQ2585X-Q1 Register
volatile double_t current = 0.0; // Current value for ESR and CAP calculations
// Determine Charge Current in AMPERES
ICHG = (((uint16_t)CHG_CURRENT[1] << 8) | (uint16_t)CHG_CURRENT[0]) >> 2;
current = (double_t)ICHG * current_conv;
// Voltage Parameter
uint8_t VBAT[2] = {0x00, 0x00};
// Variable to read ADC Conversion
volatile unsigned int adc_result0 = 0; // 16 bit variable for ADC Conversion result
volatile unsigned int adc_result1 = 0;
volatile unsigned int adc_result2 = 0;
volatile double_t volt_conv = 0.002; // 2 mV per bit on BQ2585X-Q1 ADC
volatile double_t voltage0 = 0; // Voltage value for ESR and CAP calculations
volatile double_t voltage1 = 0;
volatile double_t voltage2 = 0;
// Time parameter
volatile double_t charge_time = 1.0; // 1000 ms charge time
//Results
volatile double_t ESR = 0.0; // ESR Result
volatile double_t CAP = 0.0; // Capacitance result
// Disable Watchdog to avoid registers being overwritten
I2C_Write(BQ2585X_TIMER_CONTROL, DIS_WD, 1);
// Disable Charge to set proper settings
I2C_Write(BQ2585X_CHARGER_CONTROL, DIS_CHG, 1);
// Set 1 A IOUT for measurement calculations
I2C_Write(BQ2585X_CHARGE_CURRENT_LIMIT_LSB, CHG_CURRENT, 2);
// Disable Precharge and Termination
I2C_Write(BQ2585X_PRECHARGE_AND_TERMINATION_CONTROL, DIS_PRECHG, 1);
// Set only VOUT_ADC for best operation
I2C_Write(BQ2585X_ADC_CHANNEL_CONTROL, VOUT_ADC, 1);
// Set only ADC interrupts for best operation
I2C_Write(BQ2585X_MASK_1, DIS_INT_MASK, 3);
while (1) {
// Enable the charge sequence
I2C_Write(BQ2585X_CHARGER_CONTROL, EN_CHG, 1);
// Start timer to remove EN_CHG delay
DL_TimerG_startCounter(TIMER_0_INST);
// Wait for the 1 s timer to finish
while (!timer_exp);
// Reset timer flag for next timer cycle
timer_exp = 0;
// Perform ADC conversion for initial voltage
I2C_Write(BQ2585X_ADC_CONTROL, EN_ADC, 1);
// Wait for ADC conversion to finish
while (DL_GPIO_readPins(BQ_INT_PORT, BQ_INT_PIN_0_PIN));
// Read ADC conversion results
I2C_Read(BQ2585X_VBAT_ADC_LSB, VBAT, 2);
// Store ADC conversion results for later calculations
adc_result0 = (VBAT[1] << 8) | (VBAT[0]);
// Start the timer
DL_TimerG_startCounter(TIMER_0_INST);
// Wait for the 1 s timer to finish
while (!timer_exp);
// Perform ADC conversion for max voltage
I2C_Write(BQ2585X_ADC_CONTROL, EN_ADC, 1);
// Wait for ADC conversion to finish
while (DL_GPIO_readPins(BQ_INT_PORT, BQ_INT_PIN_0_PIN));
// Disable charge
I2C_Write(BQ2585X_CHARGER_CONTROL, DIS_CHG, 1);
// Read ADC conversion results
I2C_Read(BQ2585X_VBAT_ADC_LSB, VBAT, 2);
// Store ADC conversion results for later calculations
adc_result1 = (VBAT[1] << 8) | VBAT[0];
// Reset timer flag for next timer cycle
timer_exp = 0;
// Start timer to let output voltage settle
DL_TimerG_startCounter(TIMER_0_INST);
// Wait for the 1 s timer to finish
while (!timer_exp);
// Reset timer flag for next timer cycle
timer_exp = 0;
// Perform ADC conversion for final voltage
I2C_Write(BQ2585X_ADC_CONTROL, EN_ADC, 1);
// Wait for ADC conversion to finish
while (DL_GPIO_readPins(BQ_INT_PORT, BQ_INT_PIN_0_PIN));
// Read ADC conversion results
I2C_Read(BQ2585X_VBAT_ADC_LSB, VBAT, 2);
// Store ADC conversion results for later calculations
adc_result2 = (VBAT[1] << 8) | (VBAT[0]);
// Convert ADC values to a voltage
voltage0 = (double_t)adc_result0 * volt_conv;
voltage1 = (double_t)adc_result1 * volt_conv;
voltage2 = (double_t)adc_result2 * volt_conv;
// Calculations for Capacitance and ESR
CAP = (current * charge_time) / (voltage1 - voltage0);
ESR = (voltage1 - voltage2) / current;
}
}