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

【经验分享】基于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线通信,不过我没有用)
% f" ?+ e8 Z8 ~) G
. F9 _, V6 u4 Y( z( f% q% e
  下载下来的代码是C++文件,不能直接在STM32上使用,需要进行一些修改。
  首先修改后缀名,改成C文件,然后打开LTC6804.c文件。
. U7 M3 h4 Z' Z7 r$ C
第一步进行驱动的移植:
  1. void spi_write_array(uint8_t len, // Option: Number of bytes to be written on the SPI port( ^9 |1 E6 {! `" h& G% Q
  2.                      uint8_t data[] //Array of bytes to be written on the SPI port
    1 x  P2 _" h0 y( Y
  3.                      )
    8 ~$ O; a* k1 N& G/ [
  4. {
    3 \) n- ~3 y& X1 C% k0 N& K" _. K5 B
  5.     uint8_t i;3 @: J1 Y  x0 P7 k9 D  Q
  6. ; |# C; G# W  y# }+ n) k1 w
  7.     for(i = 0; i < len; i++)8 h& f  W) s! |! {4 Y' L* q& w
  8.     {
    6 Z- y* J6 K/ B; |
  9.         SPI2_Send_byte((int8_t)data[i]);
    * N3 ?& e# X$ }$ i
  10.     }
    % o1 B! i1 a5 W8 k
  11. }
复制代码
  1. void spi_write_read(uint8_t tx_Data[],//array of data to be written on SPI port& M# r7 t$ ^$ C9 ~9 p  B7 E. s
  2.                     uint8_t tx_len, //length of the tx data arry$ Z& Z( Z8 {" z, p3 i1 Y3 N- q
  3.                     uint8_t *rx_data,//Input: array that will store the data read by the SPI port) v8 J( N- Y6 _/ ]3 i8 x$ }- T
  4.                     uint8_t rx_len //Option: number of bytes to be read from the SPI port* z/ z& w. `+ d( r; `
  5.                     )
    - j. \5 i) u0 C3 t& ~: {/ C
  6. {
    ( D, K& ?5 m+ f: S& T/ D$ r: n" }) `! Z
  7.     uint8_t i;& r( L! `: ~* c# k0 Q# a
  8. 5 Z9 a7 @& q# o5 o2 h( y8 {
  9.     for(i = 0; i < tx_len; i++)
    5 ?$ u; K0 P' n
  10.     {
    * y5 T9 U) X4 r% h/ b. K) N
  11.         SPI2_Send_byte(tx_Data[i]);' l4 F& ]8 f8 O1 ~( p
  12.     }
    % I! r  `; @% {  R

  13. ' t! X" L8 t8 P3 M* H3 T
  14.     for(i = 0; i < rx_len; i++)
    " ^8 A: s/ O# Z) ?' E* Q
  15.     {' e8 g: v2 J4 K/ n# Q+ x" h+ g: H
  16.         rx_data[i] = (uint8_t)SPI2_Receive_byte();
    5 {+ ?1 s6 f% Z7 n
  17.     }" _% a$ S1 h) s- H
  18. " p! b* N, b7 G" D6 s# C! j
  19. }
复制代码
" Z! l; ~4 l4 D+ e( l. E
只需要把自己的SPI驱动替换上去就可以了。
: Y/ C% h6 F2 q4 F3 r, B
  1. void wakeup_idle()7 d9 e: l8 W8 w3 S8 j. u
  2. {$ }* d6 s  g- A0 |# ?" H
  3.   output_low(LTC6804_CS);+ [- A3 n: y* d' A5 C. ^5 z
  4.   delayMicroseconds(2); //Guarantees the isoSPI will be in ready mode/ t. C& C7 j$ H7 e% B
  5.   output_high(LTC6804_CS);
    5 ?- z8 V$ K# }- s& c
  6. }
复制代码
8 o. @: w' |2 F; w% ?
自己把这个函数中间的部分实现,或者替换成自己的函数:
  1. void wakeup_idle(void)
    ' Y- E, y5 R% B  R. y0 [2 d, x/ y
  2. {. ]+ t( \2 x& f, k3 ^$ J3 e& g1 S
  3.   output_low(LTC6804_CS);$ K8 A" ]3 m' \& C  C2 M
  4.   delay_ms(4); //Guarantees the isoSPI will be in ready mode
    ' }" @. f( z# J, w1 J! B
  5.   output_high(LTC6804_CS);2 f1 J2 A4 E- _9 M
  6. }
复制代码
* J! j2 N4 ]% F6 B' K
下面是原版的初始化函数:
  1. void LTC6804_initialize()
    6 k" g2 m+ K' @
  2. {) Q1 g8 E% J* S3 S& c* z( x+ \
  3.   quikeval_SPI_connect();# x+ a. u8 h6 w, q1 R+ g
  4.   spi_enable(SPI_CLOCK_DIV16); // This will set the Linduino to have a 1MHz Clock
    5 O; {* B) v+ X3 L* K3 b. `
  5.   set_adc(MD_NORMAL,DCP_DISABLED,CELL_CH_ALL,AUX_CH_ALL);
    5 E$ \' L" ^4 G: A
  6. }
复制代码
# j  C) _& k& C9 O2 u6 x) T
我把它根据自己的实际情况修改一下 :
  1. void LTC6804_initialize(void)
    2 t+ o4 E1 ~0 k3 e- ?& w
  2. {
    + G+ }: |1 B8 R+ Y2 t3 W
  3.     Drive_LTC6804_Spi_Init();//SPI外设初始化* n: P4 E, O7 z9 v1 A' c( @5 @( K8 w
  4.     init_cfg();        //配置LTC6804的寄存器
    5 P$ x# Y! B: F! F, {8 Z
  5.     set_adc(MD_FILTERED,DCP_DISABLED,CELL_CH_ALL,AUX_CH_GPIO1);//设置转换方式等* D0 ]1 b# f. S. ]* [  ~1 W
  6.     wakeup_sleep();//唤醒芯片
    6 E2 l" k$ v# p! U9 M5 Q- t
  7.     LTC6804_wrcfg(TOTAL_IC,tx_cfg);//把上面的设置写入芯片6 R2 R/ J! v8 M& |$ S! p. M& @0 b) [
  8.     if (LTC6804_rdcfg(TOTAL_IC,rx_cfg) == -1)  //检查一下到底有没有配置成功1 O, }9 I7 q1 L7 M( x
  9.     {
    * q  t. t0 c0 Z3 F2 x& o( C
  10.         printf("LTC6804_MODULAR INIT NG!\n\r");
    - {6 R6 a! Q7 Y+ i
  11.     }; ~" R0 c" y4 p' L, S
  12.     else5 q; z+ N/ ~7 t2 ]1 w( V2 i
  13.     {3 Z% W3 E! \. S" ^" h
  14.         printf("LTC6804_MODULAR INIT OK!\n\r");
      ~3 s2 Q; t" R3 A
  15.     }2 f- K2 \- R9 B0 t2 O
  16. 4 E. l7 m0 P9 I2 I3 Y; q
  17. }
复制代码
  1. //手册第49页6 q" N* t* Q, r; D# U, p" H
  2. /* 寄存器               8         7          6         5         4         3         2        1        */* C* z" a7 b* ]7 s2 ~# C' W" S
  3. //CFGR0       RD/WR   GPIO5     GPIO4      GPIO3     GPIO2     GPIO1     REFON     SWTRD    ADCOPT
    + E/ \4 L' B! \7 e! ]" i
  4. //CFGR1       RD/WR   VUV[7]    VUV[6]     VUV[5]    VUV[4]    VUV[3]    VUV[2]    VUV[1]   VUV[0]+ b! ~% W+ ?( P  X8 J
  5. //CFGR2       RD/WR   VOV[3]    VOV[2]     VOV[1]    VOV[0]    VUV[11]   VUV[10]   VUV[9]   VUV[8]) ~/ ]2 l) E6 I% D3 D# u& `
  6. //CFGR3       RD/WR   VOV[11]   VOV[10]    VOV[9]    VOV[8]    VOV[7]    VOV[6]    VOV[5]   VOV[4]
    + |$ m1 F& `/ d
  7. //CFGR4       RD/WR   DCC8      DCC7       DCC6      DCC5      DCC4      DCC3      DCC2     DCC13 W: X  a* q+ c8 ~
  8. //CFGR5       RD/WR   DCTO[3]   DCTO[2]    DCTO[1]   DCTO[0]   DCC12     DCC11     DCC10    DCC9
    7 P/ y3 ]2 D% }& D/ E9 _6 D1 z
  9. void init_cfg(void)
    ! j, A' Z% Z9 O
  10. {
    " m6 b; P6 Y$ `% g+ ^
  11.     int i;
    5 T/ B  b/ Y3 T1 S5 }( Y& P9 r

  12. 2 {* `6 S' J. ^4 I
  13.     for(i = 0; i<TOTAL_IC;i++)
    & T! C1 e3 }% b' p
  14.     {
    & R% U8 _* B. k0 g- ^6 ~3 v
  15.         tx_cfg[i][0] = 0xFE ;   //GPIO引脚下拉电路关断(bit8~bit4) | 基准保持上电状态(bit3) | SWTEN处于逻辑1(软件定时器) | ADC模式选择为0% v0 B: S- s) h
  16.         tx_cfg[i][1] = 0x00 ;   //不使用欠压比较功能
    ! `( A6 K" _0 N+ E
  17.         tx_cfg[i][2] = 0x00 ;   //不使用过压比较功能
    ! j& Y2 E/ u: v# Z3 W: ~$ O
  18.         tx_cfg[i][3] = 0x00 ;
    4 a/ g9 V6 O; n. |2 y& `4 ]1 @
  19.         tx_cfg[i][4] = 0x00 ;   //不使用电池放电功能
    9 K1 `1 F& P# N8 t5 W6 k- N& p
  20.         tx_cfg[i][5] = 0x00 ;   //放电超时时间' a8 q  q8 \% v1 D6 _
  21.     }
    " k9 f5 i+ v7 U* F) I
  22. }
复制代码
$ e, C& t5 g# J0 N/ H# V3 W5 E7 d

% [! @5 V* K1 U- f3 `9 T7 V1 p
这里只使用了最基本的电压采集,其他的功能都没有用。
上面的代码里面有一个宏 :TOTAL_IC。
这个宏是用来定义一共有几片LTC6804-1的,比如我这次使用了2片,那么它的值就是2.
上面的寄存器设置,可以参考手册:
1050425-20190403172123490-1539331691.png
比如需要追加一些别的功能,便可以根据手册的寄存器进行设置,比如设置报警,设置均衡,设置其他的功能。
以上初始化部分就完成了,或者说移植就完成了,然后便不必对代码文件进行任何修改就可以直接使用,接下来是采集部分:
我是把采集放在main中进行。
  1. /* 唤醒6804 */! {" p0 |( [" j# G9 g
  2.         wakeup_sleep();
    7 |6 z0 d5 L2 V* y7 J
  3.         /* 启动电压采集 */5 m- n; u( B0 O7 W, b
  4.         LTC6804_adcv();
    6 m- ~+ d0 f$ a7 W! C
  5.         delay_ms(50);
    ( W* U' P1 l: u6 E$ f
  6.         /* 读取电压 */* {6 q* B' \& e7 q4 E& ~
  7.         res = LTC6804_rdcv(0, TOTAL_IC, vol_buff);
复制代码
) A& t$ s6 N' u5 J0 T3 d4 ]3 _
以上便可以采集出电压了。
6 u  x9 _; B7 U0 Q! D
※如果发现几个级联起来的6804,有些片子可以运行正常通信,有些又不可以运行甚至无法通信,在排除硬件的原因以后,可以查看一下这个地方:wakeup_sleep(),试着把唤醒时间设置的长一些。

- n& [- ]- a& v$ I7 _
最后:可以看出来,精度还是不错的~
; D% m, {: M3 ^# [/ W$ x* z7 n* ~
收藏 评论0 发布时间:2022-1-18 22:27

举报

0个回答

所属标签

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版