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

【经验分享】基于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线通信,不过我没有用)
4 i, P! }( R; W9 j2 u/ K
; ?2 n# J; \; j6 w
  下载下来的代码是C++文件,不能直接在STM32上使用,需要进行一些修改。
  首先修改后缀名,改成C文件,然后打开LTC6804.c文件。
( `+ ?/ w  J% S
第一步进行驱动的移植:
  1. void spi_write_array(uint8_t len, // Option: Number of bytes to be written on the SPI port9 y0 ]/ a% p5 |+ ^
  2.                      uint8_t data[] //Array of bytes to be written on the SPI port+ s3 L7 ^/ A  f% H
  3.                      )
    ( J. P" }8 c3 W% z9 t
  4. {0 l( Z; G3 h7 _* O* {6 ^8 e
  5.     uint8_t i;4 X' G8 P2 r( L2 U( E0 w* d
  6. 5 Z+ Z. H( a( i
  7.     for(i = 0; i < len; i++)! A" S8 N, J8 T; D( y* Q2 b$ |: A
  8.     {, }# t- e+ K. ~+ l2 ]% C# I
  9.         SPI2_Send_byte((int8_t)data[i]);
      \  Z+ j& ^6 g( u4 v
  10.     }
    0 ?8 A. F) L7 y" p$ d
  11. }
复制代码
  1. void spi_write_read(uint8_t tx_Data[],//array of data to be written on SPI port
    4 g1 ~/ e3 u$ M3 V/ X
  2.                     uint8_t tx_len, //length of the tx data arry
    + y5 d. F$ ~; `8 x
  3.                     uint8_t *rx_data,//Input: array that will store the data read by the SPI port  C( ^" O. h. f
  4.                     uint8_t rx_len //Option: number of bytes to be read from the SPI port" Y7 A4 [+ @. U9 N( }) H
  5.                     )- F9 @( D+ `" i+ T/ u* k; J, L
  6. {
    : B0 b) y& D# r4 X
  7.     uint8_t i;
    . K! m& e- Z7 e2 z  V4 t
  8. 1 l+ l- h9 f* X
  9.     for(i = 0; i < tx_len; i++)
    4 `5 f' D% K' r: o: B
  10.     {
    5 a0 L" K" J  h  b3 q+ ^3 L9 B
  11.         SPI2_Send_byte(tx_Data[i]);/ G0 p$ d/ U6 ?# o/ H3 K: S
  12.     }
    4 ~0 h8 I( y8 F/ t/ H' L6 S0 P

  13. 1 _7 E( ]& ^" X/ [
  14.     for(i = 0; i < rx_len; i++)
    * {6 H& x/ i/ }: Y$ o2 W
  15.     {4 l5 S# h3 y4 v) T% A
  16.         rx_data[i] = (uint8_t)SPI2_Receive_byte();
      |. c2 |$ |+ _
  17.     }
    $ O3 T- f6 a: X: O& N
  18. . _  O# h3 Z# T) I
  19. }
复制代码

4 d( K# v& `. {- |2 ~
只需要把自己的SPI驱动替换上去就可以了。

6 @% [, H  g: N: q; C- t
  1. void wakeup_idle(): J. p3 t/ T0 d  [+ ^1 _! {% N
  2. {6 f. g6 F# Y: o3 p- |
  3.   output_low(LTC6804_CS);
    . V6 k8 ]: j  t8 ?
  4.   delayMicroseconds(2); //Guarantees the isoSPI will be in ready mode
    $ K  v- r- A* s8 o& M3 z! p
  5.   output_high(LTC6804_CS);" I  q5 e. q4 ~/ C" L6 r
  6. }
复制代码

3 F6 a! V, f, H6 ]% }2 P' B
自己把这个函数中间的部分实现,或者替换成自己的函数:
  1. void wakeup_idle(void)5 S: U& W2 o1 d+ B! X2 ?
  2. {
    9 f" G8 }9 F; b6 I. @! }/ ~
  3.   output_low(LTC6804_CS);1 b0 K* I4 x* F
  4.   delay_ms(4); //Guarantees the isoSPI will be in ready mode. a+ k7 N/ E6 `) M
  5.   output_high(LTC6804_CS);
    2 C6 O$ D; q+ E) I9 s) Z6 r5 P# X0 Q
  6. }
复制代码
3 M; F; L1 O  _2 y3 h
下面是原版的初始化函数:
  1. void LTC6804_initialize()
    0 Z+ B+ `' o" V9 d9 E
  2. {
    , [& {' ~" i4 S- {( W3 e  |
  3.   quikeval_SPI_connect();* t% ~3 u; m! v& b/ w+ H, U
  4.   spi_enable(SPI_CLOCK_DIV16); // This will set the Linduino to have a 1MHz Clock
    ; H4 N; l7 u- |. |* c- [
  5.   set_adc(MD_NORMAL,DCP_DISABLED,CELL_CH_ALL,AUX_CH_ALL);
    1 s' j3 v# Z* ?$ s+ [
  6. }
复制代码

4 X9 c& K# Q' x4 ?4 a& ]# a
我把它根据自己的实际情况修改一下 :
  1. void LTC6804_initialize(void)+ |# p& n; v: r9 y8 _/ Z' w
  2. {
    2 z& v* S, i/ z
  3.     Drive_LTC6804_Spi_Init();//SPI外设初始化1 E) i: Q9 H1 m8 N) q7 |# u
  4.     init_cfg();        //配置LTC6804的寄存器+ p# O: I# N9 E5 `
  5.     set_adc(MD_FILTERED,DCP_DISABLED,CELL_CH_ALL,AUX_CH_GPIO1);//设置转换方式等
    2 j8 d$ H+ j! X
  6.     wakeup_sleep();//唤醒芯片3 l/ L* g% C: }
  7.     LTC6804_wrcfg(TOTAL_IC,tx_cfg);//把上面的设置写入芯片
    6 t" h7 o$ G7 r! f* R
  8.     if (LTC6804_rdcfg(TOTAL_IC,rx_cfg) == -1)  //检查一下到底有没有配置成功
    1 s: j4 H  h) F: X/ w! W5 U' Z) |& {- D
  9.     {% f+ [3 v4 D7 m8 H6 ]8 ^# k. [: @
  10.         printf("LTC6804_MODULAR INIT NG!\n\r");
    . Q/ ]2 s0 |7 Q( O0 [/ @$ D
  11.     }& r1 S/ p2 n8 x* D/ m' B! M% F: r/ q
  12.     else1 e' F2 [& ?5 {
  13.     {
    ) F+ A4 u0 i4 b4 A* {8 b) ~* q& j
  14.         printf("LTC6804_MODULAR INIT OK!\n\r");
    % z+ C/ N6 t7 R# b' @/ }7 t7 |9 B
  15.     }
    ' u/ ?3 n! M5 Y& S) G2 i* }6 J) j" N
  16. " S, h0 w6 q% K9 i$ N
  17. }
