600字范文,内容丰富有趣,生活中的好帮手!
600字范文 > 电源管理芯片MAX17048驱动

电源管理芯片MAX17048驱动

时间:2024-04-16 16:13:11

相关推荐

电源管理芯片MAX17048驱动

电源管理芯片MAX17048驱动

芯片功能电路配置代码关于电量补偿

最近调试MAX17048,做个简单的记录。

基于STM32H743

芯片功能

MAX17048为小尺寸、微功耗电池电量计,用于手持及便携产品的锂离子(Li+)电池。

MAX17048配置工作在单节锂电池,MAX17049配置工作在2节串联锂电池,两者都是标准I2C接口通讯。

电路

配置

打开图形化配置工具Cubemax,选择快速模式以支持400Khz,7Bit地址,开启中断,GPIO上拉

代码

/*** @file Voltameter_Port.c** @date -03-04** @author aron566** @copyright Copyright (c) aron566 <aron566@>.** @brief 电池电量监控接口** @details 1、SCL RISE MIN KEEP 20ns* 2、SCL FALL MIN KEEP 20ns* 3、写: S. SAddr W. A. MAddr. A. Data0. A. Data1. A. P* 4、读: 先写S. SAddr W. A. MAddr. A 再读 Sr. SAddr R. A. Data0. A. Data1. N. P* 5、使用Fastmode 最高速率400Khz** @version V1.0*/#ifdef __cplusplus ///<use C compilerextern "C" {#endif/** Includes -----------------------------------------------------------------*//* Private includes ----------------------------------------------------------*/#include "main.h"#include "Voltameter_Port.h"/** Private typedef ----------------------------------------------------------*//** Private macros -----------------------------------------------------------*/#define ENABLE_MAX17048_DEBUG 0/**< 启动打印调试*//*MAX17048设备I2C地址*/#define DEV_ADDR0x6C/*MAX17048设备I2C写操作地址*/#define DEV_ADDR_WRITE(DEV_ADDR|0x00)/*MAX17048设备I2C读操作地址*/#define DEV_ADDR_READ (DEV_ADDR|0x01)/*MAX17048寄存器地址*/#define REG_V_CELL 0x02#define REG_SOC 0x04#define REG_MODE0x06#define REG_VERSION 0x08#define REG_HIBRT0x0A#define REG_CONFIG 0x0C#define REG_VALRT0x14#define REG_CRATE0x16#define REG_V_RESET 0x18#define REG_STATUS 0x1A#define REG_TABLE0x40/**< REG RANGE:0x40 to 0x70*/#define REG_TABLE_END 0x70#define REG_CMD 0xFE/*16BIT位*/ #define REG_BIT0(1U<<0)#define REG_BIT1(1U<<1)#define REG_BIT2(1U<<2)#define REG_BIT3(1U<<3)#define REG_BIT4(1U<<4)#define REG_BIT5(1U<<5)#define REG_BIT6(1U<<6)#define REG_BIT7(1U<<7)#define REG_BIT8(1U<<8)#define REG_BIT9(1U<<9)#define REG_BIT10(1U<<10)#define REG_BIT11(1U<<11)#define REG_BIT12(1U<<12)#define REG_BIT13(1U<<13)#define REG_BIT14(1U<<14)#define REG_BIT15(1U<<15)/** Private constants --------------------------------------------------------*//** Public variables ---------------------------------------------------------*/extern I2C_HandleTypeDef hi2c1;/** Private variables --------------------------------------------------------*/static uint16_t Battery_Soc = 0;/**< 电池电量百分比*/static uint16_t Battery_Voltage = 0;/**< 电池电压*/static uint8_t Send_Val_Buf[2];static uint8_t Reg_Val_Buf[2];/** Private function prototypes ----------------------------------------------*/#if ENABLE_MAX17048_DEBUGstatic void Display_Alarm_Info(uint8_t Alarm_Value);#endifstatic void I2C_State_Reset(void);static void Power_On_Reset(void);static uint16_t Read_Vcell_Update(uint32_t Block_Time);static uint16_t Read_Soc_Update(uint32_t Block_Time);/** Private user code --------------------------------------------------------*//** Private application code -------------------------------------------------*//********************************************************************************* Static code**********************************************************************************//********************************************************************* @brief I2C 异常状态恢复* @param [in]None.* @return None.* @author aron566* @version V1.0* @date -03-09*******************************************************************/static inline void I2C_State_Reset(void){__HAL_I2C_DISABLE(&hi2c1);HAL_Delay(1);__HAL_I2C_ENABLE(&hi2c1);}/********************************************************************* @brief MAX17048 报警信息打印* @param [in]None.* @return None.* @author aron566* @version V1.0* @date -03-08*******************************************************************/#if ENABLE_MAX17048_DEBUGstatic void Display_Alarm_Info(uint8_t Alarm_Value){if(Alarm_Value & REG_BIT0){printf("POWER ON IC NO CONFIG.\r\n");}if(Alarm_Value & REG_BIT1){printf("VCELL HIGH THAN ALRT.VALRTMAX.\r\n");}if(Alarm_Value & REG_BIT2){printf("VCELL LOW THAN ALRT.VALRTMIN.\r\n");}if(Alarm_Value & REG_BIT3){printf("VOLTAGE RESET.\r\n");}if(Alarm_Value & REG_BIT4){printf("SOC LOW THAN CONFIG.ATHD.\r\n");}if(Alarm_Value & REG_BIT5){printf("SOC CHANGE VALUE ARRIVE %%1.\r\n");}if(Alarm_Value & REG_BIT6){printf("ENABLE VOLTAGE RESET ALARM.\r\n");}}#endif/********************************************************************* @brief MAX17048 上电复位* @param [in]None.* @return None.* @author aron566* @version V1.0* @date -03-08*******************************************************************/static void Power_On_Reset(void){/*复位上电*/uint8_t WriteData[3] = {REG_CMD, 0x54, 0x00};HAL_I2C_Master_Transmit(&hi2c1, DEV_ADDR_WRITE, WriteData, 3, 100);/*Wait*/HAL_Delay(100);/*快速启动*/WriteData[0] = REG_MODE;WriteData[1] = 0x00;WriteData[2] |= REG_BIT6;/*使能休眠模式*/WriteData[2] |= REG_BIT5;HAL_I2C_Master_Transmit(&hi2c1, DEV_ADDR_WRITE, WriteData, 3, 100);}/********************************************************************* @brief 清除MAX17048 报警状态* @param [in]None.* @return None.* @author aron566* @version V1.0* @date -03-04*******************************************************************/static void Alarm_State_Reset(void){uint8_t RegData = 0;uint8_t RecData[2] = {0};uint8_t SendData[3] = {0};/*读取报警状态信息*/RegData = REG_STATUS;HAL_I2C_Master_Transmit(&hi2c1, DEV_ADDR_WRITE, &RegData, 1, 100);HAL_I2C_Master_Receive(&hi2c1, DEV_ADDR_READ, RecData, 2, 100);#if ENABLE_MAX17048_DEBUG printf("Status REG:%02X:VAL:%02X%02X.\r\n", RegData, RecData[0], RecData[1]);Display_Alarm_Info(RecData[0]);#endif/*清除报警信息*/SendData[0] = RegData;SendData[1] = (RecData[0]&(~0x7F));SendData[2] = RecData[1];HAL_I2C_Master_Transmit(&hi2c1, DEV_ADDR_WRITE, SendData, 3, 100);#if ENABLE_MAX17048_DEBUG printf("Set Status REG:%02X:VAL:%02X%02X.\r\n", RegData, SendData[1], SendData[2]);#endif#if ENABLE_MAX17048_DEBUG HAL_I2C_Master_Transmit(&hi2c1, DEV_ADDR_WRITE, &RegData, 1, 100);HAL_I2C_Master_Receive(&hi2c1, DEV_ADDR_READ, RecData, 2, 100);printf("After Status REG:%02X:VAL:%02X%02X.\r\n", RegData, RecData[0], RecData[1]);#endif/*读取配置信息*/RegData = REG_CONFIG;HAL_I2C_Master_Transmit(&hi2c1, DEV_ADDR_WRITE, &RegData, 1, 100);HAL_I2C_Master_Receive(&hi2c1, DEV_ADDR_READ, RecData, 2, 100);#if ENABLE_MAX17048_DEBUG printf("Config REG:%02X:VAL:%02X%02X.\r\n", RegData, RecData[0], RecData[1]);#endif/*设置报警阈值 BIT0-4 可设范围1-32% 设置10%则32-10*/RecData[1] = ((RecData[1]&0xE0)|(32-10));/*清除报警状态位 BIT5*/RecData[1] &= (~REG_BIT5);SendData[0] = RegData;SendData[1] = RecData[0];SendData[2] = RecData[1];HAL_I2C_Master_Transmit(&hi2c1, DEV_ADDR_WRITE, SendData, 3, 100);#if ENABLE_MAX17048_DEBUG printf("Set Config REG:%02X:VAL:%02X%02X.\r\n", RegData, SendData[1], SendData[2]);#endif#if ENABLE_MAX17048_DEBUG HAL_I2C_Master_Transmit(&hi2c1, DEV_ADDR_WRITE, &RegData, 1, 100);HAL_I2C_Master_Receive(&hi2c1, DEV_ADDR_READ, RecData, 2, 100);printf("After Config REG:%02X:VAL:%02X%02X.\r\n", RegData, RecData[0], RecData[1]);#endif/*读取版本信息*/#if ENABLE_MAX17048_DEBUGRegData = REG_VERSION;HAL_I2C_Master_Transmit(&hi2c1, DEV_ADDR_WRITE, &RegData, 1, 100);HAL_I2C_Master_Receive(&hi2c1, DEV_ADDR_READ, RecData, 2, 100);printf("Version REG:%02X:VAL:%02X%02X.\r\n", RegData, RecData[0], RecData[1]);#endif}/********************************************************************* @brief 读取MAX17048 Vcell电压数值 78.125uV/Vcell* @param [in]Block_Time 阻塞读取时间* @return 电量数据* @author aron566* @version V1.0* @date -03-04*******************************************************************/static uint16_t Read_Vcell_Update(uint32_t Block_Time){Send_Val_Buf[0] = REG_V_CELL;if(Block_Time == 0){if(HAL_OK != HAL_I2C_Master_Transmit_IT(&hi2c1, DEV_ADDR_WRITE, Send_Val_Buf, 1)){return Battery_Voltage;}}else if(Block_Time > 0){if(HAL_OK != HAL_I2C_Master_Transmit(&hi2c1, DEV_ADDR_WRITE, Send_Val_Buf, 1, Block_Time)){return Battery_Voltage;}if(HAL_OK != HAL_I2C_Master_Receive(&hi2c1, DEV_ADDR_READ, Reg_Val_Buf, 2, Block_Time)){return Battery_Voltage;}Battery_Voltage = (Reg_Val_Buf[0]<<8)+Reg_Val_Buf[1];Battery_Voltage = (uint16_t)(((double)Battery_Voltage * 78.125)/1000000);return Battery_Voltage;}return Battery_Voltage;}/********************************************************************* @brief 读取MAX17048 SOC(Battery state of charge)电量数值 1%/256* @param [in]Block_Time 阻塞读取时间* @return 电量数据* @author aron566* @version V1.0* @date -03-04*******************************************************************/static uint16_t Read_Soc_Update(uint32_t Block_Time){Send_Val_Buf[0] = REG_SOC;if(Block_Time == 0){if(HAL_OK != HAL_I2C_Master_Transmit_IT(&hi2c1, DEV_ADDR_WRITE, Send_Val_Buf, 1)){return Battery_Soc;}}else if(Block_Time > 0){if(HAL_OK != HAL_I2C_Master_Transmit(&hi2c1, DEV_ADDR_WRITE, Send_Val_Buf, 1, Block_Time)){I2C_State_Reset();return Battery_Soc;}if(HAL_OK != HAL_I2C_Master_Receive(&hi2c1, DEV_ADDR_READ, Reg_Val_Buf, 2, Block_Time)){return Battery_Soc;}uint16_t Battery_Soc_Temp = (Reg_Val_Buf[0]<<8) + Reg_Val_Buf[1];Battery_Soc_Temp /= 256;Battery_Soc = Battery_Soc_Temp > 100?100:Battery_Soc_Temp;return Battery_Soc;}return Battery_Soc;}/** Public application code --------------------------------------------------*//********************************************************************************* Public code**********************************************************************************//********************************************************************* @brief I2C发送完成回调* @param [in]None.* @return None.* @author aron566* @version V1.0* @date -03-04*******************************************************************/void Voltameter_Port_I2C_MasterTxCpltCallback(void){/*TODO:READ*/HAL_I2C_Master_Receive_IT(&hi2c1, DEV_ADDR_READ, Reg_Val_Buf, 2);}/********************************************************************* @brief I2C接收完成回调* @param [in]None.* @return None.* @author aron566* @version V1.0* @date -03-04*******************************************************************/void Voltameter_Port_I2C_MasterRxCpltCallback(void){/*TODO:UPDATE VAL*/if(Send_Val_Buf[0] == REG_V_CELL){uint16_t Battery_Voltage_Temp = (Reg_Val_Buf[0]<<8)+Reg_Val_Buf[1];Battery_Voltage_Temp = (uint16_t)(((double)Battery_Voltage_Temp * 78.125)/1000000);Battery_Voltage = Battery_Voltage_Temp;}else if(Send_Val_Buf[0] == REG_SOC){uint16_t Battery_Soc_Temp = (Reg_Val_Buf[0]<<8) + Reg_Val_Buf[1];Battery_Soc_Temp /= 256;Battery_Soc = Battery_Soc_Temp > 100?100:Battery_Soc_Temp;}}/********************************************************************* @brief 获取电池电量及电压信息* @param [in]None* @return 电量数据* @author aron566* @version V1.0* @date -03-04*******************************************************************/uint16_t Voltameter_Port_Get_Battery_Electric_Quantity(void){Read_Soc_Update(10);Read_Vcell_Update(0);return Battery_Soc;}/********************************************************************* @brief 获取电池充电状态* @param [in]None* @return 1 为充电状态* @author aron566* @version V1.0* @date -03-04*******************************************************************/uint8_t Voltameter_Port_Get_Battery_Charge_State(void){if(HAL_GPIO_ReadPin(BAT_STAT_GPIO_Port, BAT_STAT_Pin) == GPIO_PIN_SET){return 1;}else{return 0;}}/********************************************************************* @brief MAX17048 休眠设置* @param [in]Sleep_En 睡眠使能.* @return None.* @author aron566* @version V1.0* @date -07-07*******************************************************************/void Voltameter_Port_OnOff_Sleep(bool Sleep_En){uint8_t RegData = 0;uint8_t RecData[2] = {0};uint8_t SendData[3] = {0};/*读取配置信息*/RegData = REG_CONFIG;HAL_I2C_Master_Transmit(&hi2c1, DEV_ADDR_WRITE, &RegData, 1, 100);HAL_I2C_Master_Receive(&hi2c1, DEV_ADDR_READ, RecData, 2, 100);#if ENABLE_MAX17048_DEBUG printf("Config REG:%02X:VAL:%02X%02X.\r\n", RegData, RecData[0], RecData[1]);#endifSendData[1] = RegData;SendData[1] = RecData[0];SendData[2] = RecData[1];if(Sleep_En == true){/*进入休眠 config.sleep = 1*/SendData[1] |= REG_BIT7;}else{/*退出休眠 config.sleep = 0*/SendData[1] &= ~REG_BIT7;}HAL_I2C_Master_Transmit(&hi2c1, DEV_ADDR_WRITE, SendData, 3, 100);}/********************************************************************* @brief 电池监控接口初始化* @param [in]None* @return None.* @author aron566* @version V1.0* @date -03-04*******************************************************************/void Voltameter_Port_Init(void){/*上电复位MAX17048*/Power_On_Reset();/*报警复位*/Alarm_State_Reset();}#ifdef __cplusplus ///<end extern c}#endif/******************************** End of file *********************************/

