STM32F103CBT6单片机I2C接口读取锂电池电量计LC709203F数据
一、基本情況
? ? ? ?LC709203F是一款適用于單節(jié)鋰離子/聚合物電池應(yīng)用的電量計,通過HG-CVR算法來測量電池的RSOC(相對電荷狀態(tài))。精確的RSOC數(shù)據(jù)有助于改善便攜式設(shè)備的運行時間和合理使用。利用單片機的I2C口與LC709203F通訊,實現(xiàn)對其電池溫度、電池電壓、電池剩余電量(RSOC)等鋰電池重要數(shù)據(jù)的采集。單片機管腳PB10(I2C2_SCL)連接LC709203F的第8腳SCL,單片機管腳PB11(I2C2_SDA))連接LC709203F的第7腳SDA。
二、LC709203F的I2C通訊協(xié)議
三、程序
lc709203f.c中程序:
1)初始化函數(shù):void lc709203f_Init(void)
#include "lc709203f.h" #include "delay.h" //初始化IIC接口 void lc709203f_Init(void) {u16 Buffer_data0=0x0001;//設(shè)置電源模式u16 Buffer_data1=0x0010;//設(shè)置適合您電池的APA參數(shù)u16 Buffer_data2=0x0001;//設(shè)置適合您電池的配置文件u16 Buffer_data3=0xAA55;//初始化RSOCu16 Buffer_data4=0x0001;//設(shè)置熱敏電阻模式IIC2_Init();//IIC初始化lc709203f_WriteOneWord(LC709203F_IC_Power_Mode,Buffer_data0);lc709203f_WriteOneWord(LC709203F_Adjustment_Pack_Appli,Buffer_data1);lc709203f_WriteOneWord(LC709203F_Change_Parameter,Buffer_data2);lc709203f_WriteOneWord(LC709203F_Initial_RSOC,Buffer_data3);lc709203f_WriteOneWord(LC709203F_Status_Bit,Buffer_data4);}2)讀一個字函數(shù):u16 lc709203f_ReadOneWord(u8 ReadAddr),嚴格按照上述協(xié)議中的時許寫代碼
u16 lc709203f_ReadOneWord(u8 ReadAddr) { u16 data=0; u8 data_l=0; u8 data_h=0;u8 crc_8=0;u8 readcrc[5];IIC2_Start(); //第一步:第一次啟動delay_us(100);IIC2_Send_Byte(LC709203F_ADDR_wr); //第二步:寫入從機地址和寫入指令delay_us(100);IIC2_Wait_Ack(); //第三步:等待從機確認delay_us(100);IIC2_Send_Byte(ReadAddr); //第四步:發(fā)送寄存器地址(字節(jié)最高位為虛擬位)delay_us(100);IIC2_Wait_Ack(); //第五步:等待從機確認delay_us(100);IIC2_Start(); //第六步:第二次啟動 delay_us(100);IIC2_Send_Byte(LC709203F_ADDR_rd); //第七步:寫入從機地址和讀取指令 delay_us(100); IIC2_Wait_Ack(); //第八步:等待從機確認delay_us(100);data_l=IIC2_Read_Byte(1); //第九步:接收低字節(jié)數(shù)據(jù)delay_us(100);//IIC2_Ack(); //產(chǎn)生應(yīng)答1data_h=IIC2_Read_Byte(1); //第十步:接收高字節(jié)數(shù)據(jù)delay_us(100);//IIC2_Ack(); //產(chǎn)生應(yīng)答2crc_8=IIC2_Read_Byte(0); //第十一步:接收CRC-8數(shù)據(jù)delay_us(100);//IIC2_NAck(); //不產(chǎn)生應(yīng)答IIC2_Stop(); //第十二步:停止readcrc[0]=LC709203F_ADDR_wr;readcrc[1]=ReadAddr;readcrc[2]=LC709203F_ADDR_rd;readcrc[3]=data_l;readcrc[4]=data_h;if(gh_crc8(readcrc,5)==crc_8)data=data_h*256+data_l;return data; }3)寫一個字函數(shù):void lc709203f_WriteOneWord(u8 WriteAddr,u16 DataToWrite)
void lc709203f_WriteOneWord(u8 WriteAddr,u16 DataToWrite) {?? ??? ??? ??? ? ? ?? ? ??? ? ? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??u8 data[4];IIC2_Start(); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?//第一步:啟動IIC2_Send_Byte(LC709203F_ADDR_wr); //第二步:寫入從機地址和寫入指令I(lǐng)IC2_Wait_Ack();?? ? ? ? ? ? ? ? ? ? ? ? ? ? ?//第三步:等待從機確認IIC2_Send_Byte(WriteAddr); ? ? ? ? ? ? ? ? //第四步:發(fā)送寄存器地址(字節(jié)最高位為虛擬位)IIC2_Wait_Ack(); ?? ? ?? ??? ??? ??? ??? ? ?//第五步:等待從機確認?? ??? ??? ??? ??? ? ??? ??? ? ??IIC2_Send_Byte((u8)(DataToWrite&0x00FF)); ? ? ? ? ? ? ? //第六步:發(fā)送低字節(jié)數(shù)據(jù)?? ??? ??? ??? ??? ??? ??? ? ??IIC2_Wait_Ack(); ??? ??? ? ? ??? ? ? ? ? ? ?//第七步:等待從機確認IIC2_Send_Byte((u8)(DataToWrite>>8)); ? ? ?//第八步:發(fā)送高字節(jié)數(shù)據(jù)?? ?IIC2_Wait_Ack(); ??? ??? ? ? ??? ? ? ? ? ? ?//第九步:等待從機確認data[0]=LC709203F_ADDR_wr;data[1]=WriteAddr;data[2]=(u8)(DataToWrite&0x00FF);data[3]=(u8)(DataToWrite>>8);IIC2_Send_Byte(gh_crc8(data,4)); ? ? ?//第十步:發(fā)送CRC-8數(shù)據(jù)?? ?IIC2_Wait_Ack(); ??? ??? ? ? ??? ? ? ? ? ? ?//第十一步:等待從機確認IIC2_Stop(); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? //第十二步:停止delay_ms(10);?? ?? }4)獲取數(shù)據(jù)函數(shù):void getLC709203FOutput(s16* LC709203FData)
void getLC709203FOutput(s16* LC709203FData) {u16 data0,data1,data2;data0=lc709203f_ReadOneWord(LC709203F_Cell_Temperature);//電池溫度data1=lc709203f_ReadOneWord(LC709203F_RSOC);//電池剩余電量data2=lc709203f_ReadOneWord(LC709203F_Cell_Voltage); //電池電壓if((data0>=0x0AAC)&&(data0<=0x7FFF)) //讀取的數(shù)據(jù)處理LC709203FData[0]=data0-0x0AAC;if(data1<=0x0064)LC709203FData[1]=data1;if((data2<=0x0FA0)&&(data2>=0x07D0))LC709203FData[2]=data2; }四、調(diào)試中遇到的問題處理總結(jié)
1、起初,未嚴格按照協(xié)議,讀取到的數(shù)據(jù)均是0XABAB等,以為是I2C讀寫函數(shù)信號延時函數(shù)設(shè)置不合適的問題,后來多次測試還是不行,再后來仔細閱讀協(xié)議,發(fā)現(xiàn)此協(xié)議還需要CRC8校驗,比其他一些芯片的I2C通訊協(xié)議要復(fù)雜,于是按照通訊協(xié)議寫lc709203f_ReadOneWord()和lc709203f_WriteOneWord()函數(shù);
2、之后下載程序運行,仍然讀不到正確數(shù)據(jù),檢查程序,發(fā)現(xiàn)lc709203f_ReadOneWord()中第九步、第十步、第十一步都是IIC2_Read_Byte(1),函數(shù)的形參都為1,而該函數(shù)1表示為產(chǎn)生應(yīng)答ACK,0為不產(chǎn)生應(yīng)答NACK,根據(jù)I2C通訊協(xié)議,應(yīng)該為上面程序所寫的,不產(chǎn)生應(yīng)答的改為IIC2_Read_Byte(0),并且此函數(shù)里面已經(jīng)有ACK和NACK函數(shù),如上述程序所寫的需要注釋掉產(chǎn)生應(yīng)答1、產(chǎn)生應(yīng)答2和不產(chǎn)生應(yīng)答。
IIC2_Read_Byte()如下:
//讀1個字節(jié),ack=1時,發(fā)送ACK,ack=0,發(fā)送nACK u8 IIC2_Read_Byte(unsigned char ack) {unsigned char i,receive=0;SDA2_IN();//SDA設(shè)置為輸入for(i=0;i<8;i++ ){IIC2_SCL=0; delay_us(4); //LC709203F時鐘頻率400Khz=2.5usIIC2_SCL=1;receive<<=1; //receive=receive<<1;if(READ2_SDA)receive++; // 根據(jù)READ_SDA的值(SDA),從高到低順序依次寫入一個字節(jié),delay_us(4); //i=0時,SDA=1則receive=0B00000001,i=1,SDA=1則receive=0B00000011} if (!ack)IIC2_NAck();//發(fā)送nACKelseIIC2_Ack(); //發(fā)送ACK return receive; }3、修改上述后,下載程序運行仍然讀不到正確數(shù)據(jù),但是通過單步調(diào)試都能正確讀到數(shù)據(jù),原因在哪里呢?單步調(diào)試發(fā)現(xiàn)寫的數(shù)據(jù)均已寫入進去了,于是在讀字節(jié)函數(shù)lc709203f_ReadOneWord()中,在每一步之間增加delay_us(100);//延時100us,此時運行,都能正確讀到數(shù)據(jù)。
總結(jié)
以上是生活随笔為你收集整理的STM32F103CBT6单片机I2C接口读取锂电池电量计LC709203F数据的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 疫情下的地产中介:门店按下暂停键,数字化
- 下一篇: 初中学历可以自学matlab,过来人对初