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

【经验分享】基于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线通信,不过我没有用)

+ u/ w" x7 Q- B6 ]! v5 d! M( n
! f8 V/ h3 Q4 h( y3 ]  ?5 j2 R; _
  下载下来的代码是C++文件,不能直接在STM32上使用,需要进行一些修改。
  首先修改后缀名,改成C文件,然后打开LTC6804.c文件。

* Z* p- r$ b( s8 N9 o
第一步进行驱动的移植:
  1. void spi_write_array(uint8_t len, // Option: Number of bytes to be written on the SPI port
    ; q8 K7 a2 n$ d0 a3 [' [0 Q
  2.                      uint8_t data[] //Array of bytes to be written on the SPI port
    9 ]; y. j- g' ]6 {& g( ?8 Z; s
  3.                      )
    ( q1 y' f4 b0 n" J) w  h1 X
  4. {+ t) v6 q- v9 ]1 b. B# |6 ^5 O: w
  5.     uint8_t i;9 c, I/ ^& ?% Q) J1 p
  6. $ l& U$ b1 A# {; Q
  7.     for(i = 0; i < len; i++), o9 T4 c* x/ @* t# _, N& {! C; V$ L9 J
  8.     {6 Z- X% Q7 p* m# a0 s% z3 E
  9.         SPI2_Send_byte((int8_t)data[i]);# n' e. ?1 |0 B1 I% I: [  h" G
  10.     }
    6 m% v; M: g- L- L
  11. }
