/** * main.c — BQ25756 Charging Demo (STM32F103VE, StdPeriph) * * Hardware setup: * I2C1: PB6(SCL), PB7(SDA) — BQ25756 * CE: PA0 (output, LOW = enable charging) * INT: PB1 (input, EXTI1 falling edge) * USART1: PA9(TX), PA10(RX) — 115200 baud (for debug prints) * * Demo: 1S Li-ion battery, 5V USB input * Charge voltage: 4200mV (4.2V) * Charge current: 1000mA (1A) * Input current limit: 2000mA (2A) * Input voltage DPM: 5000mV (5V) * * Build: Keil MDK or any StdPeriph toolchain * Add stm32f10x_gpio.c, stm32f10x_i2c.c, stm32f10x_usart.c, * stm32f10x_rcc.c, stm32f10x_exti.c, misc.c */ #include "stm32f10x.h" #include "bq25756.h" #include /*=========================================================================== * Debug UART (USART1, 115200 8N1) *===========================================================================*/ static void USART1_Init(void) { GPIO_InitTypeDef gpio; USART_InitTypeDef usart; RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE); /* PA9 = TX (AF PP), PA10 = RX (input floating) */ GPIO_StructInit(&gpio); gpio.GPIO_Pin = GPIO_Pin_9; gpio.GPIO_Speed = GPIO_Speed_50MHz; gpio.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_Init(GPIOA, &gpio); GPIO_StructInit(&gpio); gpio.GPIO_Pin = GPIO_Pin_10; gpio.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOA, &gpio); USART_StructInit(&usart); usart.USART_BaudRate = 115200; usart.USART_WordLength = USART_WordLength_8b; usart.USART_StopBits = USART_StopBits_1; usart.USART_Parity = USART_Parity_No; usart.USART_HardwareFlowControl = USART_HardwareFlowControl_None; usart.USART_Mode = USART_Mode_Tx | USART_Mode_Rx; USART_Init(USART1, &usart); USART_Cmd(USART1, ENABLE); } /* Redirect printf to USART1 */ int fputc(int ch, FILE *f) { while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET); USART_SendData(USART1, (uint8_t)ch); return ch; } /*=========================================================================== * Delay (rough millisecond using SysTick) *===========================================================================*/ static volatile uint32_t g_ms_ticks = 0; void SysTick_Handler(void) { g_ms_ticks++; } static void delay_init(void) { /* SysTick at 1ms */ if (SysTick_Config(SystemCoreClock / 1000)) { while (1); /* configuration failed */ } } static void delay_ms(uint32_t ms) { uint32_t start = g_ms_ticks; while ((g_ms_ticks - start) < ms); } /*=========================================================================== * CE pin init (active LOW) *===========================================================================*/ static void CE_GPIO_Init(void) { GPIO_InitTypeDef gpio; RCC_APB2PeriphClockCmd(CE_GPIO_CLK, ENABLE); GPIO_StructInit(&gpio); gpio.GPIO_Pin = CE_GPIO_PIN; gpio.GPIO_Speed = GPIO_Speed_10MHz; gpio.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(CE_GPIO_PORT, &gpio); /* Start with CE HIGH (charging disabled) */ GPIO_SetBits(CE_GPIO_PORT, CE_GPIO_PIN); } /*=========================================================================== * Status string helper *===========================================================================*/ static const char* charge_state_str(uint8_t status) { uint8_t state = status & BQ25756_STAT_CHRG_STATE_MASK; switch (state) { case BQ25756_STAT_NO_CHARGE: return "No Charge"; case BQ25756_STAT_TRICKLE_CHARGE: return "Trickle"; case BQ25756_STAT_PRECHARGE: return "Pre-charge"; case BQ25756_STAT_FAST_CHARGE_CC: return "Fast CC"; case BQ25756_STAT_FAST_CHARGE_CV: return "Fast CV"; case BQ25756_STAT_TOPOFF: return "Top-off"; case BQ25756_STAT_CHARGE_DONE: return "Done!"; default: return "Unknown"; } } /*=========================================================================== * Main *===========================================================================*/ int main(void) { BQ25756_Status ret; /* System init */ delay_init(); USART1_Init(); CE_GPIO_Init(); printf("\r\n\r\n=== BQ25756 Charging Demo ===\r\n"); printf("Target: 1S Li-ion (4.2V, 1A), USB 5V input\r\n\r\n"); /* 1. Init I2C */ BQ25756_InitI2C(); printf("[OK] I2C1 initialized (400kHz)\r\n"); /* 2. Check presence */ ret = BQ25756_CheckPresence(); if (ret != BQ25756_OK) { printf("[FAIL] BQ25756 not found! Check wiring.\r\n"); while (1); /* hang */ } printf("[OK] BQ25756 detected (PartInfo = 0x01)\r\n"); /* 3. Disable NTC (no thermistor on demo board) */ ret = BQ25756_DisableNtc(); if (ret != BQ25756_OK) { printf("[WARN] Failed to disable NTC\r\n"); } else { printf("[OK] NTC monitoring disabled\r\n"); } /* 4. Configure charging parameters */ ret = BQ25756_ConfigChargeParams(4200, /* 4.2V */ 1000, /* 1A */ 2000, /* 2A input limit */ 5000); /* 5V input DPM */ if (ret != BQ25756_OK) { printf("[FAIL] Failed to set charge params\r\n"); while (1); } printf("[OK] Charge parameters configured\r\n"); /* 5. Enable charging */ ret = BQ25756_EnableCharging(); if (ret != BQ25756_OK) { printf("[FAIL] Failed to enable charging\r\n"); while (1); } printf("[OK] Charging enabled (CE=LOW)\r\n\r\n"); /* 6. Main loop: monitor every 2 seconds */ while (1) { uint8_t status; uint8_t fault; uint32_t vbat_mv, vac_mv; int32_t ibat_ma; /* Read charge status */ BQ25756_GetChargeState(&status); BQ25756_GetFaultStatus(&fault); /* ADC one-shot + read */ BQ25756_ReadAllAdc(NULL); /* Get readings from state */ vbat_mv = (uint32_t)g_state.vbat_mv; ibat_ma = g_state.ibat_ma; /* Also read input voltage */ BQ25756_ReadVac(&vac_mv); /* Print status */ printf("[%lu ms] ", g_ms_ticks); printf("State=%s ", charge_state_str(status)); printf("VBAT=%lumV ", vbat_mv); printf("IBAT=%+dmA ", ibat_ma); printf("VIN=%lumV ", vac_mv); if (fault) { printf("FAULT: "); if (fault & BQ25756_FAULT_VAC_UV) printf("VAC_UV "); if (fault & BQ25756_FAULT_VAC_OV) printf("VAC_OV "); if (fault & BQ25756_FAULT_VBAT_OVP) printf("VBAT_OVP "); if (fault & BQ25756_FAULT_IBAT_OCP) printf("IBAT_OCP "); if (fault & BQ25756_FAULT_TSHUT) printf("TSHUT "); if (fault & BQ25756_FAULT_CHG_TMR) printf("TIMER "); if (fault & BQ25756_FAULT_DRV_OKZ) printf("DRV_SUP "); } printf("\r\n"); /* Reset watchdog to prevent timeout */ BQ25756_ResetWatchdog(); delay_ms(2000); } }