复制代码
  1. //手册第49页
    - j" q, z6 h  K) ^( Y
  2. /* 寄存器               8         7          6         5         4         3         2        1        */& w- y$ ]: H9 j
  3. //CFGR0       RD/WR   GPIO5     GPIO4      GPIO3     GPIO2     GPIO1     REFON     SWTRD    ADCOPT4 [# q$ z9 A" }5 v& F$ o& ~6 W" o
  4. //CFGR1       RD/WR   VUV[7]    VUV[6]     VUV[5]    VUV[4]    VUV[3]    VUV[2]    VUV[1]   VUV[0]! h4 z3 B- M; l4 L" L+ A
  5. //CFGR2       RD/WR   VOV[3]    VOV[2]     VOV[1]    VOV[0]    VUV[11]   VUV[10]   VUV[9]   VUV[8]; S4 c4 n  i! p- _0 ^+ _$ p
  6. //CFGR3       RD/WR   VOV[11]   VOV[10]    VOV[9]    VOV[8]    VOV[7]    VOV[6]    VOV[5]   VOV[4]: i: n) |, D) K4 F
  7. //CFGR4       RD/WR   DCC8      DCC7       DCC6      DCC5      DCC4      DCC3      DCC2     DCC19 J" L( p4 [5 }8 }6 Q" ]/ m
  8. //CFGR5       RD/WR   DCTO[3]   DCTO[2]    DCTO[1]   DCTO[0]   DCC12     DCC11     DCC10    DCC9
    6 [5 R( J; P$ p0 K
  9. void init_cfg(void)
    8 `$ Z, x0 t+ b- h2 W# ?! Z7 C
  10. {' V6 T9 s3 u9 Y" r
  11.     int i;
    / h  s# O4 N* c
  12. 8 f3 e3 P# A" x: e, x
  13.     for(i = 0; i<TOTAL_IC;i++)
    9 K1 O4 F2 r2 f1 W" X8 F1 f
  14.     {% {" d! z9 s' q$ C; z; A/ d
  15.         tx_cfg[i][0] = 0xFE ;   //GPIO引脚下拉电路关断(bit8~bit4) | 基准保持上电状态(bit3) | SWTEN处于逻辑1(软件定时器) | ADC模式选择为0# [9 ?. T  h& ^( w5 {/ ?) X( Z
  16.         tx_cfg[i][1] = 0x00 ;   //不使用欠压比较功能
    4 f7 ^/ v3 S+ q4 F
  17.         tx_cfg[i][2] = 0x00 ;   //不使用过压比较功能- o+ k4 ^2 Y$ X' d% W
  18.         tx_cfg[i][3] = 0x00 ;
    * K9 z2 u8 U4 B6 ^7 J3 q
  19.         tx_cfg[i][4] = 0x00 ;   //不使用电池放电功能7 S) P" c; v7 e# H/ Z  P$ ~1 |
  20.         tx_cfg[i][5] = 0x00 ;   //放电超时时间
      ^: p! a/ B4 ?. d7 _( d
  21.     }3 Q2 U; K3 o$ H4 g
  22. }
复制代码
* z0 f. e/ j' t5 H# R8 U6 \
. i$ x% p+ ?1 b7 p# k% ?  H; I. i
这里只使用了最基本的电压采集,其他的功能都没有用。
上面的代码里面有一个宏 :TOTAL_IC。
这个宏是用来定义一共有几片LTC6804-1的,比如我这次使用了2片,那么它的值就是2.
上面的寄存器设置,可以参考手册:
1050425-20190403172123490-1539331691.png
比如需要追加一些别的功能,便可以根据手册的寄存器进行设置,比如设置报警,设置均衡,设置其他的功能。
以上初始化部分就完成了,或者说移植就完成了,然后便不必对代码文件进行任何修改就可以直接使用,接下来是采集部分:
我是把采集放在main中进行。
  1. /* 唤醒6804 */) o" R& V* `: i8 o
  2.         wakeup_sleep();
    9 m6 v; J: i. }7 Q0 N
  3.         /* 启动电压采集 */- I* b# \9 K; F  F  }) E" h
  4.         LTC6804_adcv();( U$ U) u9 H: h9 D, f2 ^) y
  5.         delay_ms(50);
    - x7 ^$ F+ f2 S8 _; Z
  6.         /* 读取电压 */" _. g2 f: ^% F# H) y6 h
  7.         res = LTC6804_rdcv(0, TOTAL_IC, vol_buff);
复制代码
4 ?, w5 [6 e( t8 [# g: S- h
以上便可以采集出电压了。
  L" n# ?1 \6 x5 s; h, A
※如果发现几个级联起来的6804,有些片子可以运行正常通信,有些又不可以运行甚至无法通信,在排除硬件的原因以后,可以查看一下这个地方:wakeup_sleep(),试着把唤醒时间设置的长一些。

! I, d" U, Q/ G2 g" J
最后:可以看出来,精度还是不错的~

( F" [  {" l' g( g% m  S" m
收藏 评论0 发布时间:2022-1-18 22:27

举报

0个回答

所属标签

相似分享

官网相关资源

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