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

【经验分享】基于STM32的LTC6804驱动代码解析

[复制链接]
STMCU小助手 发布时间:2022-1-18 22:27
 LTC6804是一款专门用来做多节电池电池组的监测芯片,最高可监测12节电池,官方误差是低于1.2mv,12 个通道的最快采样速度可以达到290us。
  芯片分为两种型号,6804-1和6804-2,区别在于,6804-1采用级联的形式(级联控制),6804-2采用并联形式(分开控制)。
  除开硬件连接之外,这两种型号的操作都是大同小异,基本可以视为一样,本文以6804-1为例进行讲解。
  1050425-20190403170526219-977762557.png  
  原理图和手册中的推荐一样,就不贴出来了,MCU与芯片的通信方式采用四线SPI,这种通信方式很常见,各种MCU的驱动也好找。(看了数据手册,芯片似乎还支持IIC和2线通信,不过我没有用)

5 `6 L' y5 |/ p
0 v; w1 [* i( j$ M, P" O, D
  下载下来的代码是C++文件,不能直接在STM32上使用,需要进行一些修改。
  首先修改后缀名,改成C文件,然后打开LTC6804.c文件。

# [! W! V/ U1 _: Z9 V* B
第一步进行驱动的移植:
  1. void spi_write_array(uint8_t len, // Option: Number of bytes to be written on the SPI port7 J- ~$ v  {; F3 w: u( V7 T
  2.                      uint8_t data[] //Array of bytes to be written on the SPI port4 I6 ?$ i/ q) b1 \( J
  3.                      )$ x; S, d; b" U. x
  4. {" m4 Z$ A  M: f* x4 s+ ^! q+ H+ \3 {
  5.     uint8_t i;- h0 p3 M" p3 S$ ~1 v6 \

  6. 9 i% F# ^7 |% }
  7.     for(i = 0; i < len; i++)" `7 n) n. X4 @; q9 j5 ~3 N3 A
  8.     {1 a; \( p) [/ f6 [9 X
  9.         SPI2_Send_byte((int8_t)data[i]);4 ^+ z" o8 F: H9 V+ S- ?
  10.     }
    * N7 v, I" q* k
  11. }
复制代码
  1. void spi_write_read(uint8_t tx_Data[],//array of data to be written on SPI port+ Y9 K- ?1 U6 B; W9 ?
  2.                     uint8_t tx_len, //length of the tx data arry2 o) J; D( @4 [  w: \+ d( z
  3.                     uint8_t *rx_data,//Input: array that will store the data read by the SPI port
    0 L( E0 P# @; u( u, d/ W4 C1 Z
  4.                     uint8_t rx_len //Option: number of bytes to be read from the SPI port
      p) s+ S( g3 f4 R; Q/ |
  5.                     )
    ; k) v( ]# r; U2 Y/ v- b
  6. {. q$ [5 J; A, Y& }4 L/ `: k. \
  7.     uint8_t i;% X( ^' J9 U6 _3 O4 U# s6 \+ F

  8. + {  d: ?5 q7 a
  9.     for(i = 0; i < tx_len; i++): o2 u9 E' G3 {  b
  10.     {: Z9 A' l3 t  ^+ \
  11.         SPI2_Send_byte(tx_Data[i]);
    6 k. Y, v$ d. u, y) c
  12.     }
    9 E1 D: V7 j$ ^0 l
  13. - u: q) k8 l' }* O$ f" M' A
  14.     for(i = 0; i < rx_len; i++)$ ~- ~7 H) W" y& U$ i$ J! W
  15.     {2 e$ Q9 e4 P* s5 ^. M: C
  16.         rx_data[i] = (uint8_t)SPI2_Receive_byte();( U5 H! Z6 w; o; f; o" |' C4 i; ^
  17.     }
    * v! j, `) O) q+ u& [
  18. 3 C* A' {% ^, X. ?/ T2 p" q
  19. }
复制代码
- q+ {$ h& }4 V' ^- W6 E# `
只需要把自己的SPI驱动替换上去就可以了。
" a3 G! L( M1 n6 Q% G
  1. void wakeup_idle()1 ?# T1 n: h5 y: x& w$ v
  2. {
    & U; W! i2 v  ], J5 y4 w& U
  3.   output_low(LTC6804_CS);
    3 W) c/ n- G  M4 `
  4.   delayMicroseconds(2); //Guarantees the isoSPI will be in ready mode; Z' |0 o0 D! v. ~" c9 b$ u9 X
  5.   output_high(LTC6804_CS);/ Z/ `6 }; q; Q5 W' d  i, a
  6. }
