当前位置: 首页 > news >正文

BQ27441初始化配置程序,电压、SOC等参数读取程序

系列文章目录

1.元件基础
2.电路设计
3.PCB设计
4.元件焊接
5.板子调试
6.程序设计
7.算法学习
8.编写exe
9.检测标准
10.项目举例
11.职业规划


文章目录

  • 前言
  • 一、模拟IIC
  • 二、BQ27441初始化配置程序
  • 三、学习资料

前言


送给大学毕业后找不到奋斗方向的你(每周不定时更新)

中国计算机技术职业资格网
上海市工程系列计算机专业中级专业技术职务任职资格评审


BQ27441采用I2C进行设置。 寄存器地址为0xAA(补齐八位后)。

在这里插入图片描述

初始化配置至少需要配置:电池容量、电池能量、截至电压、锥度率。一般的应用配置这四个参数就可以了,需要注意在库仑计上电后,需要延时才能配置成功,延时时间不够,配置不成功。
初始化配置完成后,即可进行电压、SOC、Current的读取。
在这里插入图片描述

当电流低于sleep电流后,芯片的默认设置会自动进入sleep模式。

该程序已经在项目验证,采集精度很高。使用下面两个函数即可
在这里插入图片描述
在这里插入图片描述

一、模拟IIC

可使用模拟也可使用硬件IIC,代码自行移植

