• 注册 / 登录
  • 切换到窄版
  • 查看: 3192|回复: 0

    BMS系统设计入门分析(下)

    [复制链接]

    665

    主题

    679

    帖子

    6476

    积分

    版主

    Rank: 7Rank: 7Rank: 7

    积分
    6476
    发表于 2022-2-12 15:17:00 | 显示全部楼层 |阅读模式

    路线栈欢迎您!

    您需要 登录 才可以下载或查看,没有帐号?立即注册

    x
    BMS前端芯讲解

    在电动车的BMS项目中用到了LTC6804这块片子,初次使用它的采集精度确实令我惊讶到了,设备用于监测2V的铅酸电池组,硬件上几乎没有加任何滤波,直接读取数据就能达到3mv以下的精度,片子真的很好用。

    下面总结一下自己的使用心得。
    ------------------------------------------------------------------------------------------------
    0.png

    LTC6804是一款专门用来做多节电池电池组的监测芯片,最高可监测12节电池,官方误差是低于1.2mv,12 个通道的最快采样速度可以达到290us。

    芯片分为两种型号,6804-1和6804-2,区别在于,6804-1采用级联的形式(级联控制),6804-2采用并联形式(分开控制)。

    除开硬件连接之外,这两种型号的操作都是大同小异,基本可以视为一样,本文以6804-1为例进行讲解。

    1.png

    原理图和手册中的推荐一样,就不贴出来了,MCU与芯片的通信方式采用四线SPI,这种通信方式很常见,各种MCU的驱动也好找。(看了数据手册,芯片似乎还支持IIC和2线通信,不过我没有用)

    驱动代码可以从本文附件去下载

    下载下来的代码是C++文件,不能直接在STM32上使用,需要进行一些修改。

    首先修改后缀名,改成C文件,然后打开LTC6804.c文件。

    第一步进行驱动的移植:
    1. void spi_write_array(uint8_t len, // Option: Number of bytes to be written on the SPI port
    2.                      uint8_t data[] //Array of bytes to be written on the SPI port
    3.                      )
    4. {
    5.     uint8_t i;

    6.     for(i = 0; i < len; i++)
    7.     {
    8.         SPI2_Send_byte((int8_t)data[i]);
    9.     }
    10. }
    复制代码
    1. void spi_write_read(uint8_t tx_Data[],//array of data to be written on SPI port
    2.                     uint8_t tx_len, //length of the tx data arry
    3.                     uint8_t *rx_data,//Input: array that will store the data read by the SPI port
    4.                     uint8_t rx_len //Option: number of bytes to be read from the SPI port
    5.                     )
    6. {
    7.     uint8_t i;

    8.     for(i = 0; i < tx_len; i++)
    9.     {
    10.         SPI2_Send_byte(tx_Data[i]);
    11.     }

    12.     for(i = 0; i < rx_len; i++)
    13.     {
    14.         rx_data[i] = (uint8_t)SPI2_Receive_byte();
    15.     }

    16. }
    复制代码
    只需要把自己的SPI驱动替换上去就可以了。
    1. void wakeup_idle()
    2. {
    3.   output_low(LTC6804_CS);
    4.   delayMicroseconds(2); //Guarantees the isoSPI will be in ready mode
    5.   output_high(LTC6804_CS);
    6. }
    复制代码

    自己把这个函数中间的部分实现,或者替换成自己的函数:
    1. void wakeup_idle(void)
    2. {
    3.   output_low(LTC6804_CS);
    4.   delay_ms(4); //Guarantees the isoSPI will be in ready mode
    5.   output_high(LTC6804_CS);
    6. }
    复制代码

    下面是原版的初始化函数:
    1. void LTC6804_initialize()
    2. {
    3.   quikeval_SPI_connect();
    4.   spi_enable(SPI_CLOCK_DIV16); // This will set the Linduino to have a 1MHz Clock
    5.   set_adc(MD_NORMAL,DCP_DISABLED,CELL_CH_ALL,AUX_CH_ALL);
    6. }
    复制代码

    我把它根据自己的实际情况修改一下 :
    1. void LTC6804_initialize(void)
    2. {
    3.     Drive_LTC6804_Spi_Init();//SPI外设初始化
    4.     init_cfg();        //配置LTC6804的寄存器
    5.     set_adc(MD_FILTERED,DCP_DISABLED,CELL_CH_ALL,AUX_CH_GPIO1);//设置转换方式等
    6.     wakeup_sleep();//唤醒芯片
    7.     LTC6804_wrcfg(TOTAL_IC,tx_cfg);//把上面的设置写入芯片
    8.     if (LTC6804_rdcfg(TOTAL_IC,rx_cfg) == -1)  //检查一下到底有没有配置成功
    9.     {
    10.         printf("LTC6804_MODULAR INIT NG!\n\r");
    11.     }
    12.     else
    13.     {
    14.         printf("LTC6804_MODULAR INIT OK!\n\r");
    15.     }

    16. }
    复制代码
    1. //手册第49页
    2. /* 寄存器               8         7          6         5         4         3         2        1        */
    3. //CFGR0       RD/WR   GPIO5     GPIO4      GPIO3     GPIO2     GPIO1     REFON     SWTRD    ADCOPT
    4. //CFGR1       RD/WR   VUV[7]    VUV[6]     VUV[5]    VUV[4]    VUV[3]    VUV[2]    VUV[1]   VUV[0]
    5. //CFGR2       RD/WR   VOV[3]    VOV[2]     VOV[1]    VOV[0]    VUV[11]   VUV[10]   VUV[9]   VUV[8]
    6. //CFGR3       RD/WR   VOV[11]   VOV[10]    VOV[9]    VOV[8]    VOV[7]    VOV[6]    VOV[5]   VOV[4]
    7. //CFGR4       RD/WR   DCC8      DCC7       DCC6      DCC5      DCC4      DCC3      DCC2     DCC1
    8. //CFGR5       RD/WR   DCTO[3]   DCTO[2]    DCTO[1]   DCTO[0]   DCC12     DCC11     DCC10    DCC9
    9. void init_cfg(void)
    10. {
    11.     int i;

    12.     for(i = 0; i<TOTAL_IC;i++)
    13.     {
    14.         tx_cfg[i][0] = 0xFE ;   //GPIO引脚下拉电路关断(bit8~bit4) | 基准保持上电状态(bit3) | SWTEN处于逻辑1(软件定时器) | ADC模式选择为0
    15.         tx_cfg[i][1] = 0x00 ;   //不使用欠压比较功能
    16.         tx_cfg[i][2] = 0x00 ;   //不使用过压比较功能
    17.         tx_cfg[i][3] = 0x00 ;
    18.         tx_cfg[i][4] = 0x00 ;   //不使用电池放电功能
    19.         tx_cfg[i][5] = 0x00 ;   //放电超时时间
    20.     }
    21. }
    复制代码

    这里只使用了最基本的电压采集,其他的功能都没有用。

    上面的代码里面有一个宏 :TOTAL_IC。

    这个宏是用来定义一共有几片LTC6804-1的,比如我这次使用了2片,那么它的值就是2.

    上面的寄存器设置,可以参考手册:

    2.png

    比如需要追加一些别的功能,便可以根据手册的寄存器进行设置,比如设置报警,设置均衡,设置其他的功能。

    以上初始化部分就完成了,或者说移植就完成了,然后便不必对代码文件进行任何修改就可以直接使用,接下来是采集部分:

    我是把采集放在main中进行。
    1. /* 唤醒6804 */
    2.         wakeup_sleep();
    3.         /* 启动电压采集 */
    4.         LTC6804_adcv();
    5.         delay_ms(50);
    6.         /* 读取电压 */
    7.         res = LTC6804_rdcv(0, TOTAL_IC, vol_buff);
    复制代码

    以上便可以采集出电压了。

    ※如果发现几个级联起来的6804,有些片子可以运行正常通信,有些又不可以运行甚至无法通信,在排除硬件的原因以后,可以查看一下这个地方:wakeup_sleep(),试着把唤醒时间设置的长一些。

    最后:可以看出来,精度还是不错的!

    3.png

    LTC6804-1&amp;2中文手册.rar

    1.09 MB, 下载次数: 20

    LTC6804_GUI_V052_20121127.zip

    725.66 KB, 下载次数: 35

    LTC6804代码文件.rar

    29.03 KB, 下载次数: 17

    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    小黑屋|路丝栈 ( 粤ICP备2021053448号 )

    GMT+8, 2024-9-17 03:40 , Processed in 0.059717 second(s), 22 queries .

    Powered by Discuz! X3.4

    Copyright © 2001-2021, Tencent Cloud.

    快速回复 返回顶部 返回列表