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

【经验分享】基于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线通信,不过我没有用)
! t; j3 w7 s- o8 m' N- l$ k( o) C
# m6 O9 \6 k. Y) W
  下载下来的代码是C++文件,不能直接在STM32上使用,需要进行一些修改。
  首先修改后缀名,改成C文件,然后打开LTC6804.c文件。
: i- T% q8 K! {/ m
第一步进行驱动的移植:
  1. void spi_write_array(uint8_t len, // Option: Number of bytes to be written on the SPI port' A4 g$ c6 D" x6 y
  2.                      uint8_t data[] //Array of bytes to be written on the SPI port! H' U/ L3 S3 K" ]1 u7 Z
  3.                      )
    / ^* B, {1 `4 x! I, t' R1 [
  4. {
    4 T/ ]7 L9 p/ B/ C" v4 K
  5.     uint8_t i;
    6 T) T! M/ M4 s: K! [: a  q2 s% e

  6. 4 c; m" p2 A" J
  7.     for(i = 0; i < len; i++)
    4 m% P( ]3 E: c+ G+ I) S7 g
  8.     {4 G; t! s' X2 F2 ]3 Y+ P) C: l3 j
  9.         SPI2_Send_byte((int8_t)data[i]);6 g: {) T( A. `% q
  10.     }
    8 I  t  C4 H; ]4 r5 [
  11. }