#ifndef __MY_IIC_H
#define __MY_IIC_H
#include "main.h"/* IO操作 */
#define IIC_SCL(x)        do{ x ? \HAL_GPIO_WritePin(My_IIC_SCL_GPIO_Port,My_IIC_SCL_Pin, GPIO_PIN_SET):\HAL_GPIO_WritePin(My_IIC_SCL_GPIO_Port,My_IIC_SCL_Pin, GPIO_PIN_RESET);\}while(0)       /* SCL */#define IIC_SDA(x)        do{ x ? \HAL_GPIO_WritePin(My_IIC_SDA_GPIO_Port, My_IIC_SDA_Pin, GPIO_PIN_SET):\HAL_GPIO_WritePin(My_IIC_SDA_GPIO_Port, My_IIC_SDA_Pin, GPIO_PIN_RESET);\}while(0)       /* SDA */
/* 读取SDA */
#define IIC_READ_SDA HAL_GPIO_ReadPin(My_IIC_SDA_GPIO_Port, My_IIC_SDA_Pin)/* SDA引脚模式设置,开漏输出,上拉, 这样就不用再设置IO方向了, 开漏输出的时候(=1), 
也可以读取外部信号的高低电平,SDA外部必须接上拉电阻 */void iic_init(void);
static void iic_delay(void);
void iic_start(void);		
void iic_stop(void);													
void iic_send_byte(uint8_t data);													
uint8_t iic_read_byte(uint8_t ack);													
uint8_t iic_wait_ack(void);
void iic_ack(void);
void iic_nack(void);
int16_t i2c_mt6701_get_value(void);													#endif
#include "MY_IIC.h"/*** @brief      	初始化IIC* @param       	无* @retval    	无*/
void iic_init(void)
{iic_stop();     /* 停止总线上所有设备 */
}/*** @brief     	IIC延时函数,用于控制IIC读写速度* @param      	无* @retval     	无*/
static void iic_delay(void)
{for(int i=0;i<100;i++){for(int j=0;j<100;j++){}}
}/*** @brief     	产生IIC起始信号* @param      	无* @retval    	无*/
void iic_start(void)
{IIC_SDA(1);IIC_SCL(1);iic_delay();IIC_SDA(0);     /* START信号: 当SCL为高时, SDA从高变成低, 表示起始信号 */iic_delay();IIC_SCL(0);     /* 钳住I2C总线,准备发送或接收数据 */iic_delay();
}/*** @brief     	产生IIC停止信号* @param      	无* @retval     	无*/
void iic_stop(void)
{IIC_SDA(0);     /* STOP信号: 当SCL为高时, SDA从低变成高, 表示停止信号 */iic_delay();IIC_SCL(1);iic_delay();IIC_SDA(1);     /* 发送I2C总线结束信号 */iic_delay();
}/*** @brief    	IIC发送一个字节* @param       	data: 要发送的数据* @retval      	无*/
void iic_send_byte(uint8_t data)
{uint8_t t;for (t = 0; t < 8; t++){IIC_SDA((data & 0x80) >> 7);    /* 高位先发送 */iic_delay();IIC_SCL(1);iic_delay();IIC_SCL(0);data <<= 1;     /* 左移1位,用于下一次发送 */}IIC_SDA(1);         /* 发送完成, 主机释放SDA线 */
}/*** @brief     	IIC读取一个字节* @param       	ack:  ack=1时,发送ack; ack=0时,发送nack* @retval      	接收到的数据*/
uint8_t iic_read_byte(uint8_t ack)
{uint8_t i, receive = 0;for (i = 0; i < 8; i++ )    /* 接收1个字节数据 */{receive <<= 1;  			/* 高位先输出,所以先收到的数据位要左移 */IIC_SCL(1);iic_delay();if (IIC_READ_SDA){receive++;}IIC_SCL(0);iic_delay();
}if (!ack){iic_nack();     /* 发送nACK */}else{iic_ack();      /* 发送ACK */
}return receive;
}/*** @brief     	等待应答信号到来* @param    	无* @retval      	1,接收应答失败*              	0,接收应答成功*/
uint8_t iic_wait_ack(void)
{uint8_t waittime = 0;uint8_t rack = 0;IIC_SDA(1);     /* 主机释放SDA线(此时外部器件可以拉低SDA线) */iic_delay();IIC_SCL(1);     /* SCL=1, 此时从机可以返回ACK */iic_delay();while (IIC_READ_SDA)    /* 等待应答 */{waittime++;if (waittime > 250){iic_stop();rack = 1;break;}
}IIC_SCL(0);     /* SCL=0, 结束ACK检查 */iic_delay();return rack;
}/*** @brief      	产生ACK应答* @param       	无* @retval      	无*/
void iic_ack(void)
{IIC_SDA(0);     	/* SCL 0 -> 1  时 SDA = 0,表示应答 */iic_delay();IIC_SCL(1);     	/* 产生一个时钟 */iic_delay();IIC_SCL(0);iic_delay();IIC_SDA(1);     	/* 主机释放SDA线 */iic_delay();
}/*** @brief    	不产生ACK应答* @param       	无* @retval      	无*/
void iic_nack(void)
{IIC_SDA(1);   	/* SCL 0 -> 1  时 SDA = 1,表示不应答 */iic_delay();IIC_SCL(1);     	/* 产生一个时钟 */iic_delay();IIC_SCL(0);iic_delay();
}int16_t i2c_mt6701_get_value(void)
{uint8_t temp[2];int16_t VALUE=0;iic_start();//产生IIC起始信号iic_send_byte(0x0C);//MT6701 的I2C从机地址(写)iic_wait_ack();//等待应答信号到来iic_send_byte(0x03);//MT6701 的03寄存器iic_wait_ack();//等待应答信号到来iic_start();//产生IIC起始信号iic_send_byte(0x0D);//MT6701 的I2C从机地址(读)iic_wait_ack();//等待应答信号到来temp[0] = iic_read_byte(0);//IIC读取一个字节h,NACKiic_stop();//产生IIC停止信号iic_start();//产生IIC起始信号iic_send_byte(0x0C);//MT6701 的I2C从机地址(写)iic_wait_ack();//等待应答信号到来iic_send_byte(0x04);//MT6701 的04寄存器iic_wait_ack();//等待应答信号到来iic_start();//产生IIC起始信号iic_send_byte(0x0D);//MT6701 的I2C从机地址(读)iic_wait_ack();//等待应答信号到来temp[1] = iic_read_byte(0);//IIC读取一个字节h,NACKiic_stop();//产生IIC停止信号VALUE = ((int16_t)temp[0] << 6) | (temp[1] >> 2);return VALUE;
}

二、BQ27441初始化配置程序

bq27441_driver.c

