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

【经验分享】基于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线通信,不过我没有用)
: v8 s% I2 E7 ^) v0 f9 I
" L2 H0 O& d9 \
  下载下来的代码是C++文件,不能直接在STM32上使用,需要进行一些修改。
  首先修改后缀名,改成C文件,然后打开LTC6804.c文件。

( ~6 N( E& E! J5 B, @8 I  z8 ~( j& _# t
第一步进行驱动的移植:
  1. void spi_write_array(uint8_t len, // Option: Number of bytes to be written on the SPI port9 s8 ~/ E, r# {$ B8 h7 L/ Y& T
  2.                      uint8_t data[] //Array of bytes to be written on the SPI port
    , M" k% r6 ?) M, |7 F/ F) n8 \
  3.                      )
    9 R- w0 q# k6 S2 @9 d
  4. {
    5 p$ ^' X# e2 @; ^8 d
  5.     uint8_t i;
    4 s/ C( A1 ~/ {+ ]
  6. " e0 \' l% t1 z' C9 V5 b; i! C* w) Q
  7.     for(i = 0; i < len; i++)
    + N& C; `! h- b
  8.     {
    , C( y8 N4 o* W' e
  9.         SPI2_Send_byte((int8_t)data[i]);& }3 I2 Z+ W, a$ X4 `6 V
  10.     }
    - a! u0 \% m" r; b4 i5 ~
  11. }
复制代码
  1. void spi_write_read(uint8_t tx_Data[],//array of data to be written on SPI port
    : l( w6 S7 W/ I1 W! B2 g
  2.                     uint8_t tx_len, //length of the tx data arry$ H% s3 K2 \' j6 J" d- M+ ?
  3.                     uint8_t *rx_data,//Input: array that will store the data read by the SPI port
    ) i: \9 \- D/ R$ a( v( Q- n$ a
  4.                     uint8_t rx_len //Option: number of bytes to be read from the SPI port; H* z2 X% n/ X8 [% X& W
  5.                     )$ Y% S7 s6 q7 D
  6. {6 q  f5 w8 ]% P$ I6 _
  7.     uint8_t i;1 \  ~& y6 W8 _) k
  8. - v! B9 ]! e& ~2 |- F. {4 n
  9.     for(i = 0; i < tx_len; i++)/ `' |, Z% K$ e7 J* }
  10.     {
    1 @6 e$ M0 I  D$ [0 h1 J
  11.         SPI2_Send_byte(tx_Data[i]);/ R, ^9 N4 p0 v2 e7 y
  12.     }$ D0 Q8 e' J" A7 s* f$ g7 X

  13. 2 S9 V" g+ z& i
  14.     for(i = 0; i < rx_len; i++)7 ?7 l7 G! `, p$ A- w4 I# C* I- m
  15.     {9 [2 n2 p+ Q9 W( u, b7 {) D- Q& u
  16.         rx_data[i] = (uint8_t)SPI2_Receive_byte();6 E' r3 ^. f7 M7 t0 M1 t" B6 z: ^. e
  17.     }2 H( B# ?+ n) X# r, C" r$ J
  18. 1 ~+ c9 r: |( R  F  o; X' N( Y
  19. }
复制代码
4 I$ I9 [! O0 d/ ~, ~: e4 j' G
只需要把自己的SPI驱动替换上去就可以了。

7 U3 s+ @( H5 g5 ~8 U. c$ m
  1. void wakeup_idle(); l' L; ]& t8 ?5 m5 C7 k$ k0 G: q
  2. {' u8 G0 x  r( s. ~8 R# `
  3.   output_low(LTC6804_CS);3 I* N% k% _& v6 u
  4.   delayMicroseconds(2); //Guarantees the isoSPI will be in ready mode
    - G3 Q- P5 G! ^9 h
  5.   output_high(LTC6804_CS);
    2 n$ M$ m$ K7 v9 X
  6. }
复制代码

" s9 r3 [3 I5 b, b4 x
自己把这个函数中间的部分实现,或者替换成自己的函数:
  1. void wakeup_idle(void)
    ! ]- h1 b7 j/ _: w* [# Q2 q
  2. {
    / k! _+ C; g; }& {+ b
  3.   output_low(LTC6804_CS);: m2 A3 B  _3 f* V, j$ D
  4.   delay_ms(4); //Guarantees the isoSPI will be in ready mode7 |8 G/ X! V0 l- e' ~
  5.   output_high(LTC6804_CS);
    8 f" F1 }* V8 ^  @  ~  t9 j
  6. }
复制代码

  S" f/ V& y3 A2 q$ A( }2 A
下面是原版的初始化函数:
  1. void LTC6804_initialize()
    ; f3 L1 N% t7 `( B
  2. {
    9 L; _. T. U9 e" [3 V1 [8 I
  3.   quikeval_SPI_connect();
    : S* @, d% D' E  ~+ i
  4.   spi_enable(SPI_CLOCK_DIV16); // This will set the Linduino to have a 1MHz Clock
    1 k) i# j# }5 @6 k5 i
  5.   set_adc(MD_NORMAL,DCP_DISABLED,CELL_CH_ALL,AUX_CH_ALL);4 c. H$ ]7 Q8 o- m8 ?# ?- R+ O
  6. }
复制代码

& a- H: B  O1 v9 r
我把它根据自己的实际情况修改一下 :
  1. void LTC6804_initialize(void)
      Y9 c2 @( H, j  Y3 P
  2. {8 K' c6 r& _: j) \' @8 h4 B
  3.     Drive_LTC6804_Spi_Init();//SPI外设初始化
    6 W! c1 V& Q( R; L0 I
  4.     init_cfg();        //配置LTC6804的寄存器# _! U$ @. L* D8 P0 u4 N. C
  5.     set_adc(MD_FILTERED,DCP_DISABLED,CELL_CH_ALL,AUX_CH_GPIO1);//设置转换方式等
    7 e/ G7 L* `5 [; \% O/ H
  6.     wakeup_sleep();//唤醒芯片2 h: {. v; x2 r2 C' i
  7.     LTC6804_wrcfg(TOTAL_IC,tx_cfg);//把上面的设置写入芯片2 a  _( X! Z! N
  8.     if (LTC6804_rdcfg(TOTAL_IC,rx_cfg) == -1)  //检查一下到底有没有配置成功
    # T" C8 L1 y4 @: E* I% C
  9.     {) W9 n- T( q- b! L! |& z( e6 g
  10.         printf("LTC6804_MODULAR INIT NG!\n\r");
    . X# I7 O7 m  m, [
  11.     }& W* i- \4 S- J9 U  ]8 Y
  12.     else* l) r$ N: k8 N
  13.     {
    : N; a. c8 _* p# p2 c* i0 o( k' m
  14.         printf("LTC6804_MODULAR INIT OK!\n\r");
    5 x- O$ v8 _1 D5 m$ F' T1 H/ f
  15.     }% g; ]) \* [. I+ O' f4 O
  16. 4 o( E4 A! {  b
  17. }
复制代码
  1. //手册第49页4 z$ z- \+ r. G; @$ Q8 V& _8 ^
  2. /* 寄存器               8         7          6         5         4         3         2        1        */6 g7 x1 r0 F; ]8 a: |# x
  3. //CFGR0       RD/WR   GPIO5     GPIO4      GPIO3     GPIO2     GPIO1     REFON     SWTRD    ADCOPT5 F9 k  U# g, c! U- q# U. _, R2 X
  4. //CFGR1       RD/WR   VUV[7]    VUV[6]     VUV[5]    VUV[4]    VUV[3]    VUV[2]    VUV[1]   VUV[0]! e! D# r$ y  A! I
  5. //CFGR2       RD/WR   VOV[3]    VOV[2]     VOV[1]    VOV[0]    VUV[11]   VUV[10]   VUV[9]   VUV[8]
    8 r, y8 ?; |) K% o6 p9 I
  6. //CFGR3       RD/WR   VOV[11]   VOV[10]    VOV[9]    VOV[8]    VOV[7]    VOV[6]    VOV[5]   VOV[4]
    8 D- m0 K$ q2 r9 v" B% q
  7. //CFGR4       RD/WR   DCC8      DCC7       DCC6      DCC5      DCC4      DCC3      DCC2     DCC1
    # K* ~+ r: i, {
  8. //CFGR5       RD/WR   DCTO[3]   DCTO[2]    DCTO[1]   DCTO[0]   DCC12     DCC11     DCC10    DCC94 i$ W5 v- w% R% j
  9. void init_cfg(void)
    - S4 C3 U( W) d! A2 r
  10. {
    . T$ A  ~- |& w9 Y$ z! A
  11.     int i;  f6 C% B% b; L" e

  12. 6 y% H/ N% n. Q( Z3 m- J5 d
  13.     for(i = 0; i<TOTAL_IC;i++)
    , s! q0 s. c9 ]# a
  14.     {
    & T9 Z  ]; d+ E( ^0 m, f1 \
  15.         tx_cfg[i][0] = 0xFE ;   //GPIO引脚下拉电路关断(bit8~bit4) | 基准保持上电状态(bit3) | SWTEN处于逻辑1(软件定时器) | ADC模式选择为0
    ! }/ `/ W7 h( |" T. Y
  16.         tx_cfg[i][1] = 0x00 ;   //不使用欠压比较功能. m7 @) m% U' ]
  17.         tx_cfg[i][2] = 0x00 ;   //不使用过压比较功能
    0 H6 N: {- R9 ?- W
  18.         tx_cfg[i][3] = 0x00 ;" |' A& x. }; \  x  j
  19.         tx_cfg[i][4] = 0x00 ;   //不使用电池放电功能
    4 w2 j! [9 I- x' w/ b# P- L
  20.         tx_cfg[i][5] = 0x00 ;   //放电超时时间4 ]: f" ^2 H6 C, v
  21.     }
      S2 A1 y/ \4 ?5 t5 U& h: J
  22. }
复制代码

' O1 l& F- ]+ p1 E+ _. n( t5 ^2 O8 j- ]
这里只使用了最基本的电压采集,其他的功能都没有用。
上面的代码里面有一个宏 :TOTAL_IC。
这个宏是用来定义一共有几片LTC6804-1的,比如我这次使用了2片,那么它的值就是2.
上面的寄存器设置,可以参考手册:
1050425-20190403172123490-1539331691.png
比如需要追加一些别的功能,便可以根据手册的寄存器进行设置,比如设置报警,设置均衡,设置其他的功能。
以上初始化部分就完成了,或者说移植就完成了,然后便不必对代码文件进行任何修改就可以直接使用,接下来是采集部分:
我是把采集放在main中进行。
  1. /* 唤醒6804 */
    6 _' l) W( K; I5 G2 r0 c+ |9 I
  2.         wakeup_sleep();5 p- m3 m, P4 M; z/ ~7 k3 u
  3.         /* 启动电压采集 */5 w: m9 r: i$ B- W. i0 W
  4.         LTC6804_adcv();- m& R! ~# l/ V  k, z) y
  5.         delay_ms(50);2 t! I8 Z3 Q: o' ~) K1 n* j4 g9 [
  6.         /* 读取电压 */
    # W+ w, D5 b: F3 _
  7.         res = LTC6804_rdcv(0, TOTAL_IC, vol_buff);
复制代码
) U1 d$ N% R4 _
以上便可以采集出电压了。
) w' j! S0 O6 T2 P$ v+ n6 @% M
※如果发现几个级联起来的6804,有些片子可以运行正常通信,有些又不可以运行甚至无法通信,在排除硬件的原因以后,可以查看一下这个地方:wakeup_sleep(),试着把唤醒时间设置的长一些。

+ G: }' z( y( `% a, q, m2 I! [5 K6 x
最后:可以看出来,精度还是不错的~

3 Z) M2 |1 u3 y2 u6 S
收藏 评论0 发布时间:2022-1-18 22:27

举报

0个回答

所属标签

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版