关于电量补偿

芯片带配置温补的区域,不过温度检测的区域为电池温度,可能条件不允许。

#define RCOMP0 0x97/**< 温度补偿值*/static int8_t Rcomp = RCOMP0;/********************************************************************* @brief 温度补偿* @param [in]Temperatur 电池温度.* @return None.* @author aron566* @version V1.0* @date -04-16*******************************************************************/void MAX17048_Driver_Compensate(float Temperature){uint8_t RegData = 0;uint8_t RecData[2] = {0};uint8_t SendData[3] = {0};if(Temperature > 20) {Rcomp = (int8_t)(RCOMP0 + (Temperature - 20) * -0.5);}else {Rcomp = (int8_t)(RCOMP0 + (Temperature - 20) * -5.0);}/*读取配置数据*/RegData = REG_CONFIG;HAL_I2C_Master_Transmit(MAX17048_I2C_HANDLE, DEV_ADDR_WRITE, &RegData, 1, 100);HAL_I2C_Master_Receive(MAX17048_I2C_HANDLE, DEV_ADDR_READ, RecData, 2, 100);/*设置温度补偿RCOMP*/SendData[0] = RegData;SendData[1] = (uint8_t)Rcomp;SendData[2] = RecData[1];HAL_I2C_Master_Transmit(MAX17048_I2C_HANDLE, DEV_ADDR_WRITE, SendData, 3, 100);}