复制代码
- k& V# j: g- R- X2 Q
自己把这个函数中间的部分实现,或者替换成自己的函数:
  1. void wakeup_idle(void): a" K' X1 {; [7 J0 _) c
  2. {
    & r- J: m" |- o& U4 l
  3.   output_low(LTC6804_CS);
    ( c6 W2 r7 m9 _- ]9 ~1 i* B
  4.   delay_ms(4); //Guarantees the isoSPI will be in ready mode
    : ?  K7 @" E" k1 e' X
  5.   output_high(LTC6804_CS);
    % q6 x, i! D6 u- I0 p
  6. }
复制代码
4 r( b' |8 ^" g  o  I* w
下面是原版的初始化函数:
  1. void LTC6804_initialize()
    # N6 `" h0 N1 o1 S3 X
  2. {- D8 t' _5 E% A; P& G6 f' q. _' q
  3.   quikeval_SPI_connect();8 u" t- t( V: V' ]6 m2 @/ u8 B8 T0 b
  4.   spi_enable(SPI_CLOCK_DIV16); // This will set the Linduino to have a 1MHz Clock: }3 r7 h/ h' M4 S* t/ B4 V- L
  5.   set_adc(MD_NORMAL,DCP_DISABLED,CELL_CH_ALL,AUX_CH_ALL);
    2 G( \2 g$ W3 f  f5 s! s1 F; t
  6. }
复制代码
4 H! U# y+ M$ L' E; {
我把它根据自己的实际情况修改一下 :
  1. void LTC6804_initialize(void)
    6 J$ U% m/ s- D+ a  ^
  2. {4 ^. R4 j: U8 A/ F; e
  3.     Drive_LTC6804_Spi_Init();//SPI外设初始化- `. Q; Y8 ~/ [6 i; f1 B' d: C
  4.     init_cfg();        //配置LTC6804的寄存器
    1 t; c9 ?5 Z; m/ U' E' u* _
  5.     set_adc(MD_FILTERED,DCP_DISABLED,CELL_CH_ALL,AUX_CH_GPIO1);//设置转换方式等
    8 d1 W+ J$ ^6 f% a0 Q' N: U) X
  6.     wakeup_sleep();//唤醒芯片7 |$ [  y9 c' S; l) W: ~7 X
  7.     LTC6804_wrcfg(TOTAL_IC,tx_cfg);//把上面的设置写入芯片1 Z% m8 Y2 p: j7 l: _- P
  8.     if (LTC6804_rdcfg(TOTAL_IC,rx_cfg) == -1)  //检查一下到底有没有配置成功8 d0 B* h4 J9 v$ W5 {
  9.     {
    , m3 F% y6 Z0 h
  10.         printf("LTC6804_MODULAR INIT NG!\n\r");
    - U& L! r7 ]1 R, G6 V
  11.     }3 s) v! k( \  l
  12.     else/ a1 H6 J; T* o8 ]+ k/ l! `6 d
  13.     {$ z5 X& z: e8 ~# B
  14.         printf("LTC6804_MODULAR INIT OK!\n\r");3 z, U  R: o9 d& N, Y8 V, J
  15.     }- E) `4 G" ]. d

  16.   T2 t/ E; d4 A) ^% o5 f
  17. }
