在上次项目中用到了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(),试着把唤醒时间设置的长一些。
最后:能够看出来,精度仍是不错的~
本文结束!