#include "bq27441_driver.h"
#include "common.h"
#include "i2c.h"const uint16_t terminatevoltage ={0x0C80};       //terminate voltage=3000mV,system shutdown voltage  ,      系统的正常工作电压
//
const uint16_t loadselect ={0x81};               //load select/load loadselectmode; 0x81 power-mode 0x01 current mode, normally use 0x81 ,if design capacity > 8500mAh change to 0x01
#define BATTERY_3200MAH
uint32_t Frack_Num;/**************************************************************************************
**************************************************************************************/#ifdef BATTERY_3200MAH
//3200mAH    
unsigned short const Designcapacity={0x0C80};     //Design capacity=2500mAh   这个值随着电池的使用会变化
unsigned short const DesignEnergy={0x2E40};       //Design Energy=2500*3.8mWh; Design Energy=Design capacity*3.7 for 4.2V battery,Design Energy=Design capacity*3.8 for 4.35V battery,
#define   FCC_SIZE   950//220   充电
const uint16_t Taperrate ={0x0140};              //Taper rate=250,taper rate=Design Capacity*10/taper current mA;(2500*10/220 = 125) a little higher than charger taper current(~>20mA)  
//Taperrate  是一个充电截止判定的量//subclass 81
//放电电流 大于62mA  2500*10 / 62.5ma = 400
const uint16_t Dsgcurrentthreshold ={0x190};    // 50000/167=299mA,  Dsg current threshold(num)=500, Dsg current threshold(mAh)=Design capacity*10/Dsg current threshold(num)=80mA//充电电流一定大于这个电流 100mA 2500*10/100 = 250
const uint16_t Chgcurrentthreshold ={0xfa};    //Chg current threshold(num)=500, Chg current threshold(mAh)=Design capacity*10/Chg current threshold(num)=80mA,must smaller than charger taper current//进入低功耗电流 2500 * 10 / 50ma = 500
const uint16_t Quitcurrent ={0x01f4};  //{0x03E8};     //Quit current threshold(num)=1000,Quit current threshold(mAh)=Design capacity*10/Quit current threshold(num)=40mA#endif/**************************************************************************************
**************************************************************************************/#ifdef BATTERY_3200MAH
const uint16_t  Qmax ={0x4000};                   const uint16_t  Ra[] ={0x66, 0x66, 0x63, 0x6b, 0x48, 0x3b, 0x3e, 0x3f, 0x35, 0x2f, 0x3c, 0x46, 0x8c, 0x171, 0x24c};    
//const uint16_t  Ra[] ={0x34, 0x34, 0x32, 0x36, 0x2d, 0x32, 0x47, 0x52, 0x50, 0x4b, 0x57, 0x52, 0x72, 0x108, 0x1a4};    
#endif#ifdef BATTERY_2000MAHuint16_t volt,soc,fcc ;int16_t avgCur;
/**************************************************************************************
**************************************************************************************/static uint32_t bq_cmdWrite(uint8_t subaddr, uint8_t cmd);
static uint32_t bq_read(uint8_t *pBuf,  uint8_t addr, uint8_t len);
static uint32_t bq_MemoryWrite(uint8_t subaddr, uint16_t data );
static uint8_t GetCheckSum(uint8_t  addr);
static void  bq_Read_Ta_and_Qmax(void);
static void bq_fullReset(void);
static void bq_CONFIG_subclass82(void);
static void bq_CONFIG_subclass81(void);
static void bq_CONFIG_subclass89(void);
static uint32_t bq_ConfigRead(void);
static uint32_t bq_Rdarg(uint16_t *volt, int16_t *avgCur, uint16_t *soc, uint16_t *fcc);
uint16_t bq_ITPOR(void);
/**************************************************************************************
**************************************************************************************//**************************************************************************************
**************************************************************************************//********************************************************
向subaddr 这个地址写入cmd这个指令(写单个指令)********************************************************/
uint32_t bq_cmdWrite(uint8_t subaddr, uint8_t cmd) 
{return HAL_I2C_Mem_Write(&hi2c1,BQ2744_ADDRESS,subaddr,I2C_MEMADD_SIZE_8BIT,&cmd,1,0xff);
}
/*************************************  *************************************/
uint32_t bq_read(uint8_t *pBuf,  uint8_t addr, uint8_t len) 
{ return HAL_I2C_Mem_Read(&hi2c1, BQ2744_ADDRESS, addr, len, pBuf, len, 0xfff);   }
/********************************************************
*********************************************************/
uint32_t bq_MemoryWrite(uint8_t subaddr, uint16_t data )
{uint8_t Mdata=(data>>8);uint8_t Ldata=(data&0xFF);   HAL_I2C_Mem_Write(&hi2c1,BQ2744_ADDRESS,subaddr,I2C_MEMADD_SIZE_8BIT,&Mdata,1,0xff);return HAL_I2C_Mem_Write(&hi2c1,BQ2744_ADDRESS,subaddr+1,I2C_MEMADD_SIZE_8BIT,&Ldata,1,0xff);    
}
/********************************************************
*********************************************************/
uint8_t GetCheckSum(uint8_t  addr) 
{uint8_t checksum = 0, i;uint8_t rtBuf[2];for (i = 0; i < 32; i++) {rtBuf[0] = 0;bq_read(rtBuf, addr, 1);checksum = checksum + rtBuf[0];addr++;}checksum = 0xFF - checksum;return checksum;
}
/********************************************************
*********************************************************/
void  bq_Read_Ta_and_Qmax(void)
{unsigned short  qmax=0x00;uint8_t  Ra_table[32]= {0x0A};unsigned short  cap=0x00;uint8_t buf[1];uint8_t tbuf[2];   uint8_t i;tbuf[0]=0;tbuf[1]=0;       Ra_table[31]='\r';Ra_table[30]='\n';bq_cmdWrite(0x00,0x00);   //Places the device in UNSEALED access mode.bq_cmdWrite(0x01,0x80);bq_cmdWrite(0x00,0x00);bq_cmdWrite(0x01,0x80);bq_cmdWrite(0x61,0x00);       // enables BlockData() to access to RAM.bq_cmdWrite(0x3e,0x52);     //选择0x52区域      //access the state subclass (decimal 82, 0x52 hex)bq_cmdWrite(0x3f,0x00);         //use offset 0x00 for offsets 0 to 31bq_read(buf, 0x40, 2);qmax = (buf[0] << 8) | buf[1];  //高低位交换bq_read(buf, 0x4A, 2);cap = (buf[0] << 8) | buf[1]; //高低位交换bq_cmdWrite(0x3e,0x59);//选择0x59区域bq_cmdWrite(0x3f,0x00);for(i=0; i<30; i++){bq_read(buf, 0x40+i, 1);Ra_table[i] = buf[0]; //高低位交换}HAL_UART_Transmit(&huart2,Ra_table,32,0xff); Frack_Num++;tbuf[0]=Frack_Num>>24;HAL_UART_Transmit(&huart2,tbuf,1,0xff);tbuf[0]=((Frack_Num>>16)&0xFF);HAL_UART_Transmit(&huart2,tbuf,1,0xff);tbuf[0]=((Frack_Num>>8)&0xFF);HAL_UART_Transmit(&huart2,tbuf,1,0xff);       tbuf[0]=(Frack_Num&0xFF);HAL_UART_Transmit(&huart2,tbuf,1,0xff);         
//	bq_cmdWrite(0x3e,0x40);//选择0x59区域
//	bq_cmdWrite(0x3f,0x00);
//
//
//        bq_read(buf, 0x40, 1);
//        HAL_UART_Transmit(&huart2,buf,1,0xff);         
//        bq_read(tbuf, 0x41, 1);
//        HAL_UART_Transmit(&huart2,tbuf,1,0xff);  }/********************************************************
*********************************************************/
void bq_fullReset(void)
{if (bq_cmdWrite(0x00,0x00) || bq_cmdWrite(0x01,0x80))   //Places the device in UNSEALED access mode.{return ;}if (bq_cmdWrite(0x00,0x00) || bq_cmdWrite(0x01,0x80)){return ;}if (bq_cmdWrite(0x00,0x41) || bq_cmdWrite(0x01,0x00)) //Performs a full device reset.{return;}
}/********************************************************
*********************************************************/void bq_CONFIG_subclass82(void) 
{uint8_t checksum = 0;bq_cmdWrite(0x3e, 0x52); //选择0x52区域      //access the state subclass (decimal 82, 0x52 hex)bq_cmdWrite(0x3f, 0x00); //use offset 0x00 for offsets 0 to 31bq_MemoryWrite(0x40, Qmax);bq_MemoryWrite(0x50, terminatevoltage); //terminatevoltage 截止电压(系统能够正常运行的最低电压) bq_cmdWrite(0x45, loadselect);bq_MemoryWrite(0x4A, Designcapacity); //电池容量  mAhbq_MemoryWrite(0x4C, DesignEnergy); //mWhbq_MemoryWrite(0x5B, Taperrate);checksum = GetCheckSum(0x40);bq_cmdWrite(0x60, checksum); //0xba  checksum}
void bq_CONFIG_subclass81(void) //充放电阈值设置
{uint8_t checksum = 0;bq_cmdWrite(0x3e, 0x51); //选择0x51区域bq_cmdWrite(0x3f, 0x00);bq_MemoryWrite(0x40, Dsgcurrentthreshold); //放电电流bq_MemoryWrite(0x42, Chgcurrentthreshold); //充电电流,充电电流的判断标准bq_MemoryWrite(0x44, Quitcurrent); //静态电源  checksum = GetCheckSum(0x40);bq_cmdWrite(0x60, checksum); //0x5e
}void bq_CONFIG_subclass89(void)//内阻表设置
{uint8_t checksum = 0, i = 0;bq_cmdWrite(0x3e, 0x59); //选择0x59区域bq_cmdWrite(0x3f, 0x00);for (i = 0; i < 15; i++) {bq_MemoryWrite(0x40 + i * 2, Ra[i]);}checksum = GetCheckSum(0x40);bq_cmdWrite(0x60, checksum);
}/********************************************************
返回0,  进入配置模式并退出成功, 返回1, 进入配置失败, 返回0xFE, 超时
*********************************************************/
uint32_t bq_Config(void) 
{  uint8_t  rtBuf[2];uint16_t value;uint32_t result;static uint32_t m_tryCnt = 0;if (m_tryCnt++ > 10){	   m_tryCnt = 0;return 0xFE;}if (bq_cmdWrite(0x00, 0x00) || bq_cmdWrite(0x01, 0x80)) //Places the device in UNSEALED access mode.{cmsLog_error("entry unsealed err\n");return 1;}if (bq_cmdWrite(0x00, 0x00) || bq_cmdWrite(0x01, 0x80)){cmsLog_error("entry unsealed err1\n");return 1;}if (bq_cmdWrite(0x00, 0x13) || bq_cmdWrite(0x01, 0x00)){cmsLog_error("entry config mode err\n");return 1;}HAL_Delay(1);result = bq_read(rtBuf, bq27421CMD_FLAG_LSB, 2);if (result == 0){value = (rtBuf[1] << 8) | rtBuf[0];if (!(value & 0x10)){    		cmsLog_error("upmode=0\n");         bq_cmdWrite(0x61,0x00);       // enables BlockData() to access to RAM.bq_CONFIG_subclass82();//            bq_CONFIG_subclass81();
//
//            bq_CONFIG_subclass89();bq_cmdWrite(0x00,0x42); //软复位 退出配置模式            bq_cmdWrite(0x01,0x00);bq_cmdWrite(0x00,0x00);bq_cmdWrite(0x01,0x00);m_tryCnt = 0;            }else{cmsLog_error("upmode=1\n");bq_cmdWrite(0x61,0x00);       // enables BlockData() to access to RAM.bq_CONFIG_subclass82();//            bq_CONFIG_subclass81();
//
//            bq_CONFIG_subclass89();bq_cmdWrite(0x00,0x42); //软复位 退出配置模式            bq_cmdWrite(0x01,0x00);bq_cmdWrite(0x00,0x00);bq_cmdWrite(0x01,0x00);          result = 1;  cmsLog_error("value=0x%x\n", value);}}  cmsLog_debug(" %s\n", result == 0 ? "Ok" : "Fail");return result;
}
/********************************************************
返回0, 配置成功, 返回1, 配置失败  返回其他, 配置超时
*********************************************************/
uint32_t bq_ConfigRead(void)
{uint8_t  rtBuf[2] = {0};uint16_t value;uint32_t result;result = bq_read(rtBuf, bq27421CMD_FLAG_LSB, 2);if (result != 0){return 0xFF;}if (result == 0) {value = (rtBuf[1] << 8) | rtBuf[0];if (value & 0x10) {   result = 1;}else{bq_cmdWrite(0x00,0x20);bq_cmdWrite(0x01,0x00);}}return result;
}/********************************************************读参数
********************************************************/
uint32_t bq_Rdarg(uint16_t *volt, int16_t *avgCur, uint16_t *soc, uint16_t *fcc)
{uint8_t  lrtBuf[1];uint8_t  mrtBuf[1];uint16_t  value;	uint16_t ret1;uint16_t ret2;ret1=HAL_I2C_Mem_Read(&hi2c1, BQ2744_ADDRESS, bq27421CMD_VOLT_LSB, 1, lrtBuf, 1, 0xfff);   //volt  为电压  ret2=HAL_I2C_Mem_Read(&hi2c1, BQ2744_ADDRESS, bq27421CMD_VOLT_MSB, 1, mrtBuf, 1, 0xfff); if(0 == ret1 && ret2 == 0)   {value = (mrtBuf[0] << 8) |lrtBuf[0];*volt = value;}else{return 0xF1;}ret1=HAL_I2C_Mem_Read(&hi2c1, BQ2744_ADDRESS, bq27421CMD_AI_LSB, 1, lrtBuf, 1, 0xfff);     //avgCur 为平均电流ret2=HAL_I2C_Mem_Read(&hi2c1, BQ2744_ADDRESS, bq27421CMD_AI_MSB, 1, mrtBuf, 1, 0xfff); if(0 == ret1 && ret2 == 0)   {value = (mrtBuf[0] << 8) |lrtBuf[0];*avgCur = value;    }else{return 0xF1;} ret1=HAL_I2C_Mem_Read(&hi2c1, BQ2744_ADDRESS, bq27421CMD_SOC_LSB, 1, lrtBuf, 1, 0xfff);    //soc 为电量百份比   ret2=HAL_I2C_Mem_Read(&hi2c1, BQ2744_ADDRESS, bq27421CMD_SOC_MSB, 1, mrtBuf, 1, 0xfff); if(0 == ret1 && ret2 == 0)   {value = (mrtBuf[0] << 8) |lrtBuf[0];*soc = value;  }else{return 0xF1;}ret1=HAL_I2C_Mem_Read(&hi2c1, BQ2744_ADDRESS, bq27421CMD_FCC_LSB, 1, lrtBuf, 1, 0xfff);   //FCC为充电电量ret2=HAL_I2C_Mem_Read(&hi2c1, BQ2744_ADDRESS, bq27421CMD_FCC_MSB, 1, mrtBuf, 1, 0xfff); if(0 == ret1 && ret2 == 0)   {value = (mrtBuf[0] << 8) |lrtBuf[0];*fcc = value;}else{return 0xF1;}   return ret1;
}
/********************************************************
返回1 需要配置 返回0 已配置过 返回其他值出错
********************************************************/
uint16_t bq_ITPOR(void)
{uint8_t  rtBuf[2] = {0};uint32_t ret;ret  = bq_read(rtBuf, bq27421CMD_FLAG_LSB, 1);if (ret != 0){return 0xFF;}	if (rtBuf[0] & 0x20){return 1;}return 0xAA;    
}uint8_t BQ25895_STATE(){bq_Rdarg(&volt, &avgCur, &soc, &fcc);if((avgCur >20)&&HAL_GPIO_ReadPin(TYPEC_DEC_GPIO_Port,TYPEC_DEC_Pin)&&soc<91){return BQ_Charging;}else if(soc>90){return BQ_Charge_Done;}else if(avgCur<(-150)){return Rod_Charging;}return 1;
}uint8_t getBoxBattery(void)
{ uint16_t volt,soc,fcc ;int16_t avgCur;     if(bq_ITPOR() !=0xAA ){HAL_Delay(500);bq_Config();if(bq_ConfigRead() != 0)return 0xFE;          }bq_Rdarg(&volt, &avgCur, &soc, &fcc);return soc&0xFF;
}uint8_t Batter_Gauge_Test(){uint8_t data;uint16_t volt,soc,fcc ;int16_t avgCur;     volt=bq_ITPOR();if(volt == 1 ){bq_Config();if(bq_ConfigRead() != 0)return 2;          }bq_Read_Ta_and_Qmax();      bq_Rdarg(&volt, &avgCur, &soc, &fcc);return 1;}/********************************************************
返回0,  进入配置模式并退出成功, 返回1, 进入配置失败, 返回0xFE, 超时
*********************************************************/
uint32_t bq_Config_nww(void) 
{  uint8_t  rtBuf[2];uint16_t value;uint32_t result;static uint8_t m_tryCnt = 0;if (m_tryCnt++ > 10){	   m_tryCnt = 0;return 0xFE;}if (bq_cmdWrite(0x00, 0x00) || bq_cmdWrite(0x01, 0x80)) //Places the device in UNSEALED access mode.{return 1;}if (bq_cmdWrite(0x00, 0x00) || bq_cmdWrite(0x01, 0x80)){return 2;}if (bq_cmdWrite(0x00, 0x13) || bq_cmdWrite(0x01, 0x00)){return 3;}HAL_Delay(1);result=1;while(result){result = bq_read(rtBuf, bq27421CMD_FLAG_LSB, 2);if (result == 0){value = (rtBuf[1] << 8) | rtBuf[0];result=(value & 0x10);}}bq_cmdWrite(0x61,0x00);       // enables BlockData() to access to RAM.bq_CONFIG_subclass52();return result;
}void bq27441_init(void){ if(bq_ITPOR() == 1){ cmsLog_error("need_config\n");           HAL_Delay(1100);bq_Config();HAL_Delay(10);            bq_ConfigRead();//            bq_fullReset();            }elsecmsLog_error("noconfig=0\n");          }

bq27441_driver.h

#ifndef __BQ27441_DRIVER_H
#define __BQ27441_DRIVER_H#include "stm32f0xx.h"
#include <stdio.h>/***********************************************/
#define  COLUMB_FLAG_VOLT   (1 << 0)
#define  COLUMB_FLAG_CURR   (1 << 1)
#define  COLUMB_FLAG_SOC    (1 << 2)
#define  COLUMB_FLAG_FCC    (1 << 3)
/***********************************************/
#define SLAVE_I2C_GENERIC_RETRY_MAX  5//#define  BQ2744_ADDRESS    0x55
#define  BQ2744_ADDRESS    0xAA/***********************************************/#define bq27421CMD_CNTL_LSB           0x00
#define bq27421CMD_CNTL_MSB           0x01
#define bq27421CMD_TEMP_LSB           0x02
#define bq27421CMD_TEMP_MSB           0x03
#define bq27421CMD_VOLT_LSB           0x04
#define bq27421CMD_VOLT_MSB           0x05
#define bq27421CMD_FLAG_LSB           0x06
#define bq27421CMD_FLAG_MSB           0x07
#define bq27421CMD_NAC_LSB            0x08
#define bq27421CMD_NAC_MSB            0x09
#define bq27421CMD_FAC_LSB            0x0a
#define bq27421CMD_FAC_MSB            0x0b
#define bq27421CMD_RM_LSB             0x0c
#define bq27421CMD_RM_MSB             0x0d
#define bq27421CMD_FCC_LSB            0x0e
#define bq27421CMD_FCC_MSB            0x0f
#define bq27421CMD_AI_LSB             0x10
#define bq27421CMD_AI_MSB             0x11
#define bq27421CMD_SI_LSB             0x12
#define bq27421CMD_SI_MSB             0x13
#define bq27421CMD_MLI_LSB            0x14
#define bq27421CMD_MLI_MSB            0x15
#define bq27421CMD_AP_LSB             0x18
#define bq27421CMD_AP_MSB             0x19
#define bq27421CMD_SOC_LSB            0x1c
#define bq27421CMD_SOC_MSB            0x1d
#define bq27421CMD_ITEMP_LSB          0x1e
#define bq27421CMD_ITEMP_MSB          0x1f
#define bq27421CMD_SOH_LSB            0x20
#define bq27421CMD_SOH_MSB            0x21
/**************************************************************************************
**************************************************************************************/
typedef struct __BQ27XX_Drive{void     (*init)(void);void     (*uninit)(void);uint32_t (*itpor)(void);void     (*fullreset)(void);uint32_t (*updategauge)(uint16_t *volt, uint16_t *avgCur, uint16_t *soc, uint16_t *fcc);uint32_t (*config)(void);uint32_t (*confirmconfig)(void);void     (*showtaandmax)(void);
}BQ27XX_INTERFACE_T;enum{Rod_Charging=1,BQ_Charge_Done,BQ_Charging,
};
extern const BQ27XX_INTERFACE_T g_pfBQ27xxFunction[];
uint32_t bq_Config(void);
uint8_t BQ25895_STATE();
uint8_t Batter_Gauge_Test();
uint8_t getBoxBattery(void);
void bq27441_init(void);
#endif

common.c

#include "common.h"
#include "timer_driver.h"static uint32_t  m_EnterCnt = 0;/*************************************************************************************** FunctionName   : Task_EnterCritical()* Description    : * EntryParameter : None* ReturnValue    : None**************************************************************************************/
void Task_EnterCritical(void)
{  m_EnterCnt++;__set_PRIMASK(1);     }
/*************************************************************************************** FunctionName   : Task_ExitCritical()* Description    : * EntryParameter : None* ReturnValue    : None**************************************************************************************/
void Task_ExitCritical(void)
{    m_EnterCnt--; if (m_EnterCnt == 0){__set_PRIMASK(0);}
}/**************************************************************************************
* FunctionName   : Task_GetCurrentTime()
* Description    : 
* EntryParameter : None
* ReturnValue    : None
**************************************************************************************/
uint32_t Task_GetCurrentTime(void)
{uint32_t value;Task_EnterCritical();/*10ms 增加1*/value = TIM2_GetClock();Task_ExitCritical();return value;
}

common.h

#ifndef __COMMON_H__
#define __COMMON_H__#include "stm32f0xx.h"
#include "stm32f0xx_hal.h"
//#include "SysTick.h"
#include <stdio.h>
#include "main.h"
//#include "dwtdelay.h"
/***********************************************
***********************************************/#define  cmsLog_error(format,...)   printf("%s(%d)|" format"\r",__FUNCTION__,__LINE__,##__VA_ARGS__)#if 01
#define  cmsLog_debug(format,...)   printf("%s|" format"\r",__FUNCTION__,##__VA_ARGS__)
#else
#define  cmsLog_debug(format,...) 
#endif#define  SYSTEM_TICK_HZ    5  /*5ms*/
/***********************************************
***********************************************/
#define  PROCESS_TIME_SYNC(nowT, sysT, nextT) \
do{\if ((int32_t)((int32_t)(sysT) - (int32_t)(nowT)) < 0 )\{\return;\}\(nowT) = (sysT) +  (nextT)/SYSTEM_TICK_HZ;\
}while(0)/***********************************************
***********************************************/enum
{SYS_IDLE    = 0,         /*系统停机状态*/    SYS_METER      ,         /*配置库仑计*/SYS_STAR       ,         /*系统启动,准备显示开机画面*/           SYS_CHARG      ,         /*系统充电启动,准备显示开机画面*/      SYS_VOLTLOW    ,         /*系统电压低5%*/    SYS_CLOSE      ,SYS_MAX,      
};/***********************************************
***********************************************/void Task_EnterCritical(void);void Task_ExitCritical(void);void Task_EnterSleep(void);uint32_t Task_GetCurrentTime(void);void DelayFunction_Init(void);void Delay_us(__IO uint32_t nTime);/***********************************************
***********************************************/
#endif

三、学习资料

1、TI单节电量计基本介绍及常见问题解答
2、TI电量计应用指导
3、TI电量计应用培训视频
4、从零开始快速让电量计工作起来
5、TI电量计–配置及训练流程
6、TI电量计–循环学习产生量产文件及易错分析
7、关于Qmax cell 的填写

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 玩转单例模式
  • 【Unity教程】使用 Animation Rigging实现IK制作程序化的动画
  • 使用模板导出excel文件
  • C++ 124类和对象_运算符重载_赋值
  • 前端工程化-05.Vue项目开发流程
  • Jenkins持续集成工具学习
  • LeetCode 242 有效的字母异位词
  • 使用X-AnyLabeling自动标注数据集(以yolov10模型为例,多图详细介绍)
  • 【商城源码开发要多久】
  • 时间记录内核模块
  • 【AI/算法类】OPPO 2025届秋招笔试题(B卷)
  • OpenCV的编译(MinGW)
  • 大模型是如何升级的呢?技术?应用?
  • 微信小程序开发:基础架构与配置文件
  • opencv 控制鼠标键盘实现功能setMouseCallback
  • [ 一起学React系列 -- 8 ] React中的文件上传
  • 【108天】Java——《Head First Java》笔记(第1-4章)
  • 【划重点】MySQL技术内幕:InnoDB存储引擎
  • 【跃迁之路】【669天】程序员高效学习方法论探索系列(实验阶段426-2018.12.13)...
  • gcc介绍及安装
  • IP路由与转发
  • Java知识点总结(JavaIO-打印流)
  • PHP面试之三:MySQL数据库
  • Python十分钟制作属于你自己的个性logo
  • Shadow DOM 内部构造及如何构建独立组件
  • VUE es6技巧写法(持续更新中~~~)
  • 从零开始在ubuntu上搭建node开发环境
  • 探索 JS 中的模块化
  • 王永庆:技术创新改变教育未来
  • 微信小程序填坑清单
  • ​力扣解法汇总1802. 有界数组中指定下标处的最大值
  • #我与Java虚拟机的故事#连载01:人在JVM,身不由己
  • #我与Java虚拟机的故事#连载05:Java虚拟机的修炼之道
  • (js)循环条件满足时终止循环
  • (WSI分类)WSI分类文献小综述 2024
  • (二十一)devops持续集成开发——使用jenkins的Docker Pipeline插件完成docker项目的pipeline流水线发布
  • (几何:六边形面积)编写程序,提示用户输入六边形的边长,然后显示它的面积。
  • (四)Tiki-taka算法(TTA)求解无人机三维路径规划研究(MATLAB)
  • (学习日记)2024.03.25:UCOSIII第二十二节:系统启动流程详解
  • (转) RFS+AutoItLibrary测试web对话框
  • (转)Android学习系列(31)--App自动化之使用Ant编译项目多渠道打包
  • (转)http-server应用
  • (转载)Linux网络编程入门
  • (转载)利用webkit抓取动态网页和链接
  • .net 4.0发布后不能正常显示图片问题
  • .NET delegate 委托 、 Event 事件
  • .NET LINQ 通常分 Syntax Query 和Syntax Method
  • .Net MVC + EF搭建学生管理系统
  • .NET WebClient 类下载部分文件会错误?可能是解压缩的锅
  • .net web项目 调用webService
  • .net 调用海康SDK以及常见的坑解释
  • .net通用权限框架B/S (三)--MODEL层(2)
  • .NET运行机制
  • ??myeclipse+tomcat
  • @Bean有哪些属性