在上次項目中用到了LTC6804這塊片子,初次使用它的採集精度確實令我驚訝到了,設備用於監測2V的鉛酸電池組,硬件上幾乎沒有加任何濾波,直接讀取數據就能達到3mv如下的精度,片子真的很好用。html
下面總結一下本身的使用心得。函數
------------------------------------------------------------------------------------------------ui
LTC6804是一款專門用來作多節電池電池組的監測芯片,最高可監測12節電池,官方偏差是低於1.2mv,12 個通道的最快採樣速度能夠達到290us。spa
芯片分爲兩種型號,6804-1和6804-2,區別在於,6804-1採用級聯的形式(級聯控制),6804-2採用並聯形式(分開控制)。3d
除開硬件鏈接以外,這兩種型號的操做都是大同小異,基本能夠視爲同樣,本文以6804-1爲例進行講解。code
原理圖和手冊中的推薦同樣,就不貼出來了,MCU與芯片的通訊方式採用四線SPI,這種通訊方式很常見,各類MCU的驅動也好找。(看了數據手冊,芯片彷佛還支持IIC和2線通訊,不過我沒有用)htm
驅動代碼能夠從官網下載:https://www.analog.com/cn/products/ltc6804-1.htmlblog
下載下來的代碼是C++文件,不能直接在STM32上使用,須要進行一些修改。it
首先修改後綴名,改爲C文件,而後打開LTC6804.c文件。io
第一步進行驅動的移植:
void spi_write_array(uint8_t len, // Option: Number of bytes to be written on the SPI port uint8_t data[] //Array of bytes to be written on the SPI port ) { uint8_t i; for(i = 0; i < len; i++) { SPI2_Send_byte((int8_t)data[i]); } }
void spi_write_read(uint8_t tx_Data[],//array of data to be written on SPI port uint8_t tx_len, //length of the tx data arry uint8_t *rx_data,//Input: array that will store the data read by the SPI port uint8_t rx_len //Option: number of bytes to be read from the SPI port ) { uint8_t i; for(i = 0; i < tx_len; i++) { SPI2_Send_byte(tx_Data[i]); } for(i = 0; i < rx_len; i++) { rx_data[i] = (uint8_t)SPI2_Receive_byte(); } }
只須要把本身的SPI驅動替換上去就能夠了。
void wakeup_idle() { output_low(LTC6804_CS); delayMicroseconds(2); //Guarantees the isoSPI will be in ready mode output_high(LTC6804_CS); }
本身把這個函數中間的部分實現,或者替換成本身的函數:
void wakeup_idle(void) { output_low(LTC6804_CS); delay_ms(4); //Guarantees the isoSPI will be in ready mode output_high(LTC6804_CS); }
下面是原版的初始化函數:
void LTC6804_initialize() { quikeval_SPI_connect(); spi_enable(SPI_CLOCK_DIV16); // This will set the Linduino to have a 1MHz Clock set_adc(MD_NORMAL,DCP_DISABLED,CELL_CH_ALL,AUX_CH_ALL); }
我把它根據本身的實際狀況修改一下 :
void LTC6804_initialize(void) { Drive_LTC6804_Spi_Init();//SPI外設初始化 init_cfg(); //配置LTC6804的寄存器 set_adc(MD_FILTERED,DCP_DISABLED,CELL_CH_ALL,AUX_CH_GPIO1);//設置轉換方式等 wakeup_sleep();//喚醒芯片 LTC6804_wrcfg(TOTAL_IC,tx_cfg);//把上面的設置寫入芯片 if (LTC6804_rdcfg(TOTAL_IC,rx_cfg) == -1) //檢查一下到底有沒有配置成功 { printf("LTC6804_MODULAR INIT NG!\n\r"); } else { printf("LTC6804_MODULAR INIT OK!\n\r"); } }
//手冊第49頁 /* 寄存器 8 7 6 5 4 3 2 1 */ //CFGR0 RD/WR GPIO5 GPIO4 GPIO3 GPIO2 GPIO1 REFON SWTRD ADCOPT //CFGR1 RD/WR VUV[7] VUV[6] VUV[5] VUV[4] VUV[3] VUV[2] VUV[1] VUV[0] //CFGR2 RD/WR VOV[3] VOV[2] VOV[1] VOV[0] VUV[11] VUV[10] VUV[9] VUV[8] //CFGR3 RD/WR VOV[11] VOV[10] VOV[9] VOV[8] VOV[7] VOV[6] VOV[5] VOV[4] //CFGR4 RD/WR DCC8 DCC7 DCC6 DCC5 DCC4 DCC3 DCC2 DCC1 //CFGR5 RD/WR DCTO[3] DCTO[2] DCTO[1] DCTO[0] DCC12 DCC11 DCC10 DCC9 void init_cfg(void) { int i; for(i = 0; i<TOTAL_IC;i++) { tx_cfg[i][0] = 0xFE ; //GPIO引腳下拉電路關斷(bit8~bit4) | 基準保持上電狀態(bit3) | SWTEN處於邏輯1(軟件定時器) | ADC模式選擇爲0 tx_cfg[i][1] = 0x00 ; //不使用欠壓比較功能 tx_cfg[i][2] = 0x00 ; //不使用過壓比較功能 tx_cfg[i][3] = 0x00 ; tx_cfg[i][4] = 0x00 ; //不使用電池放電功能 tx_cfg[i][5] = 0x00 ; //放電超時時間 } }
這裏只使用了最基本的電壓採集,其餘的功能都沒有用。
上面的代碼裏面有一個宏 :TOTAL_IC。
這個宏是用來定義一共有幾片LTC6804-1的,好比我此次使用了2片,那麼它的值就是2.
上面的寄存器設置,能夠參考手冊:
好比須要追加一些別的功能,即可以根據手冊的寄存器進行設置,好比設置報警,設置均衡,設置其餘的功能。
以上初始化部分就完成了,或者說移植就完成了,而後便沒必要對代碼文件進行任何修改就能夠直接使用,接下來是採集部分:
我是把採集放在main中進行。
/* 喚醒6804 */ wakeup_sleep(); /* 啓動電壓採集 */ LTC6804_adcv(); delay_ms(50); /* 讀取電壓 */ res = LTC6804_rdcv(0, TOTAL_IC, vol_buff);
以上即可以採集出電壓了。
※若是發現幾個級聯起來的6804,有些片子能夠運行正常通訊,有些又不能夠運行甚至沒法通訊,在排除硬件的緣由之後,能夠查看一下這個地方:wakeup_sleep(),試着把喚醒時間設置的長一些。
最後:能夠看出來,精度仍是不錯的~
本文結束!