/** * BQ25756 Driver — STM32 Standard Peripheral Library * I2C1: PB6(SCL), PB7(SDA), 400kHz * Reference: TI SLUSEN5 BQ25756 Datasheet (Aug 2023) * * CE: PA0 (adjust to your board) * INT: PB1 (adjust to your board) */ #include "bq25756.h" #include "stm32f10x.h" /*=========================================================================== * 引脚定义(按实际板子修改) *===========================================================================*/ #define CE_GPIO_PORT GPIOA #define CE_GPIO_PIN GPIO_Pin_0 #define CE_GPIO_CLK RCC_APB2Periph_GPIOA #define INT_GPIO_PORT GPIOB #define INT_GPIO_PIN GPIO_Pin_1 #define INT_GPIO_CLK RCC_APB2Periph_GPIOB #define INT_EXTI_LINE EXTI_Line1 #define INT_EXTI_PORT_SRC GPIO_PortSourceGPIOB #define INT_EXTI_PIN_SRC GPIO_PinSource1 #define INT_EXTI_IRQn EXTI1_IRQn #define I2Cx I2C1 #define I2C_GPIO_PORT GPIOB #define I2C_SCL_PIN GPIO_Pin_6 #define I2C_SDA_PIN GPIO_Pin_7 #define I2C_GPIO_CLK RCC_APB2Periph_GPIOB #define I2C_CLK RCC_APB1Periph_I2C1 #define I2C_SPEED 400000 /*=========================================================================== * 内部状态 *===========================================================================*/ BQ25756_State g_state = {0}; /*=========================================================================== * I2C 底层 — 等待标志位 *===========================================================================*/ static BQ25756_Status i2c_wait_flag(FlagStatus flag, uint32_t timeout_us) { while (timeout_us--) { if (I2C_GetFlagStatus(I2Cx, flag) == SET) return BQ25756_OK; uint32_t dly = 12; while (dly--) { __NOP(); } } return BQ25756_ERR_TIMEOUT; } static BQ25756_Status i2c_start(void) { I2C_GenerateSTART(I2Cx, ENABLE); return i2c_wait_flag(I2C_FLAG_SB, 10000); } static void i2c_stop(void) { I2C_GenerateSTOP(I2Cx, ENABLE); } static BQ25756_Status i2c_send_addr(uint8_t addr, uint8_t rw) { I2C_Send7bitAddress(I2Cx, addr, rw); if (rw == I2C_Direction_Transmitter) return i2c_wait_flag(I2C_FLAG_ADDR, 10000); BQ25756_Status ret = i2c_wait_flag(I2C_FLAG_ADDR, 10000); if (ret != BQ25756_OK) return ret; (void)I2Cx->SR1; (void)I2Cx->SR2; return BQ25756_OK; } static BQ25756_Status i2c_send_byte(uint8_t data) { I2C_SendData(I2Cx, data); return i2c_wait_flag(I2C_FLAG_TXE, 10000); } static BQ25756_Status i2c_wait_btf(void) { return i2c_wait_flag(I2C_FLAG_BTF, 10000); } static BQ25756_Status i2c_recv_byte(uint8_t *pdata, uint8_t ack) { if (ack) I2C_AcknowledgeConfig(I2Cx, ENABLE); else I2C_AcknowledgeConfig(I2Cx, DISABLE); BQ25756_Status ret = i2c_wait_flag(I2C_FLAG_RXNE, 10000); if (ret != BQ25756_OK) return ret; *pdata = I2C_ReceiveData(I2Cx); return BQ25756_OK; } /*=========================================================================== * I2C 初始化 *===========================================================================*/ void BQ25756_InitI2C(void) { GPIO_InitTypeDef gpio; I2C_InitTypeDef i2c; RCC_APB2PeriphClockCmd(I2C_GPIO_CLK | RCC_APB2Periph_AFIO, ENABLE); RCC_APB1PeriphClockCmd(I2C_CLK, ENABLE); GPIO_StructInit(&gpio); gpio.GPIO_Pin = I2C_SCL_PIN | I2C_SDA_PIN; gpio.GPIO_Speed = GPIO_Speed_10MHz; gpio.GPIO_Mode = GPIO_Mode_AF_OD; GPIO_Init(I2C_GPIO_PORT, &gpio); I2C_StructInit(&i2c); i2c.I2C_Mode = I2C_Mode_I2C; i2c.I2C_DutyCycle = I2C_DutyCycle_2; i2c.I2C_OwnAddress1 = 0x00; i2c.I2C_Ack = I2C_Ack_Enable; i2c.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit; i2c.I2C_ClockSpeed = I2C_SPEED; I2C_Init(I2Cx, &i2c); I2C_Cmd(I2Cx, ENABLE); } /*=========================================================================== * 检测 — REG0x3D Part_Info = 0x12 *===========================================================================*/ BQ25756_Status BQ25756_CheckPresence(void) { uint8_t part = 0; BQ25756_Status ret = BQ25756_ReadReg(BQ25756_REG_PART_INFO, &part); if (ret != BQ25756_OK) return ret; return (part == 0x12) ? BQ25756_OK : BQ25756_ERR_NACK; } /*=========================================================================== * I2C 寄存器读写 *===========================================================================*/ BQ25756_Status BQ25756_WriteReg(uint8_t reg, uint8_t data) { if (i2c_start() != BQ25756_OK) return BQ25756_ERR_I2C; if (i2c_send_addr(BQ25756_I2C_ADDR, I2C_Direction_Transmitter) != BQ25756_OK) return BQ25756_ERR_NACK; if (i2c_send_byte(reg) != BQ25756_OK) return BQ25756_ERR_I2C; if (i2c_send_byte(data) != BQ25756_OK) return BQ25756_ERR_I2C; i2c_stop(); return BQ25756_OK; } BQ25756_Status BQ25756_ReadReg(uint8_t reg, uint8_t *pdata) { if (!pdata) return BQ25756_ERR_BUSY; if (i2c_start() != BQ25756_OK) return BQ25756_ERR_I2C; if (i2c_send_addr(BQ25756_I2C_ADDR, I2C_Direction_Transmitter) != BQ25756_OK) return BQ25756_ERR_NACK; if (i2c_send_byte(reg) != BQ25756_OK) return BQ25756_ERR_I2C; if (i2c_wait_btf() != BQ25756_OK) return BQ25756_ERR_I2C; I2C_GenerateSTART(I2Cx, ENABLE); if (i2c_wait_flag(I2C_FLAG_SB, 10000) != BQ25756_OK) return BQ25756_ERR_TIMEOUT; if (i2c_send_addr(BQ25756_I2C_ADDR, I2C_Direction_Receiver) != BQ25756_OK) return BQ25756_ERR_NACK; if (i2c_recv_byte(pdata, 0) != BQ25756_OK) return BQ25756_ERR_I2C; i2c_stop(); return BQ25756_OK; } BQ25756_Status BQ25756_WriteReg16(uint8_t reg, uint16_t data) { uint8_t lo = (uint8_t)(data & 0xFF); uint8_t hi = (uint8_t)((data >> 8) & 0xFF); if (i2c_start() != BQ25756_OK) return BQ25756_ERR_I2C; if (i2c_send_addr(BQ25756_I2C_ADDR, I2C_Direction_Transmitter) != BQ25756_OK) return BQ25756_ERR_NACK; if (i2c_send_byte(reg) != BQ25756_OK) return BQ25756_ERR_I2C; if (i2c_send_byte(lo) != BQ25756_OK) return BQ25756_ERR_I2C; if (i2c_send_byte(hi) != BQ25756_OK) return BQ25756_ERR_I2C; i2c_stop(); return BQ25756_OK; } BQ25756_Status BQ25756_ReadReg16(uint8_t reg, uint16_t *pdata) { uint8_t lo, hi; if (!pdata) return BQ25756_ERR_BUSY; if (i2c_start() != BQ25756_OK) return BQ25756_ERR_I2C; if (i2c_send_addr(BQ25756_I2C_ADDR, I2C_Direction_Transmitter) != BQ25756_OK) return BQ25756_ERR_NACK; if (i2c_send_byte(reg) != BQ25756_OK) return BQ25756_ERR_I2C; if (i2c_wait_btf() != BQ25756_OK) return BQ25756_ERR_I2C; I2C_GenerateSTART(I2Cx, ENABLE); if (i2c_wait_flag(I2C_FLAG_SB, 10000) != BQ25756_OK) return BQ25756_ERR_TIMEOUT; if (i2c_send_addr(BQ25756_I2C_ADDR, I2C_Direction_Receiver) != BQ25756_OK) return BQ25756_ERR_NACK; if (i2c_recv_byte(&lo, 1) != BQ25756_OK) return BQ25756_ERR_I2C; if (i2c_recv_byte(&hi, 0) != BQ25756_OK) return BQ25756_ERR_I2C; i2c_stop(); *pdata = ((uint16_t)hi << 8) | lo; return BQ25756_OK; } /*=========================================================================== * 充电参数 *===========================================================================*/ BQ25756_Status BQ25756_ConfigChargeParams(uint32_t charge_current_ma, uint32_t input_current_ma, uint32_t input_voltage_mv) { BQ25756_Status ret; /* 充电电流 16-bit = (mA/50)<<2 */ ret = BQ25756_WriteReg16(BQ25756_REG_CHG_CURRENT, BQ25756_ICHG_RAW(charge_current_ma)); if (ret != BQ25756_OK) return ret; /* 输入电流限 */ ret = BQ25756_WriteReg16(BQ25756_REG_INPUT_CURRENT_DPM, BQ25756_IDPM_RAW(input_current_ma)); if (ret != BQ25756_OK) return ret; /* 输入电压 DPM */ return BQ25756_WriteReg16(BQ25756_REG_INPUT_VOLTAGE_DPM, BQ25756_VDPM_RAW(input_voltage_mv)); } /*=========================================================================== * 充电使能/禁用 + CE 脚控制 *===========================================================================*/ BQ25756_Status BQ25756_EnableCharging(void) { BQ25756_Status ret; uint8_t ctrl; ret = BQ25756_ReadReg(BQ25756_REG_CHARGER_CTRL, &ctrl); if (ret != BQ25756_OK) return ret; ctrl |= BQ25756_EN_CHG; ret = BQ25756_WriteReg(BQ25756_REG_CHARGER_CTRL, ctrl); if (ret != BQ25756_OK) return ret; GPIO_ResetBits(CE_GPIO_PORT, CE_GPIO_PIN); return BQ25756_OK; } BQ25756_Status BQ25756_DisableCharging(void) { BQ25756_Status ret; uint8_t ctrl; GPIO_SetBits(CE_GPIO_PORT, CE_GPIO_PIN); ret = BQ25756_ReadReg(BQ25756_REG_CHARGER_CTRL, &ctrl); if (ret != BQ25756_OK) return ret; ctrl &= ~BQ25756_EN_CHG; return BQ25756_WriteReg(BQ25756_REG_CHARGER_CTRL, ctrl); } BQ25756_Status BQ25756_SetCePin(uint8_t level) { if (level) GPIO_SetBits(CE_GPIO_PORT, CE_GPIO_PIN); else GPIO_ResetBits(CE_GPIO_PORT, CE_GPIO_PIN); return BQ25756_OK; } /*=========================================================================== * 看门狗 *===========================================================================*/ BQ25756_Status BQ25756_ResetWatchdog(void) { uint8_t ctrl; BQ25756_Status ret = BQ25756_ReadReg(BQ25756_REG_CHARGER_CTRL, &ctrl); if (ret != BQ25756_OK) return ret; ctrl |= BQ25756_WD_RST; return BQ25756_WriteReg(BQ25756_REG_CHARGER_CTRL, ctrl); } BQ25756_Status BQ25756_DisableWatchdog(void) { return BQ25756_WriteReg(BQ25756_REG_TIMER_CTRL, 0x0D); } /*=========================================================================== * 预充/终止 *===========================================================================*/ BQ25756_Status BQ25756_SetPrechargeCurrent(uint32_t ma) { return BQ25756_WriteReg16(BQ25756_REG_PRECHG_CURRENT, (uint16_t)((ma / 50) << 2)); } BQ25756_Status BQ25756_SetTerminationCurrent(uint32_t ma) { return BQ25756_WriteReg16(BQ25756_REG_TERM_CURRENT, (uint16_t)((ma / 50) << 2)); } BQ25756_Status BQ25756_ConfigPrechargeTerm(uint8_t en_term, uint8_t vbat_lowv, uint8_t en_prechg) { uint8_t val = 0; if (en_term) val |= BQ25756_EN_TERM; val |= (vbat_lowv << 1) & BQ25756_VBAT_LOWV_MASK; if (en_prechg) val |= BQ25756_EN_PRECHG; return BQ25756_WriteReg(BQ25756_REG_PRECHG_TERM_CTRL, val); } /*=========================================================================== * 定时器 *===========================================================================*/ BQ25756_Status BQ25756_ConfigTimers(uint8_t watchdog, uint8_t chg_tmr, uint8_t cv_tmr, uint8_t topoff) { uint8_t val = 0; val |= (topoff << 6) & BQ25756_TOPOFF_MASK; val |= (watchdog << 4) & BQ25756_WD_MASK; val |= BQ25756_EN_CHG_TMR; val |= (chg_tmr << 1) & BQ25756_CHG_TMR_MASK; BQ25756_Status ret = BQ25756_WriteReg(BQ25756_REG_TIMER_CTRL, val); if (ret != BQ25756_OK) return ret; return BQ25756_WriteReg(BQ25756_REG_THREE_STAGE_CHG, cv_tmr & 0x0F); } /*=========================================================================== * 状态监测 *===========================================================================*/ BQ25756_Status BQ25756_GetChargeState(uint8_t *pstate) { return BQ25756_ReadReg(BQ25756_REG_CHARGER_STATUS_1, pstate); } BQ25756_Status BQ25756_GetFaultStatus(uint8_t *pfault) { return BQ25756_ReadReg(BQ25756_REG_FAULT_STATUS, pfault); } BQ25756_Status BQ25756_ReadPowerGood(uint8_t *ppg) { uint8_t stat2 = 0; BQ25756_Status ret = BQ25756_ReadReg(BQ25756_REG_CHARGER_STATUS_2, &stat2); if (ret != BQ25756_OK) return ret; *ppg = (stat2 & BQ25756_STAT2_PG) ? 1 : 0; return BQ25756_OK; } BQ25756_Status BQ25756_ReadFlags1(uint8_t *pflags) { return BQ25756_ReadReg(BQ25756_REG_FLAG_1, pflags); } BQ25756_Status BQ25756_ReadFlags2(uint8_t *pflags) { return BQ25756_ReadReg(BQ25756_REG_FLAG_2, pflags); } BQ25756_Status BQ25756_ReadFaultFlags(uint8_t *pflags) { return BQ25756_ReadReg(BQ25756_REG_FAULT_FLAG, pflags); } BQ25756_Status BQ25756_ConfigMasks(uint8_t mask1, uint8_t mask2, uint8_t fault_mask) { BQ25756_Status ret; ret = BQ25756_WriteReg(BQ25756_REG_MASK_1, mask1); if (ret != BQ25756_OK) return ret; ret = BQ25756_WriteReg(BQ25756_REG_MASK_2, mask2); if (ret != BQ25756_OK) return ret; return BQ25756_WriteReg(BQ25756_REG_FAULT_MASK, fault_mask); } /*=========================================================================== * 状态汇总 — 一次调用读取全部关键状态 *===========================================================================*/ BQ25756_Status BQ25756_GetStatusSummary(BQ25756_StatusSummary *ps) { if (!ps) return BQ25756_ERR_BUSY; uint8_t stat1, stat2, fault; uint32_t vbat, vin; int32_t ibat; BQ25756_Status ret; ret = BQ25756_ReadReg(BQ25756_REG_CHARGER_STATUS_1, &stat1); if (ret != BQ25756_OK) return ret; ret = BQ25756_ReadReg(BQ25756_REG_CHARGER_STATUS_2, &stat2); if (ret != BQ25756_OK) return ret; ret = BQ25756_ReadReg(BQ25756_REG_FAULT_STATUS, &fault); if (ret != BQ25756_OK) return ret; ret = BQ25756_AdcOneshot(); if (ret != BQ25756_OK) return ret; ret = BQ25756_ReadVbat(&vbat); if (ret != BQ25756_OK) return ret; ret = BQ25756_ReadIbat(&ibat); if (ret != BQ25756_OK) return ret; ret = BQ25756_ReadVac(&vin); if (ret != BQ25756_OK) return ret; ps->charge_state = stat1 & BQ25756_STAT_CHRG_STATE_MASK; ps->fault = fault; ps->pg_good = (stat2 & BQ25756_STAT2_PG) ? 1 : 0; ps->ts_status = (stat2 & BQ25756_STAT2_TS_MASK) >> 4; ps->wd_expired = (stat1 & BQ25756_STAT_WD_EXPIRED) ? 1 : 0; ps->mppt_status = stat2 & BQ25756_STAT2_MPPT_MASK; ps->vbat_mv = (uint16_t)vbat; ps->ibat_ma = (int16_t)ibat; ps->vin_mv = (uint16_t)vin; ps->vfb_mv = 0; g_state.charger_status = stat1; g_state.fault_status = fault; g_state.vbat_mv = (uint16_t)vbat; g_state.ibat_ma = (int16_t)ibat; return BQ25756_OK; } /*=========================================================================== * 引脚/通道配置 *===========================================================================*/ BQ25756_Status BQ25756_ConfigPins(uint8_t en_ichg, uint8_t en_ilim, uint8_t dis_pg, uint8_t dis_stat) { uint8_t val = 0; if (en_ichg) val |= BQ25756_EN_ICHG_PIN; if (en_ilim) val |= BQ25756_EN_ILIM_HIZ_PIN; if (dis_pg) val |= BQ25756_DIS_PG_PIN; if (dis_stat) val |= BQ25756_DIS_STAT_PINS; return BQ25756_WriteReg(BQ25756_REG_PIN_CTRL, val); } BQ25756_Status BQ25756_ConfigAdcChannels(uint8_t disable_mask) { return BQ25756_WriteReg(BQ25756_REG_ADC_CHANNEL_CTRL, disable_mask); } /*=========================================================================== * ADC *===========================================================================*/ BQ25756_Status BQ25756_AdcOneshot(void) { BQ25756_Status ret; /* 先写复位值再写使能 */ ret = BQ25756_WriteReg(BQ25756_REG_ADC_CTRL, 0x60); if (ret != BQ25756_OK) return ret; ret = BQ25756_WriteReg(BQ25756_REG_ADC_CTRL, 0xE0); if (ret != BQ25756_OK) return ret; uint32_t wait = 200000; while (wait--) { uint8_t check; BQ25756_ReadReg(BQ25756_REG_ADC_CTRL, &check); if ((check & BQ25756_ADC_EN) == 0) return BQ25756_OK; uint32_t dly = 12; while (dly--) { __NOP(); } } return BQ25756_ERR_TIMEOUT; } BQ25756_Status BQ25756_AdcStartContinuous(void) { return BQ25756_WriteReg(BQ25756_REG_ADC_CTRL, 0xA0); } BQ25756_Status BQ25756_AdcStop(void) { return BQ25756_WriteReg(BQ25756_REG_ADC_CTRL, 0x60); } BQ25756_Status BQ25756_ReadVbat(uint32_t *pvoltage_mv) { uint16_t raw; BQ25756_Status ret = BQ25756_ReadReg16(BQ25756_REG_VBAT_ADC, &raw); if (ret != BQ25756_OK) return ret; *pvoltage_mv = BQ25756_VBAT_ADC_MV(raw); g_state.vbat_mv = (uint16_t)*pvoltage_mv; return BQ25756_OK; } BQ25756_Status BQ25756_ReadIbat(int32_t *pcurrent_ma) { uint16_t raw; BQ25756_Status ret = BQ25756_ReadReg16(BQ25756_REG_IBAT_ADC, &raw); if (ret != BQ25756_OK) return ret; *pcurrent_ma = BQ25756_IBAT_ADC_MA(raw); g_state.ibat_ma = (int16_t)*pcurrent_ma; return BQ25756_OK; } BQ25756_Status BQ25756_ReadVac(uint32_t *pvoltage_mv) { uint16_t raw; BQ25756_Status ret = BQ25756_ReadReg16(BQ25756_REG_VAC_ADC, &raw); if (ret != BQ25756_OK) return ret; *pvoltage_mv = BQ25756_VAC_ADC_MV(raw); return BQ25756_OK; } BQ25756_Status BQ25756_ReadVfb(uint32_t *pvoltage_mv) { uint16_t raw; BQ25756_Status ret = BQ25756_ReadReg16(BQ25756_REG_VFB_ADC, &raw); if (ret != BQ25756_OK) return ret; *pvoltage_mv = BQ25756_VFB_ADC_MV(raw); return BQ25756_OK; } BQ25756_Status BQ25756_ReadAllAdc(BQ25756_State *pstate) { BQ25756_Status ret = BQ25756_AdcOneshot(); if (ret != BQ25756_OK) return ret; uint32_t vbat, vac; int32_t ibat; ret = BQ25756_ReadVbat(&vbat); if (ret != BQ25756_OK) return ret; ret = BQ25756_ReadIbat(&ibat); if (ret != BQ25756_OK) return ret; ret = BQ25756_ReadVac(&vac); if (ret != BQ25756_OK) return ret; if (pstate) *pstate = g_state; return BQ25756_OK; } /*=========================================================================== * NTC / JEITA *===========================================================================*/ BQ25756_Status BQ25756_DisableNtc(void) { uint8_t ts; BQ25756_Status ret = BQ25756_ReadReg(BQ25756_REG_TS_REGION_BEHAVIOR, &ts); if (ret != BQ25756_OK) return ret; ts &= ~BQ25756_EN_TS; return BQ25756_WriteReg(BQ25756_REG_TS_REGION_BEHAVIOR, ts); } BQ25756_Status BQ25756_EnableNtc(void) { uint8_t ts; BQ25756_Status ret = BQ25756_ReadReg(BQ25756_REG_TS_REGION_BEHAVIOR, &ts); if (ret != BQ25756_OK) return ret; ts |= BQ25756_EN_TS; return BQ25756_WriteReg(BQ25756_REG_TS_REGION_BEHAVIOR, ts); } BQ25756_Status BQ25756_ConfigJeita(uint8_t en_jeita, uint8_t vset, uint8_t iseth, uint8_t isetc) { uint8_t val = 0; static const uint8_t vset_map[4] = {0, 0x20, 0x40, 0x60}; static const uint8_t isetc_map[4] = {0, 0x04, 0x08, 0x0C}; if (vset < 4) val |= vset_map[vset]; if (iseth) val |= BQ25756_JEITA_ISETH; if (isetc < 4) val |= isetc_map[isetc]; if (en_jeita) val |= BQ25756_EN_JEITA; val |= BQ25756_EN_TS; return BQ25756_WriteReg(BQ25756_REG_TS_REGION_BEHAVIOR, val); } BQ25756_Status BQ25756_ConfigNtcThresholds(uint8_t t1, uint8_t t2, uint8_t t3, uint8_t t5) { static const uint8_t t1_map[4] = {0x00, 0x01, 0x02, 0x03}; static const uint8_t t2_map[4] = {0x00, 0x04, 0x08, 0x0C}; static const uint8_t t3_map[4] = {0x00, 0x10, 0x20, 0x30}; static const uint8_t t5_map[4] = {0x00, 0x40, 0x80, 0xC0}; uint8_t val = 0; if (t1 < 4) val |= t1_map[t1]; if (t2 < 4) val |= t2_map[t2]; if (t3 < 4) val |= t3_map[t3]; if (t5 < 4) val |= t5_map[t5]; return BQ25756_WriteReg(BQ25756_REG_TS_THRESHOLD, val); } /*=========================================================================== * MPPT *===========================================================================*/ BQ25756_Status BQ25756_EnableMppt(void) { uint8_t mppt; BQ25756_Status ret = BQ25756_ReadReg(BQ25756_REG_MPPT_CTRL, &mppt); if (ret != BQ25756_OK) return ret; mppt |= BQ25756_EN_MPPT; return BQ25756_WriteReg(BQ25756_REG_MPPT_CTRL, mppt); } BQ25756_Status BQ25756_DisableMppt(void) { uint8_t mppt; BQ25756_Status ret = BQ25756_ReadReg(BQ25756_REG_MPPT_CTRL, &mppt); if (ret != BQ25756_OK) return ret; mppt &= ~BQ25756_EN_MPPT; return BQ25756_WriteReg(BQ25756_REG_MPPT_CTRL, mppt); } BQ25756_Status BQ25756_MpptForceSweep(void) { uint8_t mppt; BQ25756_Status ret = BQ25756_ReadReg(BQ25756_REG_MPPT_CTRL, &mppt); if (ret != BQ25756_OK) return ret; mppt |= BQ25756_FORCE_SWEEP; return BQ25756_WriteReg(BQ25756_REG_MPPT_CTRL, mppt); } /*=========================================================================== * 中断 *===========================================================================*/ void BQ25756_InitInterrupt(void) { GPIO_InitTypeDef gpio; EXTI_InitTypeDef exti; NVIC_InitTypeDef nvic; RCC_APB2PeriphClockCmd(INT_GPIO_CLK | RCC_APB2Periph_AFIO, ENABLE); GPIO_StructInit(&gpio); gpio.GPIO_Pin = INT_GPIO_PIN; gpio.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(INT_GPIO_PORT, &gpio); GPIO_EXTILineConfig(INT_EXTI_PORT_SRC, INT_EXTI_PIN_SRC); EXTI_StructInit(&exti); exti.EXTI_Line = INT_EXTI_LINE; exti.EXTI_Mode = EXTI_Mode_Interrupt; exti.EXTI_Trigger = EXTI_Trigger_Falling; exti.EXTI_LineCmd = ENABLE; EXTI_Init(&exti); NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); nvic.NVIC_IRQChannel = INT_EXTI_IRQn; nvic.NVIC_IRQChannelPreemptionPriority = 1; nvic.NVIC_IRQChannelSubPriority = 0; nvic.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&nvic); } void BQ25756_IRQHandler(void) { if (EXTI_GetITStatus(INT_EXTI_LINE) != RESET) { uint8_t status, fault; BQ25756_GetChargeState(&status); BQ25756_GetFaultStatus(&fault); g_state.charger_status = status; g_state.fault_status = fault; /* 可选:读出并丢弃标志寄存器以清除INT */ uint8_t flags; BQ25756_ReadReg(BQ25756_REG_FLAG_1, &flags); EXTI_ClearITPendingBit(INT_EXTI_LINE); } } /*=========================================================================== * 完整初始化 — 关看门狗→关NTC→设参数→启ADC *===========================================================================*/ BQ25756_Status BQ25756_InitForCharging(uint32_t charge_ma, uint32_t input_ma, uint32_t input_mv) { BQ25756_Status ret; ret = BQ25756_DisableWatchdog(); if (ret != BQ25756_OK) return ret; ret = BQ25756_DisableNtc(); if (ret != BQ25756_OK) return ret; ret = BQ25756_ConfigChargeParams(charge_ma, input_ma, input_mv); if (ret != BQ25756_OK) return ret; return BQ25756_AdcStartContinuous(); }