你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

STM32F103CBT6单片机I2C接口读取锂电池电量计LC709203F数据

[复制链接]
STMCU 发布时间:2020-9-29 12:45

一、基本情况


       LC709203F是一款适用于单节锂离子/聚合物电池应用的电量计,通过HG-CVR算法来测量电池的RSOC(相对电荷状态)。精确的RSOC数据有助于改善便携式设备的运行时间和合理使用。利用单片机的I2C口与LC709203F通讯,实现对其电池温度、电池电压、电池剩余电量(RSOC)等锂电池重要数据的采集。单片机管脚PB10(I2C2_SCL)连接LC709203F的第8脚SCL,单片机管脚PB11(I2C2_SDA))连接LC709203F的第7脚SDA。



二、LC709203F的I2C通讯协议

20200925214134995_meitu_1.jpg


三、程序



lc709203f.c中程序:


  1. #include "lc709203f.h"  
  2. #include "delay.h"                                  

  3. //初始化IIC接口
  4. void lc709203f_Init(void)
  5. {
  6.         u16 Buffer_data0=0x0001;//设置电源模式
  7.         u16 Buffer_data1=0x0010;//设置适合您电池的APA参数
  8.         u16 Buffer_data2=0x0001;//设置适合您电池的配置文件
  9.         u16 Buffer_data3=0xAA55;//初始化RSOC
  10.         u16 Buffer_data4=0x0001;//设置热敏电阻模式
  11.        
  12.         IIC2_Init();//IIC初始化
  13.         lc709203f_WriteOneWord(LC709203F_IC_Power_Mode,Buffer_data0);
  14.         lc709203f_WriteOneWord(LC709203F_Adjustment_Pack_Appli,Buffer_data1);
  15.         lc709203f_WriteOneWord(LC709203F_Change_Parameter,Buffer_data2);
  16.         lc709203f_WriteOneWord(LC709203F_Initial_RSOC,Buffer_data3);
  17.         lc709203f_WriteOneWord(LC709203F_Status_Bit,Buffer_data4);
  18.        

  19. }
复制代码

2)读一个字函数:u16 lc709203f_ReadOneWord(u8 ReadAddr),严格按照上述协议中的时许写代码



  1. u16 lc709203f_ReadOneWord(u8 ReadAddr)
  2. {                                  
  3.         u16 data=0;       
  4.     u8 data_l=0;       
  5.         u8 data_h=0;
  6.         u8 crc_8=0;
  7.         u8 readcrc[5];
  8.     IIC2_Start();                              //第一步:第一次启动
  9.         delay_us(100);
  10.         IIC2_Send_Byte(LC709203F_ADDR_wr); //第二步:写入从机地址和写入指令
  11.         delay_us(100);
  12.         IIC2_Wait_Ack();                           //第三步:等待从机确认
  13.         delay_us(100);
  14.     IIC2_Send_Byte(ReadAddr);                  //第四步:发送寄存器地址(字节最高位为虚拟位)
  15.         delay_us(100);
  16.         IIC2_Wait_Ack();                                  //第五步:等待从机确认
  17.         delay_us(100);
  18.         IIC2_Start();                                         //第六步:第二次启动
  19.         delay_us(100);
  20.     IIC2_Send_Byte(LC709203F_ADDR_rd); //第七步:写入从机地址和读取指令       
  21.     delay_us(100);        
  22.         IIC2_Wait_Ack();                                  //第八步:等待从机确认
  23.         delay_us(100);
  24.     data_l=IIC2_Read_Byte(1);                              //第九步:接收低字节数据
  25.         delay_us(100);
  26.         //IIC2_Ack();                                   //产生应答1
  27.         data_h=IIC2_Read_Byte(1);                              //第十步:接收高字节数据
  28.         delay_us(100);
  29.         //IIC2_Ack();                                   //产生应答2
  30.         crc_8=IIC2_Read_Byte(0);                              //第十一步:接收CRC-8数据
  31.         delay_us(100);
  32.         //IIC2_NAck();                                  //不产生应答
  33.     IIC2_Stop();                                      //第十二步:停止
  34.         readcrc[0]=LC709203F_ADDR_wr;
  35.         readcrc[1]=ReadAddr;
  36.         readcrc[2]=LC709203F_ADDR_rd;
  37.         readcrc[3]=data_l;
  38.         readcrc[4]=data_h;
  39.         if(gh_crc8(readcrc,5)==crc_8)
  40.                 data=data_h*256+data_l;
  41.        
  42.         return data;
  43. }
复制代码