手动补偿90%-100%电量区域

/*充电耗时记录*/typedef struct rectification{uint32_t Start_Time_Sec;// uint32_t End_Time_Sec;// uint32_t Next_Time_Sec;// uint32_t Elapsed;uint16_t Compensation_Soc;}RECTIFICATION_Typedef_t;/*设备参考实测功率*/#define DEVICE_REF_POWER 150 /**< 150mA/h*/#define BATTERY_CAPACITY 1000 /**< 1000mAh*/#define CAN_USE_MIN_TOTAL (BATTERY_CAPACITY*60/DEVICE_REF_POWER)/*电量时间补偿记录*/static RECTIFICATION_Typedef_t E_Record[11] = {0};/********************************************************************* @brief 修正补偿MAX17048 SOC(Battery state of charge)电量数值* @param [in]Current_Soc 当前电量数值* @return 修正后电量数据* @author aron566* @version V1.0* @date -04-22*******************************************************************/static uint16_t Soc_Compensation(uint16_t Current_Soc){static uint16_t last_soc_val = 0;uint16_t range_num = Current_Soc - 90;/*无需补偿*/if(Current_Soc == 100){return Current_Soc;}/*充电中进行补偿运算*/if(last_soc_val != Current_Soc && Current_Soc >= 90 && MAX17048_Driver_Get_Battery_Charge_State() == 1){E_Record[range_num].Start_Time_Sec = Timer_Port_Get_Current_Time(TIMER_SEC);E_Record[range_num].Compensation_Soc = Current_Soc;last_soc_val = Current_Soc;return Current_Soc;}if(last_soc_val == Current_Soc && Current_Soc >= 90 && MAX17048_Driver_Get_Battery_Charge_State() == 1){/*电量值在90%区域,补偿*/if(range_num < 2){if((Timer_Port_Get_Current_Time(TIMER_SEC) - E_Record[range_num].Start_Time_Sec) > 60*30){E_Record[range_num].Start_Time_Sec = Timer_Port_Get_Current_Time(TIMER_SEC);E_Record[range_num].Compensation_Soc += 1;}}else{uint32_t ref_time = E_Record[range_num].Start_Time_Sec - E_Record[range_num-1].Start_Time_Sec;uint32_t elapsed_time = Timer_Port_Get_Current_Time(TIMER_SEC) - E_Record[range_num].Start_Time_Sec;if(elapsed_time > ref_time && elapsed_time > 2*ref_time){E_Record[range_num].Start_Time_Sec = Timer_Port_Get_Current_Time(TIMER_SEC);E_Record[range_num-1].Start_Time_Sec = E_Record[range_num].Start_Time_Sec - ref_time;E_Record[range_num].Compensation_Soc += 1;}}E_Record[range_num].Compensation_Soc = E_Record[range_num].Compensation_Soc >= 100?100:E_Record[range_num].Compensation_Soc;return E_Record[range_num].Compensation_Soc;}/*电量值在90%区域,放电电量控制*/if(Current_Soc >= 90 && MAX17048_Driver_Get_Battery_Charge_State() == 0){/*属修正值*/if(E_Record[range_num].Compensation_Soc > Current_Soc){/*计算耗电时间*/uint32_t elapsed_time_min = (Timer_Port_Get_Current_Time(TIMER_SEC) - E_Record[range_num].Start_Time_Sec)/60;float pow = (float)elapsed_time_min/(float)CAN_USE_MIN_TOTAL;E_Record[range_num].Compensation_Soc = (uint16_t)((float)E_Record[range_num].Compensation_Soc - (100.f * pow));E_Record[range_num].Compensation_Soc = E_Record[range_num].Compensation_Soc < Current_Soc?Current_Soc:E_Record[range_num].Compensation_Soc;return E_Record[range_num].Compensation_Soc;}}return Current_Soc;}

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。