复制代码
  1. //手册第49页
    ; A; A2 ^  m* x
  2. /* 寄存器               8         7          6         5         4         3         2        1        */* N' U' q# M) X; _
  3. //CFGR0       RD/WR   GPIO5     GPIO4      GPIO3     GPIO2     GPIO1     REFON     SWTRD    ADCOPT! U& h6 Y( r" F, W6 s
  4. //CFGR1       RD/WR   VUV[7]    VUV[6]     VUV[5]    VUV[4]    VUV[3]    VUV[2]    VUV[1]   VUV[0]2 ~' B3 Y6 |( w' K& O1 {! w& o3 f
  5. //CFGR2       RD/WR   VOV[3]    VOV[2]     VOV[1]    VOV[0]    VUV[11]   VUV[10]   VUV[9]   VUV[8]3 b3 A; H/ i. v& l$ V0 L
  6. //CFGR3       RD/WR   VOV[11]   VOV[10]    VOV[9]    VOV[8]    VOV[7]    VOV[6]    VOV[5]   VOV[4]6 B0 c( }  x8 s9 J0 F( Q1 ~8 C
  7. //CFGR4       RD/WR   DCC8      DCC7       DCC6      DCC5      DCC4      DCC3      DCC2     DCC1
    4 G% o% I$ \2 T7 R* \0 E8 ]( @' n" u: V
  8. //CFGR5       RD/WR   DCTO[3]   DCTO[2]    DCTO[1]   DCTO[0]   DCC12     DCC11     DCC10    DCC9; H. I4 \4 `, Q1 q/ v3 P
  9. void init_cfg(void)3 j9 m9 S  i/ i6 Q; e
  10. {" M1 G5 @/ q6 m( I1 g2 I: a
  11.     int i;/ P6 L; g: l4 e! L+ q$ I

  12. $ m/ C( K& }( C+ M$ A. l
  13.     for(i = 0; i<TOTAL_IC;i++)) L: X$ v- G' O4 }* X
  14.     {/ Q: X2 u8 E& l* t- S% w- |" ^
  15.         tx_cfg[i][0] = 0xFE ;   //GPIO引脚下拉电路关断(bit8~bit4) | 基准保持上电状态(bit3) | SWTEN处于逻辑1(软件定时器) | ADC模式选择为0
    7 d$ l: Q2 [& N7 g+ U; ?. o, v, B
  16.         tx_cfg[i][1] = 0x00 ;   //不使用欠压比较功能' F  v+ Q7 s4 Y3 p5 }' h" m# V: ]
  17.         tx_cfg[i][2] = 0x00 ;   //不使用过压比较功能
    ! R% t7 _# d) I2 J9 d+ {: `
  18.         tx_cfg[i][3] = 0x00 ;
    6 M, q5 }3 D3 c& A
  19.         tx_cfg[i][4] = 0x00 ;   //不使用电池放电功能9 y" e9 r' Y* ]7 M( c3 x& s$ _
  20.         tx_cfg[i][5] = 0x00 ;   //放电超时时间  O3 e& @# G" A6 q$ K3 }
  21.     }  D. c1 q$ }, v0 s( }
  22. }
复制代码

5 t$ M5 D# x+ l& ?
+ I" \# A( w9 k" g  P% w: w, D
这里只使用了最基本的电压采集,其他的功能都没有用。
上面的代码里面有一个宏 :TOTAL_IC。
这个宏是用来定义一共有几片LTC6804-1的,比如我这次使用了2片,那么它的值就是2.
上面的寄存器设置,可以参考手册:
1050425-20190403172123490-1539331691.png
比如需要追加一些别的功能,便可以根据手册的寄存器进行设置,比如设置报警,设置均衡,设置其他的功能。
以上初始化部分就完成了,或者说移植就完成了,然后便不必对代码文件进行任何修改就可以直接使用,接下来是采集部分:
我是把采集放在main中进行。
  1. /* 唤醒6804 */& C* b$ E% T4 w) _& @) {/ S3 E
  2.         wakeup_sleep();) v: f5 `1 D9 E$ R3 w7 Q) M. V' f2 X
  3.         /* 启动电压采集 */9 e; j3 Y! S, @% W
  4.         LTC6804_adcv();, R8 {2 o- t; v
  5.         delay_ms(50);
    2 ~: z+ a; t4 e6 l  K
  6.         /* 读取电压 */
    1 _( d$ X/ L' D
  7.         res = LTC6804_rdcv(0, TOTAL_IC, vol_buff);
复制代码

1 N$ `( }' b) a( r, l
以上便可以采集出电压了。
" d# T4 J; P5 Q
※如果发现几个级联起来的6804,有些片子可以运行正常通信,有些又不可以运行甚至无法通信,在排除硬件的原因以后,可以查看一下这个地方:wakeup_sleep(),试着把唤醒时间设置的长一些。
8 n) ~' P! G9 i/ P
最后:可以看出来,精度还是不错的~
: ^* w; w0 c! X+ |5 v' [, ]
收藏 评论0 发布时间:2022-1-18 22:27

举报

0个回答
关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新和工艺
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版