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

【经验分享】基于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线通信,不过我没有用)
. ]" v( F3 J2 T+ H  I, Z* V4 ]

+ a( x7 f; @3 _, Q
  下载下来的代码是C++文件,不能直接在STM32上使用,需要进行一些修改。
  首先修改后缀名,改成C文件,然后打开LTC6804.c文件。

& t3 {' U7 O0 m* W1 P' M
第一步进行驱动的移植:
  1. void spi_write_array(uint8_t len, // Option: Number of bytes to be written on the SPI port
    ' i' ~8 F" l- P& h; s7 }6 O% \! k. m# W
  2.                      uint8_t data[] //Array of bytes to be written on the SPI port
    . v7 D) m, \; k5 K( v9 ^' q
  3.                      )
    : z# \% H; g& T2 C0 H2 p7 R& {
  4. {2 v1 h9 Y3 U: ~+ d3 E
  5.     uint8_t i;9 H8 `' k' ^( X' g! y6 I) c8 ?# j/ c8 _

  6. 1 r! H  N$ ?5 A
  7.     for(i = 0; i < len; i++)
    7 x$ \, g9 c. K8 u$ O6 }; g
  8.     {
    # s5 _' d- Y! ~
  9.         SPI2_Send_byte((int8_t)data[i]);
    6 V. W6 D- A* i3 X- K% ^
  10.     }
    8 S" f& ]% {" M( \* W  H
  11. }
复制代码
  1. void spi_write_read(uint8_t tx_Data[],//array of data to be written on SPI port! x9 E/ n; o2 B9 B' e5 G
  2.                     uint8_t tx_len, //length of the tx data arry3 x7 q9 h2 }# q
  3.                     uint8_t *rx_data,//Input: array that will store the data read by the SPI port$ c5 E" \3 W& [; X, F9 x$ [
  4.                     uint8_t rx_len //Option: number of bytes to be read from the SPI port
    4 w0 [( `- Z$ M  _. t
  5.                     )4 j0 G; |+ C6 f3 R1 ^
  6. {0 Z1 T, H: S. \; h* V0 j
  7.     uint8_t i;7 g, a, D, ^; }& G; F+ p' o5 U

  8. 1 H* M# `& K/ S6 y: Z& O
  9.     for(i = 0; i < tx_len; i++)
    ( U8 w( e/ @# K" A
  10.     {( l, V: D( D" U8 f
  11.         SPI2_Send_byte(tx_Data[i]);
    ; Z9 ~" ?3 ?1 e  _5 y, u3 H
  12.     }
    & r7 g7 ^0 k$ M* e3 t
  13. ! {2 v" a" _9 v$ |
  14.     for(i = 0; i < rx_len; i++)" P, k3 t& t& P
  15.     {5 e8 |& O7 F8 c& ~
  16.         rx_data[i] = (uint8_t)SPI2_Receive_byte();4 o$ u% L4 A% h' S4 p( e. G4 j+ p
  17.     }
    " j  Q1 |5 ^% ^+ V, {3 ]# {& O- M7 `6 w
  18. 7 ?. d7 o0 [1 u" d6 z! @8 \) R
  19. }
复制代码
. D( U  T0 @! u# k8 W7 c$ f
只需要把自己的SPI驱动替换上去就可以了。
+ x% ~1 G% P6 l6 h( @( h! o9 M% `1 L
  1. void wakeup_idle()9 V, u* c2 ^$ _+ ?3 V
  2. {
    5 w4 o* a& J! h" u) ?0 f3 t- d
  3.   output_low(LTC6804_CS);% I) ?/ i9 d$ w5 ^! C( n: D% a5 w
  4.   delayMicroseconds(2); //Guarantees the isoSPI will be in ready mode4 ]+ }9 I: R  G6 V
  5.   output_high(LTC6804_CS);
    . j, r: {  [. m' |
  6. }
复制代码

9 e  m1 Z: `' \3 P$ V6 @% ^
自己把这个函数中间的部分实现,或者替换成自己的函数:
  1. void wakeup_idle(void). ~5 y* a+ k. r9 M9 g
  2. {
    % z2 m3 E; H: G  {
  3.   output_low(LTC6804_CS);
    ) a2 n, C) ?3 M7 T$ V; G
  4.   delay_ms(4); //Guarantees the isoSPI will be in ready mode
    - a5 ?6 I0 L: }1 Q6 ]
  5.   output_high(LTC6804_CS);- z8 p- F. D5 T8 U
  6. }
复制代码
' ^$ k. H; O) ]' \2 K* W. v
下面是原版的初始化函数:
  1. void LTC6804_initialize()) |9 w- u4 C) n; Q" R0 h* Z" |
  2. {! O  }( S$ |* |5 Y% F7 i6 X
  3.   quikeval_SPI_connect();% `! @, f, J4 N
  4.   spi_enable(SPI_CLOCK_DIV16); // This will set the Linduino to have a 1MHz Clock  r& O1 t5 ^7 {: ^' ~
  5.   set_adc(MD_NORMAL,DCP_DISABLED,CELL_CH_ALL,AUX_CH_ALL);/ G! E& `3 A; \) Y7 H
  6. }
复制代码

" K6 L& h6 H7 A4 @6 D
我把它根据自己的实际情况修改一下 :
  1. void LTC6804_initialize(void)  r$ t) d+ k0 r$ o/ u# w* N  r9 }
  2. {- F! \' q3 j( g( y
  3.     Drive_LTC6804_Spi_Init();//SPI外设初始化/ h7 r1 ]/ @! J' H1 K8 n" b
  4.     init_cfg();        //配置LTC6804的寄存器
    , O5 M/ u8 g5 g7 c( O5 U; D" j
  5.     set_adc(MD_FILTERED,DCP_DISABLED,CELL_CH_ALL,AUX_CH_GPIO1);//设置转换方式等) Z$ H  K9 H0 |
  6.     wakeup_sleep();//唤醒芯片. o% S( Y# V; |3 T
  7.     LTC6804_wrcfg(TOTAL_IC,tx_cfg);//把上面的设置写入芯片. V' q! Z6 K% Y* F* W. R- X4 M
  8.     if (LTC6804_rdcfg(TOTAL_IC,rx_cfg) == -1)  //检查一下到底有没有配置成功3 p: p- D$ u" B$ b$ n
  9.     {
    0 R# E( ?% H& S6 Y- \/ j2 N6 D$ |+ B0 S# m! R
  10.         printf("LTC6804_MODULAR INIT NG!\n\r");2 u" \" ^$ t  P+ Q, v
  11.     }
    : b0 f1 j( ], L4 B- K1 ]9 `
  12.     else
    ( P/ h/ a. A3 b, B
  13.     {
    0 c8 {' E8 [6 [" Y# u8 b; e7 ]5 g
  14.         printf("LTC6804_MODULAR INIT OK!\n\r");( x% Z1 @, Q; @9 _3 t3 k- A+ ^
  15.     }
    9 z" D) c  J0 K1 L( ?8 @3 M2 D/ z- n
  16. / y8 q- r) q1 R1 r- {
  17. }
复制代码
  1. //手册第49页
    : p% O: Q( D/ K9 q1 P+ O
  2. /* 寄存器               8         7          6         5         4         3         2        1        */
    ! }9 O4 a! x6 A& N8 m9 A  ]( A
  3. //CFGR0       RD/WR   GPIO5     GPIO4      GPIO3     GPIO2     GPIO1     REFON     SWTRD    ADCOPT
    7 H7 T- S5 B6 s; R: V: R  S
  4. //CFGR1       RD/WR   VUV[7]    VUV[6]     VUV[5]    VUV[4]    VUV[3]    VUV[2]    VUV[1]   VUV[0]" f' w  [1 d9 H
  5. //CFGR2       RD/WR   VOV[3]    VOV[2]     VOV[1]    VOV[0]    VUV[11]   VUV[10]   VUV[9]   VUV[8]
    ; `7 V2 M- U7 {! D, I
  6. //CFGR3       RD/WR   VOV[11]   VOV[10]    VOV[9]    VOV[8]    VOV[7]    VOV[6]    VOV[5]   VOV[4]8 o6 D- Z* M& I$ x5 }8 r
  7. //CFGR4       RD/WR   DCC8      DCC7       DCC6      DCC5      DCC4      DCC3      DCC2     DCC1" X/ N. |' f5 p+ G, R4 V
  8. //CFGR5       RD/WR   DCTO[3]   DCTO[2]    DCTO[1]   DCTO[0]   DCC12     DCC11     DCC10    DCC9
    + z9 ^; ?- t  t/ D; y! d) i% S
  9. void init_cfg(void)
    $ b- B* \9 c/ S2 l" ~3 f
  10. {9 C/ |0 d( I0 X3 z
  11.     int i;
    2 K" d8 _% `1 z% Z2 {

  12. 7 H, U- {3 \) I& ]3 \& ~; B
  13.     for(i = 0; i<TOTAL_IC;i++)
    $ S- J0 s- t$ O3 L* g
  14.     {
    ( e/ p  n  Z0 c' F+ J+ N% H
  15.         tx_cfg[i][0] = 0xFE ;   //GPIO引脚下拉电路关断(bit8~bit4) | 基准保持上电状态(bit3) | SWTEN处于逻辑1(软件定时器) | ADC模式选择为0# M: |/ S( }: ^
  16.         tx_cfg[i][1] = 0x00 ;   //不使用欠压比较功能! ~; k2 X! I! X: P
  17.         tx_cfg[i][2] = 0x00 ;   //不使用过压比较功能
    / r4 e8 j3 R4 C4 ~) H
  18.         tx_cfg[i][3] = 0x00 ;
    8 s: A1 p; x5 k5 p' r& M2 ?4 {: F
  19.         tx_cfg[i][4] = 0x00 ;   //不使用电池放电功能8 [$ ^5 U: `# @( P1 _; a
  20.         tx_cfg[i][5] = 0x00 ;   //放电超时时间' J: Y+ b/ M, |% c" S: ?
  21.     }" S: x+ s8 A/ z# }8 p
  22. }
复制代码
, E- M7 Y) w7 @" b' G
$ U3 B! J( r7 O$ e: `& ?
这里只使用了最基本的电压采集,其他的功能都没有用。
上面的代码里面有一个宏 :TOTAL_IC。
这个宏是用来定义一共有几片LTC6804-1的,比如我这次使用了2片,那么它的值就是2.
上面的寄存器设置,可以参考手册:
1050425-20190403172123490-1539331691.png
比如需要追加一些别的功能,便可以根据手册的寄存器进行设置,比如设置报警,设置均衡,设置其他的功能。
以上初始化部分就完成了,或者说移植就完成了,然后便不必对代码文件进行任何修改就可以直接使用,接下来是采集部分:
我是把采集放在main中进行。
  1. /* 唤醒6804 */" _, T" V$ [! s: {* i
  2.         wakeup_sleep();
    " x6 y9 A4 {9 G( Y; q4 g
  3.         /* 启动电压采集 */
    - y) Q3 M% Z. o' d& y( H0 V
  4.         LTC6804_adcv();
    2 t; u# b( e8 x$ t$ ]
  5.         delay_ms(50);
    8 W7 M8 }. ~6 n$ X. o1 d/ _
  6.         /* 读取电压 */
    . N2 {, U& i7 G4 k2 k" M
  7.         res = LTC6804_rdcv(0, TOTAL_IC, vol_buff);
复制代码

# q6 G* S/ N# ^: n. R- G( @( z
以上便可以采集出电压了。
/ F3 _0 E( M  w5 r  t5 Z
※如果发现几个级联起来的6804,有些片子可以运行正常通信,有些又不可以运行甚至无法通信,在排除硬件的原因以后,可以查看一下这个地方:wakeup_sleep(),试着把唤醒时间设置的长一些。
* Z0 M* P5 O$ h' f
最后:可以看出来,精度还是不错的~
1 D9 B7 U+ Y& ~
赞 收藏 评论0 发布时间:2022-1-18 22:27

举报

0个回答

所属标签

相似技术帖

官网相关资源

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