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

【经验分享】基于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 `! j4 L; z# V- ]. o/ q

' ]: O9 k) n5 N7 M
  下载下来的代码是C++文件,不能直接在STM32上使用,需要进行一些修改。
  首先修改后缀名,改成C文件,然后打开LTC6804.c文件。
/ X$ f" f1 F3 [# Z2 ~" p
第一步进行驱动的移植:
  1. void spi_write_array(uint8_t len, // Option: Number of bytes to be written on the SPI port
    7 Z; y' [* T+ o4 l  w7 a
  2.                      uint8_t data[] //Array of bytes to be written on the SPI port4 ?* Y# U( V( a% ?; b5 d. j
  3.                      )" e& ?+ \8 C/ M% D4 ~7 T% L
  4. {9 c. \5 F/ J$ u
  5.     uint8_t i;6 _6 ]- w  D  d: L) P

  6. 8 j' I$ O2 {: T* O6 w4 g
  7.     for(i = 0; i < len; i++)
    & \4 m. ~" \- C8 C( Q8 @
  8.     {( R0 L! o/ M( t  K- }
  9.         SPI2_Send_byte((int8_t)data[i]);) q  l7 {) B/ z5 F) j4 U- _; P
  10.     }0 H' i; }6 s6 q5 }4 P8 x
  11. }
复制代码
  1. void spi_write_read(uint8_t tx_Data[],//array of data to be written on SPI port8 E) r# U4 p. w  x& l
  2.                     uint8_t tx_len, //length of the tx data arry
    ; M* ^6 S) E0 c" n
  3.                     uint8_t *rx_data,//Input: array that will store the data read by the SPI port) E5 z5 \4 \3 {8 s, A
  4.                     uint8_t rx_len //Option: number of bytes to be read from the SPI port  {7 X$ d4 I$ ]2 Y+ O0 j
  5.                     )
    / ?9 ^$ [0 }( C' D  u; \6 y: s
  6. {: L. e6 \6 g# x: Y, A
  7.     uint8_t i;
    * B1 D4 K/ \7 r
  8. 1 _- V* z2 M0 }. u
  9.     for(i = 0; i < tx_len; i++)
    ; \  e% S( d5 K4 [$ A6 Z/ d5 Z% i0 ]
  10.     {7 U4 B9 |- @7 N! Q
  11.         SPI2_Send_byte(tx_Data[i]);
    - u9 g/ V7 p& N& y6 Y5 V
  12.     }
    / L& s+ C; b- B+ M# A
  13. * ?* K' g: A. H
  14.     for(i = 0; i < rx_len; i++)
    + a, D0 |1 i* Z
  15.     {
    6 U5 H1 ]* d* o) v( P$ }7 M' d+ M
  16.         rx_data[i] = (uint8_t)SPI2_Receive_byte();
    2 s9 J  p8 r6 V: v$ R
  17.     }' r2 Z/ W; G# ~8 w
  18. 7 s$ ?" z/ j, q& y- @
  19. }
复制代码
8 P" s7 Y( T* x2 h& D( W, P
只需要把自己的SPI驱动替换上去就可以了。

8 v$ K/ p, B- b7 _7 J- E- n
  1. void wakeup_idle()7 v3 j" f7 D1 |- E4 k$ L' l
  2. {
    3 p/ U# [( e& E8 l: j9 V
  3.   output_low(LTC6804_CS);% ~9 A7 L! m: f  M6 S! @5 _; W
  4.   delayMicroseconds(2); //Guarantees the isoSPI will be in ready mode
    $ L+ A$ n8 I* o. a
  5.   output_high(LTC6804_CS);3 O" T  |" k% c  m
  6. }
复制代码

' _6 U! [8 r' x$ c  d
自己把这个函数中间的部分实现,或者替换成自己的函数:
  1. void wakeup_idle(void); h) U. \# ~) L! e/ A; v& Z
  2. {0 E9 }) }$ B1 _$ p2 D
  3.   output_low(LTC6804_CS);" g6 o- Q7 m8 n9 W( S( T+ v
  4.   delay_ms(4); //Guarantees the isoSPI will be in ready mode
    ' E- O5 n  g5 D9 W8 ~) ?$ Q" z
  5.   output_high(LTC6804_CS);
    9 E( c" [, q- L: W: X5 f
  6. }
复制代码
$ q' R6 E) ?7 V' i
下面是原版的初始化函数:
  1. void LTC6804_initialize(); Y. o  X! _: O7 r! r6 Z0 @
  2. {
    " E& _+ ~  ]  x4 V6 s6 |1 d
  3.   quikeval_SPI_connect();* W8 a6 L9 ?4 d
  4.   spi_enable(SPI_CLOCK_DIV16); // This will set the Linduino to have a 1MHz Clock$ E. [0 m2 _4 _% S  m
  5.   set_adc(MD_NORMAL,DCP_DISABLED,CELL_CH_ALL,AUX_CH_ALL);- W# Q3 t. Q3 s1 e( a1 ]
  6. }
复制代码
5 u& S  P4 E5 R* ~( W' Q$ E' U
我把它根据自己的实际情况修改一下 :
  1. void LTC6804_initialize(void)3 r6 o) `# `0 H1 U9 _1 |! b: p) f
  2. {
    0 c9 J! U8 o, `- t) C: a& L
  3.     Drive_LTC6804_Spi_Init();//SPI外设初始化6 g) k* Y+ P# K. [. t" [
  4.     init_cfg();        //配置LTC6804的寄存器
    0 U) Q; U9 t9 u5 Z7 n; d8 m
  5.     set_adc(MD_FILTERED,DCP_DISABLED,CELL_CH_ALL,AUX_CH_GPIO1);//设置转换方式等
    , {% f* u* P, G. j
  6.     wakeup_sleep();//唤醒芯片
    1 \1 O2 S9 A+ `2 _3 S$ g" N
  7.     LTC6804_wrcfg(TOTAL_IC,tx_cfg);//把上面的设置写入芯片- z4 f; M% I1 j( G! i. z
  8.     if (LTC6804_rdcfg(TOTAL_IC,rx_cfg) == -1)  //检查一下到底有没有配置成功# H5 E- H% t2 I
  9.     {
    : p" b. d9 y8 O; u& ^& \% d# @
  10.         printf("LTC6804_MODULAR INIT NG!\n\r");
    : k6 ?2 m7 O/ B0 j
  11.     }% T8 i1 p, N! h8 B( J; v
  12.     else; O' x( a* j9 @1 w  `! g4 ]
  13.     {
    6 z/ C7 z4 e! i, f' K3 Y
  14.         printf("LTC6804_MODULAR INIT OK!\n\r");2 ~' l, H$ ~% Q
  15.     }
    1 Z5 V, q) p# o8 Q* m
  16. , `$ z% [; Z- ?2 f* q! b
  17. }
复制代码
  1. //手册第49页/ ^6 k% n+ z: `& ?
  2. /* 寄存器               8         7          6         5         4         3         2        1        */" C0 P* [3 T% \4 r; c1 U
  3. //CFGR0       RD/WR   GPIO5     GPIO4      GPIO3     GPIO2     GPIO1     REFON     SWTRD    ADCOPT7 o, \' n& _# r' P) q
  4. //CFGR1       RD/WR   VUV[7]    VUV[6]     VUV[5]    VUV[4]    VUV[3]    VUV[2]    VUV[1]   VUV[0]6 C+ h+ g* r# W+ E* B
  5. //CFGR2       RD/WR   VOV[3]    VOV[2]     VOV[1]    VOV[0]    VUV[11]   VUV[10]   VUV[9]   VUV[8]7 J* @; k9 h7 X/ m7 [
  6. //CFGR3       RD/WR   VOV[11]   VOV[10]    VOV[9]    VOV[8]    VOV[7]    VOV[6]    VOV[5]   VOV[4]+ C1 i! T3 G: t. }% m' ?
  7. //CFGR4       RD/WR   DCC8      DCC7       DCC6      DCC5      DCC4      DCC3      DCC2     DCC1
    1 l( k3 @- A4 |! [" R& h
  8. //CFGR5       RD/WR   DCTO[3]   DCTO[2]    DCTO[1]   DCTO[0]   DCC12     DCC11     DCC10    DCC96 z2 |4 `+ }) c  i
  9. void init_cfg(void)) n# W! p6 \$ O4 ], O/ }) o
  10. {
    - J  ^" C' `: x0 x+ ~# Q
  11.     int i;" A; J7 m+ L- b6 M8 v
  12.   i. N8 f8 ]3 m/ g4 a% t3 O
  13.     for(i = 0; i<TOTAL_IC;i++)
    ( c( A2 y7 A' Y7 _  r5 O8 M; }% q* U
  14.     {! L0 L, O7 v$ N2 q
  15.         tx_cfg[i][0] = 0xFE ;   //GPIO引脚下拉电路关断(bit8~bit4) | 基准保持上电状态(bit3) | SWTEN处于逻辑1(软件定时器) | ADC模式选择为0
    & E  z/ H! k' u( f
  16.         tx_cfg[i][1] = 0x00 ;   //不使用欠压比较功能
    6 Q8 u9 h8 n5 A  Z- @
  17.         tx_cfg[i][2] = 0x00 ;   //不使用过压比较功能8 u( g& g) h9 \6 f' U
  18.         tx_cfg[i][3] = 0x00 ;$ C. s" C% p+ N* q+ R
  19.         tx_cfg[i][4] = 0x00 ;   //不使用电池放电功能2 T7 q* l# m4 b& ~6 N0 X" S
  20.         tx_cfg[i][5] = 0x00 ;   //放电超时时间! E( s2 B5 L: W0 V
  21.     }
    8 }! _( k7 A& G# R2 {& x
  22. }
复制代码
% h$ {2 j+ q! ?  h

' a* U0 b! I2 f/ o' r
这里只使用了最基本的电压采集,其他的功能都没有用。
上面的代码里面有一个宏 :TOTAL_IC。
这个宏是用来定义一共有几片LTC6804-1的,比如我这次使用了2片,那么它的值就是2.
上面的寄存器设置,可以参考手册:
1050425-20190403172123490-1539331691.png
比如需要追加一些别的功能,便可以根据手册的寄存器进行设置,比如设置报警,设置均衡,设置其他的功能。
以上初始化部分就完成了,或者说移植就完成了,然后便不必对代码文件进行任何修改就可以直接使用,接下来是采集部分:
我是把采集放在main中进行。
  1. /* 唤醒6804 */
    ( f9 [% c+ G+ D5 t' x6 H) V+ k
  2.         wakeup_sleep();
    % j6 z" d$ Y& s5 ]9 P6 j( i! I! g$ S
  3.         /* 启动电压采集 */
    : d) P9 n% K  q* q. u
  4.         LTC6804_adcv();
    ( \4 \( t! C4 L& z) b
  5.         delay_ms(50);* S" k9 ~) A* y7 W
  6.         /* 读取电压 */
    4 S& U7 v) S: w6 W& H. W3 H
  7.         res = LTC6804_rdcv(0, TOTAL_IC, vol_buff);
复制代码

% O8 }% k0 W. k; N+ r- k
以上便可以采集出电压了。

& ?9 R8 S1 E) T+ I8 i
※如果发现几个级联起来的6804,有些片子可以运行正常通信,有些又不可以运行甚至无法通信,在排除硬件的原因以后,可以查看一下这个地方:wakeup_sleep(),试着把唤醒时间设置的长一些。

4 ~+ b2 S: Q* t5 g* W- J
最后:可以看出来,精度还是不错的~

* T  U; Q, G: N' X: g
收藏 评论0 发布时间:2022-1-18 22:27

举报

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