复制代码
  1. void spi_write_read(uint8_t tx_Data[],//array of data to be written on SPI port  o. L( n  L; l4 y( h5 P) V
  2.                     uint8_t tx_len, //length of the tx data arry! A$ q" K! {0 `, q: k2 W7 \) `
  3.                     uint8_t *rx_data,//Input: array that will store the data read by the SPI port0 p! B$ Q6 g$ l8 u
  4.                     uint8_t rx_len //Option: number of bytes to be read from the SPI port, g+ T+ H2 X3 S/ t9 A  p
  5.                     )( `6 ~' W# x2 R# |7 i6 L7 }
  6. {
    4 f/ r, K, ]  s  ~! w
  7.     uint8_t i;: q; e5 T1 L1 S& i& w: q0 J

  8. 5 u0 X5 W4 F; @$ y  j- e  f5 w  K
  9.     for(i = 0; i < tx_len; i++)( r! P1 E9 p% A7 u( O1 g1 y
  10.     {1 T+ h+ E% B. R3 ]$ N4 @  u* I6 }' t
  11.         SPI2_Send_byte(tx_Data[i]);4 U! z0 c3 B) J+ r+ }# n2 e) B& D$ x
  12.     }' |: X0 W! E% O. d( H" A# M2 ?2 n

  13. 7 [# h2 h7 ^4 d: P1 ^) ], A  C
  14.     for(i = 0; i < rx_len; i++)
    ( M* v& I' A% }+ V* s
  15.     {% k- r+ ~5 L9 m7 i0 ?" Y
  16.         rx_data[i] = (uint8_t)SPI2_Receive_byte();
    7 S8 [6 @6 S3 Y  Z3 @0 O; L; d
  17.     }* k+ E- m. n+ A

  18. 6 ~( Q% G0 Q8 i  l9 J$ W
  19. }
复制代码

1 @6 b* W- }$ B5 t% Z4 ~+ Q
只需要把自己的SPI驱动替换上去就可以了。
* C. A3 `' G4 k" g! ^
  1. void wakeup_idle()
    0 L: @  N$ Z* K1 ?5 u
  2. {
    8 M  W" v# f- T! A. {
  3.   output_low(LTC6804_CS);
    # @9 M3 L* P6 \- N0 Q9 g; O
  4.   delayMicroseconds(2); //Guarantees the isoSPI will be in ready mode
    5 O2 T$ }. T2 F2 d, V2 A  m8 Q+ M+ B
  5.   output_high(LTC6804_CS);
    5 f( P- D& }4 {4 o5 n. b" Z  {1 W
  6. }
复制代码
" |. f! h9 d' `; g, Z% F5 ~
自己把这个函数中间的部分实现,或者替换成自己的函数:
  1. void wakeup_idle(void)
    6 V) F7 x) u+ [2 m3 z% K8 o( Q
  2. {! t$ a6 N# }  ], v; p  k# {
  3.   output_low(LTC6804_CS);
    - M5 x# n, }/ F# h" R
  4.   delay_ms(4); //Guarantees the isoSPI will be in ready mode$ E( ~8 B7 F0 F1 @& U
  5.   output_high(LTC6804_CS);
    " R* C4 K8 Q" _% c
  6. }
复制代码

9 N% W- n, `3 i' p& F* P
下面是原版的初始化函数:
  1. void LTC6804_initialize()6 e( t2 n% d; a" ~, v
  2. {; N& A+ `" ?: b% \0 ?; A
  3.   quikeval_SPI_connect();1 [7 O6 p& M% q" y6 C
  4.   spi_enable(SPI_CLOCK_DIV16); // This will set the Linduino to have a 1MHz Clock
    & y' ~' x& Z0 J0 W1 b3 p0 V1 A
  5.   set_adc(MD_NORMAL,DCP_DISABLED,CELL_CH_ALL,AUX_CH_ALL);
    , a! S' I! K  [3 L" u
  6. }
复制代码

2 s  m* h4 Q+ D4 o& T/ K
我把它根据自己的实际情况修改一下 :
  1. void LTC6804_initialize(void)
    & p6 Q% E. @! A2 _- T% T) i4 s
  2. {! k% S- M5 a2 J. K& L
  3.     Drive_LTC6804_Spi_Init();//SPI外设初始化# X# k9 m: r. r7 k
  4.     init_cfg();        //配置LTC6804的寄存器
    & K! t" g( K% U' `9 |, W
  5.     set_adc(MD_FILTERED,DCP_DISABLED,CELL_CH_ALL,AUX_CH_GPIO1);//设置转换方式等
    / F4 Y8 Q, H4 [8 |/ t2 U  h
  6.     wakeup_sleep();//唤醒芯片
    ; V9 b8 `$ ~4 w9 H
  7.     LTC6804_wrcfg(TOTAL_IC,tx_cfg);//把上面的设置写入芯片
    / b# d& H) d$ V+ G
  8.     if (LTC6804_rdcfg(TOTAL_IC,rx_cfg) == -1)  //检查一下到底有没有配置成功& x: ?" R2 }( U3 j% w# I( p9 _$ v
  9.     {, r2 ^7 s" o. k5 t: }4 i
  10.         printf("LTC6804_MODULAR INIT NG!\n\r");
    - m/ f& M/ d6 K: @! z% i& D! f
  11.     }- f: z7 Z' k& E! B; _; s
  12.     else
    / r7 S6 B" W+ x" I- M; ]
  13.     {
    / \6 Q3 v' L) K2 d, ~7 g
  14.         printf("LTC6804_MODULAR INIT OK!\n\r");
    + x- I+ l+ e! t; }( Z
  15.     }
    + Z4 i$ ]9 O. I. K6 J

  16. # T# x% U) G' z( Q0 ~: u
  17. }
复制代码
  1. //手册第49页
    0 {9 _$ \2 }% c  X& Q
  2. /* 寄存器               8         7          6         5         4         3         2        1        */
    ' X# W! ]: `& O. J
  3. //CFGR0       RD/WR   GPIO5     GPIO4      GPIO3     GPIO2     GPIO1     REFON     SWTRD    ADCOPT, a, Y# V9 C- p
  4. //CFGR1       RD/WR   VUV[7]    VUV[6]     VUV[5]    VUV[4]    VUV[3]    VUV[2]    VUV[1]   VUV[0]
    " ?$ L/ q0 X  w  ~) K8 M& F' q/ i' F
  5. //CFGR2       RD/WR   VOV[3]    VOV[2]     VOV[1]    VOV[0]    VUV[11]   VUV[10]   VUV[9]   VUV[8]- }# [! A* w. B6 ^8 A+ d5 C
  6. //CFGR3       RD/WR   VOV[11]   VOV[10]    VOV[9]    VOV[8]    VOV[7]    VOV[6]    VOV[5]   VOV[4]
    & g$ |* t4 d' O  W- r
  7. //CFGR4       RD/WR   DCC8      DCC7       DCC6      DCC5      DCC4      DCC3      DCC2     DCC1, a6 l6 F9 t3 R# s; d7 i' y- y
  8. //CFGR5       RD/WR   DCTO[3]   DCTO[2]    DCTO[1]   DCTO[0]   DCC12     DCC11     DCC10    DCC93 M+ Y( Y/ q- Z4 ?& Q  @% k; _! h
  9. void init_cfg(void)4 F) }6 `' x' I- T. q$ n
  10. {5 s8 C/ j0 [9 ^5 p
  11.     int i;+ q9 T: k8 t; N4 \
  12. ) {8 B3 B9 d4 D& Z7 ?, Z/ g
  13.     for(i = 0; i<TOTAL_IC;i++); F5 U9 Z1 ^. |0 o: Z+ F, @2 [
  14.     {8 i4 B5 o4 P' {' c7 X3 p
  15.         tx_cfg[i][0] = 0xFE ;   //GPIO引脚下拉电路关断(bit8~bit4) | 基准保持上电状态(bit3) | SWTEN处于逻辑1(软件定时器) | ADC模式选择为0: S1 ?* H" L4 g9 d3 v& Y  k
  16.         tx_cfg[i][1] = 0x00 ;   //不使用欠压比较功能
    - Y# P5 P( u' R3 E
  17.         tx_cfg[i][2] = 0x00 ;   //不使用过压比较功能% J! w- o8 O/ q# M3 r) `( J# ^
  18.         tx_cfg[i][3] = 0x00 ;
    6 V- C" A* \4 C* m: A
  19.         tx_cfg[i][4] = 0x00 ;   //不使用电池放电功能
    : X& G% |' d6 O* S; I8 m
  20.         tx_cfg[i][5] = 0x00 ;   //放电超时时间
    ' T% C, z# D5 E7 I
  21.     }, R, B% Y7 c: O
  22. }
