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 的填写

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/402307.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

html+css+js网页制作 自定义电商10个页面

htmlcssjs网页制作 自定义电商10个页面 网页作品代码简单&#xff0c;可使用任意HTML编辑软件&#xff08;如&#xff1a;Dreamweaver、HBuilder、Vscode 、Sublime 、Webstorm、Text 、Notepad 等任意html编辑软件进行运行及修改编辑等操作&#xff09;。 获取源码 1&#…

机器学习 第11章-特征选择与稀疏学习

机器学习 第11章-特征选择与稀疏学习 11.1 子集搜索与评价 我们将属性称为“特征”(feature)&#xff0c;对当前学习任务有用的属性称为“相关特征”(relevant feature)、没什么用的属性称为“无关特征”(irrelevant feature)。从给定的特征集合中选择出相关特征子集的过程&a…

UART通信实现与验证(RS485)

前言 UART是一种常用的串行通信协议&#xff0c;RS485则是一种用于长距离和抗干扰的物理层标准。结合UART和RS485可以实现可靠的数据传输&#xff0c;特别是在多点通信和长距离应用中。通过合适的硬件连接、软件配置和验证测试&#xff0c;可以确保这一通信系统的稳定性和数据完…

【刷题笔记】二叉树2

1 二叉树的层序遍历 上一期我们讲了关于二叉树的前序、中序以及后序遍历的相关内容。然而&#xff0c;还存在一种遍历方式&#xff0c;这种方式非常符合我们人类的正常思维&#xff0c;可以求解很多树相关的问题&#xff0c;比较暴力——二叉树的层序遍历。 二叉树的层序遍历与…

读软件开发安全之道:概念、设计与实施01基础

1. 基础 1.1. 实现软件安全既需要运用逻辑&#xff0c;又是一项艺术 1.1.1. 一项仰赖直觉来做出判断的艺术 1.1.2. 需要践行者对当代数字系统有所掌 1.1.3. 需要他们对人与系统之间的交互有所体悟 1.2. 需要准确地思考一下何谓安全 1.2.1. 安全定义的主观性颇强&#xff0…

HarmonyOS开发:跨应用数据共享详解

目录 前言跨应用数据共享的重要性HarmonyOS的数据共享能力相关的基本概念跨应用数据共享的数据管理具体实现跨应用数据共享延伸&#xff1a;数据共享的安全和隐私结语 前言 现在的移动操作系统中&#xff0c;应用之间的数据共享已成为提升用户体验和实现功能互补的重要手段&a…

watch 和 watchEffect 的隐藏点 --- 非常细致

之前有一篇文章讲述了 watch 和 watchEffect 的使用&#xff0c;但在实际使用中&#xff0c;仍然存在一些“隐藏点”&#xff0c;可能会影响开发&#xff0c;在这补充一下。 1. watch 的隐藏点 1.1 性能陷阱&#xff1a;深度监听的影响 当在 watch 中使用 deep: true 来监听…

[MRCTF2020]套娃1

打开题目&#xff0c;查看源代码&#xff0c;有提示 有两层过滤 1.过滤"_"与"%5f" 。 这里要求的参数必须是"b_u_p_t"但是不能检测出"_"。这里看着很作弄人。其实这里要用到php里非法参数名的问题。可以参考一下博客 ?b.u.p.t2333…

Python爬虫技术与K-means算法的计算机类招聘信息获取与数据分析

有需要本项目的代码或文档以及全部资源&#xff0c;或者部署调试可以私信博主 目录 摘要.... 1 Abstract 2 1 引言.... 3 1.1 研究背景... 3 1.2 国内外研究现状... 4 1.3 研究目的... 5 1.4 研究意义... 7 2 关键技术理论介绍... 7 2.1 Python爬虫... 7 2.1 K-means…

微软开源库 Detours 详细介绍与使用实例分享

目录 1、Detours概述 2、Detours功能特性 3、Detours工作原理 4、Detours应用场景 5、Detours兼容性 6、Detours具体使用方法 7、Detours使用实例 - 使用Detours拦截系统库中的UnhandledExceptionFilter接口&#xff0c;实现对程序异常的拦截 C软件异常排查从入门到精通…

