电源管理芯片MAX17048驱动

@toc
最近调试MAX17048,做个简单的记录。
基于STM32H743

芯片功能

MAX17048为小尺寸、微功耗电池电量计,用于手持及便携产品的锂离子(Li+)电池。
MAX17048配置工作在单节锂电池,MAX17049配置工作在2节串联锂电池,两者都是标准I2C接口通讯。

电路

配置

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


代码

/**
 *  @file Voltameter_Port.c
 *
 *  @date 2021-03-04
 *
 *  @author aron566
 *
 *  @copyright Copyright (c) 2021 aron566 <aron566@163.com>.
 *
 *  @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 compiler
extern "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_ADDR                0x6C
/*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_MODE                0x06
#define REG_VERSION             0x08
#define REG_HIBRT               0x0A
#define REG_CONFIG              0x0C
#define REG_VALRT               0x14
#define REG_CRATE               0x16
#define REG_V_RESET             0x18
#define REG_STATUS              0x1A
        
#define REG_TABLE               0x40/**< 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_DEBUG
static void Display_Alarm_Info(uint8_t Alarm_Value);
#endif
static 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    2021-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    2021-03-08
  ******************************************************************
  */
#if ENABLE_MAX17048_DEBUG
static 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    2021-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] = 0x01;
  HAL_I2C_Master_Transmit(&hi2c1, DEV_ADDR_WRITE, WriteData, 3, 100);
}

/**
  ******************************************************************
  * @brief   清除MAX17048 报警状态
  * @param   [in]None.
  * @return  None.
  * @author  aron566
  * @version V1.0
  * @date    2021-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_DEBUG
  RegData = 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    2021-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    2021-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    2021-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    2021-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    2021-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    2021-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   电池监控接口初始化
  * @param   [in]None
  * @return  None.
  * @author  aron566
  * @version V1.0
  * @date    2021-03-04
  ******************************************************************
  */
void Voltameter_Port_Init(void)
{
  /*上电复位MAX17048*/
  Power_On_Reset();
  
  /*报警复位*/
  Alarm_State_Reset();
}

#ifdef __cplusplus ///<end extern c
}
#endif
/******************************** End of file *********************************/

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 今天感恩节哎,感谢一直在我身边的亲朋好友。感恩相遇!感恩不离不弃。 中午开了第一次的党会,身份的转变要...
    余生动听阅读 10,857评论 0 11
  • 彩排完,天已黑
    刘凯书法阅读 4,478评论 1 3
  • 表情是什么,我认为表情就是表现出来的情绪。表情可以传达很多信息。高兴了当然就笑了,难过就哭了。两者是相互影响密不可...
    Persistenc_6aea阅读 129,665评论 2 7

友情链接更多精彩内容