3)写一个字函数:void lc709203f_WriteOneWord(u8 WriteAddr,u16 DataToWrite)


  1. void lc709203f_WriteOneWord(u8 WriteAddr,u16 DataToWrite)
  2. {                                                                                                  
  3.     u8 data[4];
  4.     IIC2_Start();                              //第一步:启动
  5.     IIC2_Send_Byte(LC709203F_ADDR_wr); //第二步:写入从机地址和写入指令
  6.     IIC2_Wait_Ack();                              //第三步:等待从机确认
  7.     IIC2_Send_Byte(WriteAddr);                 //第四步:发送寄存器地址(字节最高位为虚拟位)
  8.     IIC2_Wait_Ack();                            //第五步:等待从机确认                                 
  9.     IIC2_Send_Byte((u8)(DataToWrite&0x00FF));               //第六步:发送低字节数据                              
  10.     IIC2_Wait_Ack();                            //第七步:等待从机确认
  11.     IIC2_Send_Byte((u8)(DataToWrite>>8));      //第八步:发送高字节数据   
  12.     IIC2_Wait_Ack();                            //第九步:等待从机确认
  13.     data[0]=LC709203F_ADDR_wr;
  14.     data[1]=WriteAddr;
  15.     data[2]=(u8)(DataToWrite&0x00FF);
  16.     data[3]=(u8)(DataToWrite>>8);
  17.     IIC2_Send_Byte(gh_crc8(data,4));      //第十步:发送CRC-8数据   
  18.     IIC2_Wait_Ack();                            //第十一步:等待从机确认
  19.     IIC2_Stop();                               //第十二步:停止
  20.     delay_ms(10);     
  21. }
复制代码

4)获取数据函数:void getLC709203FOutput(s16* LC709203FData)


  1. void getLC709203FOutput(s16* LC709203FData)
  2. {
  3.       
  4.     u16 data0,data1,data2;
  5.        
  6.     data0=lc709203f_ReadOneWord(LC709203F_Cell_Temperature);//电池温度
  7.         data1=lc709203f_ReadOneWord(LC709203F_RSOC);//电池剩余电量
  8.         data2=lc709203f_ReadOneWord(LC709203F_Cell_Voltage); //电池电压
  9.    
  10.     if((data0>=0x0AAC)&&(data0<=0x7FFF)) //读取的数据处理
  11.         LC709203FData[0]=data0-0x0AAC;
  12.         if(data1<=0x0064)
  13.         LC709203FData[1]=data1;
  14.     if((data2<=0x0FA0)&&(data2>=0x07D0))
  15.         LC709203FData[2]=data2;
  16. }
复制代码

四、调试中遇到的问题处理总结


1、起初,未严格按照协议,读取到的数据均是0XABAB等,以为是I2C读写函数信号延时函数设置不合适的问题,后来多次测试还是不行,再后来仔细阅读协议,发现此协议还需要CRC8校验,比其他一些芯片的I2C通讯协议要复杂,于是按照通讯协议写lc709203f_ReadOneWord()和lc709203f_WriteOneWord()函数;



2、之后下载程序运行,仍然读不到正确数据,检查程序,发现lc709203f_ReadOneWord()中第九步、第十步、第十一步都是IIC2_Read_Byte(1),函数的形参都为1,而该函数1表示为产生应答ACK,0为不产生应答NACK,根据I2C通讯协议,应该为上面程序所写的,不产生应答的改为IIC2_Read_Byte(0),并且此函数里面已经有ACK和NACK函数,如上述程序所写的需要注释掉产生应答1、产生应答2和不产生应答。



IIC2_Read_Byte()如下:



  1. //读1个字节,ack=1时,发送ACK,ack=0,发送nACK   
  2. u8 IIC2_Read_Byte(unsigned char ack)
  3. {
  4.         unsigned char i,receive=0;
  5.         SDA2_IN();//SDA设置为输入
  6.     for(i=0;i<8;i++ )
  7.         {
  8.         IIC2_SCL=0;
  9.         delay_us(4);                   //LC709203F时钟频率400Khz=2.5us
  10.                 IIC2_SCL=1;
  11.         receive<<=1;  //receive=receive<<1;
  12.         if(READ2_SDA)receive++;   // 根据READ_SDA的值(SDA),从高到低顺序依次写入一个字节,
  13.                 delay_us(4);             //i=0时,SDA=1则receive=0B00000001,i=1,SDA=1则receive=0B00000011
  14.     }                                         
  15.     if (!ack)
  16.         IIC2_NAck();//发送nACK
  17.     else
  18.         IIC2_Ack(); //发送ACK   
  19.     return receive;
  20. }
复制代码




3、修改上述后,下载程序运行仍然读不到正确数据,但是通过单步调试都能正确读到数据,原因在哪里呢?单步调试发现写的数据均已写入进去了,于是在读字节函数lc709203f_ReadOneWord()中,在每一步之间增加delay_us(100);//延时100us,此时运行,都能正确读到数据。


收藏 评论0 发布时间:2020-9-29 12:45

举报

0个回答

所属标签

STM32团队

意法半导体微控制器和微处理器拥有广泛的产品线,包含低成本的8位单片机和基于ARM® Cortex®-M0、M0+、M3、M4、M33、M7及A7内核并具备丰富外设选择的32位微控制器及微处理器


最新内容

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
微信公众号二维码 微信公众号
手机版二维码 手机版