VMware虚拟机下安装Ubuntu22.04以及汉化配置保姆级教程

目录 一.VMware和Ubuntu下载 二.在VMware中创建Ubuntu 1.点击 创建新的虚拟机 2.选择典型 3.选择Ubuntu镜像包&#xff08;自定义存放的位置&#xff09; 4.创建个人信息&#xff08;密码一定要牢记&#xff09; 5.选择虚拟机的安装位置 6.其他配置项&#xff08;默认下…

Unity Obfuscator 使用说明

一、Assembly - Settings 1. 核心Unity程序集&#xff08;Assembly-CSharp&#xff09; Obfuscate Assembly-CSharp: 开启 这是Unity的核心程序集&#xff0c;所有没有存储在程序集定义文件&#xff08;assembly definition file&#xff09;中的代码都会被存储在这里。大多数…

C++多态详解

1. 多态的概念 多态就是函数调用的多种形态&#xff0c;使用多态能够使得不同的对象去完成同一件事时&#xff0c;产生不同的动作和结果。 举个栗子&#xff1a;比如买票这个行为&#xff0c;当普通人买票时&#xff0c;是全价买票&#xff1b;学生买票时&#xff0c;是半价买…

yolov5网络初始化问题

当你打印detect层的三个特征层时&#xff0c;发现有三种不同的长和宽&#xff0c;如下图所示&#xff1a; 我提出三个问题&#xff1a; 为什么不一样呢&#xff0c;输入有什么含义吗&#xff1f; 为什么网络初始化四次&#xff08;forward)&#xff1f; 下面来逐个击破 1. torc…

uniapp 微信小程序生成水印图片

效果 源码 <template><view style"overflow: hidden;"><camera device-position"back" flash"auto" class"camera"><cover-view class"text-white padding water-mark"><cover-view class"…

【笔记】泰山派环境配置遇到E: Unable to locate package repo

答案来自通义千问&#xff0c;解决了我的问题&#xff0c;做一些记录 你尝试在Ubuntu或Debian系统上使用apt命令安装repo工具&#xff0c;但是遇到了问题&#xff0c;因为repo不是直接在软件源中作为一个独立的包提供的。repo是Google的一个Git仓库管理工具&#xff0c;通常用…

EasyCVR视频汇聚平台:打造全栈视频监控系统的基石,解锁可视化管理与高效运维

随着科技的飞速发展&#xff0c;视频监控已成为现代社会不可或缺的一部分&#xff0c;广泛应用于社区、公共场所、工业领域等多个场景。EasyCVR视频汇聚平台&#xff0c;作为一款高性能的视频汇聚管理平台&#xff0c;凭借其强大的视频处理、汇聚与融合能力&#xff0c;在构建全…

数据结构——关于栈

1.栈 1.1栈的概念及结构 栈&#xff1a;一种特殊的线性表&#xff0c;其只允许在固定的一端进行插入和删除元素操作 进行数据插入和删除操作的一端称为栈顶&#xff0c;另一端称为栈底。栈中的数据元素遵守后进先出的原则 比如&#xff1a;羽毛球桶&#xff0c;弹夹等等 压…

苍穹外卖项目DAY05

苍穹外卖项目DAY05 1、店铺营业状态设置 1.1、Redis入门 Redis简介 Redis是一个基于内存的key-value结构数据库 基于内存存储&#xff0c;读写性能高适合存储热点数据&#xff08;热点商品、咨询、新闻&#xff09;企业应用广泛 中文网&#xff1a;https://www.redis.net…

【Java学习】Stream流详解

所属专栏&#xff1a;Java学习 Stream流是JDK 8引入的一个概念&#xff0c;它提供了一种高效且表达力强的方式来处理数据集合&#xff08;如List、Set等&#xff09;或数组。Stream API可以以声明性方式&#xff08;指定做什么&#xff09;来处理数据序列。流操作可以被分为两大…