复制代码

+ ]$ p6 C- o' x6 J3 q$ w5 o3 Y8 o, G
; \, R. L8 O% [+ J# V3 ]# e, ]
这里只使用了最基本的电压采集,其他的功能都没有用。
上面的代码里面有一个宏 :TOTAL_IC。
这个宏是用来定义一共有几片LTC6804-1的,比如我这次使用了2片,那么它的值就是2.
上面的寄存器设置,可以参考手册:
1050425-20190403172123490-1539331691.png
比如需要追加一些别的功能,便可以根据手册的寄存器进行设置,比如设置报警,设置均衡,设置其他的功能。
以上初始化部分就完成了,或者说移植就完成了,然后便不必对代码文件进行任何修改就可以直接使用,接下来是采集部分:
我是把采集放在main中进行。
  1. /* 唤醒6804 */0 X6 |9 Z/ m6 m; e7 q* O6 T
  2.         wakeup_sleep();& F% t) a* n  _1 H9 D" J+ J
  3.         /* 启动电压采集 */" ~5 h9 J0 d# J
  4.         LTC6804_adcv();5 F" w6 I# m% M4 E, o' a" h
  5.         delay_ms(50);& j" s- v$ ]4 v4 v
  6.         /* 读取电压 */
    4 c& x9 k# `5 _& b( _) w
  7.         res = LTC6804_rdcv(0, TOTAL_IC, vol_buff);
复制代码

; _7 z5 P* M! n5 F
以上便可以采集出电压了。

$ g: I/ [" _/ k% X4 i! ^) p# I
※如果发现几个级联起来的6804,有些片子可以运行正常通信,有些又不可以运行甚至无法通信,在排除硬件的原因以后,可以查看一下这个地方:wakeup_sleep(),试着把唤醒时间设置的长一些。
7 e7 |# h0 \, y3 C, n3 X
最后:可以看出来,精度还是不错的~
9 j2 H  A% o/ U* Y0 L
收藏 评论0 发布时间:2022-1-18 22:27

举报

0个回答

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32Cube扩展软件包
意法半导体边缘AI套件
ST - 理想汽车豪华SUV案例
ST意法半导体智能家居案例
STM32 ARM Cortex 32位微控制器
关注我们
st-img 微信公众号
st-img 手机版