复制代码
  1. void spi_write_read(uint8_t tx_Data[],//array of data to be written on SPI port& f) y3 L" F' r7 w/ Y
  2.                     uint8_t tx_len, //length of the tx data arry  ~2 p# O4 R" x- P( k9 m( r3 b; l
  3.                     uint8_t *rx_data,//Input: array that will store the data read by the SPI port
    ' j4 a; d5 O* y. {; P2 k
  4.                     uint8_t rx_len //Option: number of bytes to be read from the SPI port
    + x2 i$ F% u) J. `  v. X' b1 B
  5.                     )
    , L4 S, Q' I2 W0 y! ]
  6. {- E- n  u7 e9 ?% D. H3 |
  7.     uint8_t i;
    : L/ Q; R' H2 z% I4 i

  8. 9 `$ w( }2 @5 R
  9.     for(i = 0; i < tx_len; i++)
    2 z; q) R2 i- s
  10.     {
    3 ?9 f5 t0 X- _. E% g, c- d: K
  11.         SPI2_Send_byte(tx_Data[i]);
    3 w7 @  N1 L( v7 `  F0 I
  12.     }
    $ O' C4 Y& x1 k' {
  13. 1 _; y+ O# I" o5 E7 m0 _
  14.     for(i = 0; i < rx_len; i++)' O+ n" H: Y; J5 h/ S, y! m5 T. J# [
  15.     {2 Q0 K( r5 X' D
  16.         rx_data[i] = (uint8_t)SPI2_Receive_byte();
    0 `( t! w/ U" l9 X- _5 B9 |: ]. T
  17.     }! \, Z' y6 C9 H" |8 k
  18. & c% Y7 ^! T2 k
  19. }
复制代码
- [$ _8 a$ J" q0 @3 h
只需要把自己的SPI驱动替换上去就可以了。

+ l9 j' z, O. ?1 l1 v; [
  1. void wakeup_idle()4 N  S8 ?# q6 q& D2 [
  2. {* `" N' K- G: V3 ?
  3.   output_low(LTC6804_CS);. L$ h8 J# G$ X4 a* {) I& t+ k
  4.   delayMicroseconds(2); //Guarantees the isoSPI will be in ready mode2 D) w' o# r) \+ W8 M1 i4 V7 e
  5.   output_high(LTC6804_CS);
    : z  `5 K9 A( K& P& T& w
  6. }
复制代码

4 q0 E# Q  V7 c0 u
自己把这个函数中间的部分实现,或者替换成自己的函数:
  1. void wakeup_idle(void)6 N/ `& j% D7 y- W5 }7 T9 H5 v
  2. {
    . a8 s/ H2 ^! \
  3.   output_low(LTC6804_CS);* H# p: ]. D3 C# P- E/ Z
  4.   delay_ms(4); //Guarantees the isoSPI will be in ready mode
    + t; N' i- A6 o% o9 R
  5.   output_high(LTC6804_CS);! J/ l+ T; q5 z2 ^( k6 F! Y
  6. }
复制代码
$ ^* B+ k2 A# e- }/ W4 `* v
下面是原版的初始化函数:
  1. void LTC6804_initialize()
    & G2 H) [$ w4 i/ R
  2. {
    $ z4 {3 @9 V4 I" T4 |1 |( E
  3.   quikeval_SPI_connect();
    2 t6 }% D. t% G6 _
  4.   spi_enable(SPI_CLOCK_DIV16); // This will set the Linduino to have a 1MHz Clock
      Y1 m& ~$ u4 V# q" N, h: N
  5.   set_adc(MD_NORMAL,DCP_DISABLED,CELL_CH_ALL,AUX_CH_ALL);
    ( b! L' C4 n/ Z" E8 i, g( G
  6. }
复制代码
) [8 i9 x. A2 T$ w3 t  G0 C3 |: T
我把它根据自己的实际情况修改一下 :
  1. void LTC6804_initialize(void)5 |& h' N9 A7 Q  {) S+ a0 h) X1 T  W
  2. {
    2 ^$ [# [4 _, {& z2 I9 w8 p" o; i
  3.     Drive_LTC6804_Spi_Init();//SPI外设初始化6 A  A: k4 W7 P" B# F- _7 x
  4.     init_cfg();        //配置LTC6804的寄存器1 b# R8 ^- U( n( J8 N* C+ o  G
  5.     set_adc(MD_FILTERED,DCP_DISABLED,CELL_CH_ALL,AUX_CH_GPIO1);//设置转换方式等8 h, z6 O( O: L* u- X
  6.     wakeup_sleep();//唤醒芯片
    " v, W3 y! D5 _. L* P+ O; h( ]: t
  7.     LTC6804_wrcfg(TOTAL_IC,tx_cfg);//把上面的设置写入芯片
    4 C/ y  i$ _; g, D2 ]3 C! r
  8.     if (LTC6804_rdcfg(TOTAL_IC,rx_cfg) == -1)  //检查一下到底有没有配置成功: }% [5 U6 q/ T; S/ U2 W$ C  ^
  9.     {; f9 q$ X' I* Y* `( r
  10.         printf("LTC6804_MODULAR INIT NG!\n\r");1 O$ |* [0 o% o. F" z
  11.     }9 E- |/ X8 S( E4 X% w, c1 t; b) k
  12.     else5 E; n; H* c" z
  13.     {
    9 ?$ F: h& n- [' @+ K
  14.         printf("LTC6804_MODULAR INIT OK!\n\r");
    1 s; r2 Y$ s9 o$ R
  15.     }
    ; O7 I6 \% }) x% g$ A
  16. ( j$ R/ C* t! k6 A
  17. }
复制代码
  1. //手册第49页
    ! ~% g* y+ f) Z
  2. /* 寄存器               8         7          6         5         4         3         2        1        */
    3 M7 ]: d) r+ ^* p% [1 r4 a
  3. //CFGR0       RD/WR   GPIO5     GPIO4      GPIO3     GPIO2     GPIO1     REFON     SWTRD    ADCOPT& |: u0 x/ w+ T. h1 _# t) B' _$ D
  4. //CFGR1       RD/WR   VUV[7]    VUV[6]     VUV[5]    VUV[4]    VUV[3]    VUV[2]    VUV[1]   VUV[0]3 x4 D! x7 O/ x) `
  5. //CFGR2       RD/WR   VOV[3]    VOV[2]     VOV[1]    VOV[0]    VUV[11]   VUV[10]   VUV[9]   VUV[8]
    , E1 q8 r, X* j/ g+ z4 s
  6. //CFGR3       RD/WR   VOV[11]   VOV[10]    VOV[9]    VOV[8]    VOV[7]    VOV[6]    VOV[5]   VOV[4]1 p; `2 K% E6 d' _6 C$ n3 J
  7. //CFGR4       RD/WR   DCC8      DCC7       DCC6      DCC5      DCC4      DCC3      DCC2     DCC1
    5 I7 R& ^- ^2 F& x. O
  8. //CFGR5       RD/WR   DCTO[3]   DCTO[2]    DCTO[1]   DCTO[0]   DCC12     DCC11     DCC10    DCC9% c  ?. L3 R4 E/ J6 D1 B+ C. [
  9. void init_cfg(void)
    " p. [2 K5 r& F5 t' l$ l) g
  10. {( s6 g: B, w3 F
  11.     int i;& r! x+ c' R, Z3 W, w

  12. 1 u1 X9 f0 z1 n
  13.     for(i = 0; i<TOTAL_IC;i++)
    5 A7 ]4 d$ T% Z: w) U3 ~2 m
  14.     {
    7 w, P- S( l: a9 [" ]/ s8 l
  15.         tx_cfg[i][0] = 0xFE ;   //GPIO引脚下拉电路关断(bit8~bit4) | 基准保持上电状态(bit3) | SWTEN处于逻辑1(软件定时器) | ADC模式选择为0) |- Z% d' V+ ^5 E, p1 g
  16.         tx_cfg[i][1] = 0x00 ;   //不使用欠压比较功能
    . H1 b: v2 k/ w
  17.         tx_cfg[i][2] = 0x00 ;   //不使用过压比较功能
    + T1 }6 t4 y: n& ^
  18.         tx_cfg[i][3] = 0x00 ;  N3 A! h- O5 ^$ {, c( k
  19.         tx_cfg[i][4] = 0x00 ;   //不使用电池放电功能8 h$ d3 [* ^' h* G# M
  20.         tx_cfg[i][5] = 0x00 ;   //放电超时时间1 I9 N7 d( O6 k* O' H8 ?7 L$ A
  21.     }
    , `# _, x  A" r; {) F  k
  22. }
复制代码

! i& m" `/ \6 }' Z& B0 C
5 d; l* E  k+ l' w$ h$ f; z3 @
这里只使用了最基本的电压采集,其他的功能都没有用。
上面的代码里面有一个宏 :TOTAL_IC。
这个宏是用来定义一共有几片LTC6804-1的,比如我这次使用了2片,那么它的值就是2.
上面的寄存器设置,可以参考手册:
1050425-20190403172123490-1539331691.png
比如需要追加一些别的功能,便可以根据手册的寄存器进行设置,比如设置报警,设置均衡,设置其他的功能。
以上初始化部分就完成了,或者说移植就完成了,然后便不必对代码文件进行任何修改就可以直接使用,接下来是采集部分:
我是把采集放在main中进行。
  1. /* 唤醒6804 */) c/ Y1 |. ]2 Z) ^7 S8 ~
  2.         wakeup_sleep();4 \0 R; e& r: b5 \% I% c
  3.         /* 启动电压采集 */
    8 X. A% C* q$ ?" [2 Q8 e
  4.         LTC6804_adcv();  S7 R4 U& }6 K1 b! p/ M0 W
  5.         delay_ms(50);: s: A$ T/ l' _4 b# C
  6.         /* 读取电压 */
    # j7 e' U" @- }
  7.         res = LTC6804_rdcv(0, TOTAL_IC, vol_buff);
复制代码

# t- t  A8 I: o6 x
以上便可以采集出电压了。

/ P4 r% f* h! i. j
※如果发现几个级联起来的6804,有些片子可以运行正常通信,有些又不可以运行甚至无法通信,在排除硬件的原因以后,可以查看一下这个地方:wakeup_sleep(),试着把唤醒时间设置的长一些。
+ a8 L: O2 l3 ~4 g$ R% X0 Z
最后:可以看出来,精度还是不错的~

7 ~3 H: ?+ U9 W7 P6 D- v
收藏 评论0 发布时间:2022-1-18 22:27

举报

0个回答

所属标签

相似技术帖

官网相关资源

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