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

【经验分享】STM32G031K LL库的使用 - IIC

[复制链接]
STMCU小助手 发布时间:2021-11-10 22:53
说明:驱动基于STm32G031K6,其他型号需自行做改动。/ m+ K5 W7 t' v! o1 e  K3 J$ x
! L' W9 E9 N& Z3 }
注:因为之前项目暂未用到LL库的IIC,所以此驱动未经过实机验证。欢迎反馈使用中的问题。# s0 t) W3 E+ S2 |8 W

: A% e$ ~, D1 k$ n9 P$ J7 z% ZIIC的初始化: CubeMX生成
' f- v0 |* x7 C2 q; W5 r: z- ?* K2 J$ t3 ?
  1. void STM32LLI2C1_Init(void)) _& {' e* b; P! E0 D7 T- r
  2. {. y3 A) j4 x1 O. x, a
  3.   LL_I2C_InitTypeDef I2C_InitStruct = {0};- ]' [  b: t4 d5 o
  4. - E+ x$ b  ?( r  N: N5 c3 i
  5.   LL_GPIO_InitTypeDef GPIO_InitStruct = {0};
    % I! K7 C8 p* Z
  6. 0 [# \; y* c& E+ I, K2 W
  7.   LL_IOP_GRP1_EnableClock(LL_IOP_GRP1_PERIPH_GPIOA);
    $ P% I, a" L1 c1 R( a& B8 i" j2 d
  8.   /**I2C1 GPIO Configuration  
    # e9 h% u% j' a8 N0 c  u
  9.   PA9   ------> I2C1_SCL, W2 D$ u; H7 i
  10.   PA10   ------> I2C1_SDA , d8 I; m) [; X+ E$ P) y
  11.   */  y' C+ `( m9 R5 q- u4 r) Z
  12.   GPIO_InitStruct.Pin = LL_GPIO_PIN_9|LL_GPIO_PIN_10;" n3 p; w$ t  i; e+ p/ _
  13.   GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
    : W. `0 g' n' P3 x5 p  z
  14.   GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_LOW;$ v: p$ J1 ]! C! |  U% ?7 S" L: d
  15.   GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_OPENDRAIN;
    1 _) k8 |6 y4 f) U3 ~
  16.   GPIO_InitStruct.Pull = LL_GPIO_PULL_UP;  I& p5 k0 r* p5 D
  17.   GPIO_InitStruct.Alternate = LL_GPIO_AF_6;
    4 W  E% j  w* d3 Q5 I3 Q, u! U
  18.   LL_GPIO_Init(GPIOA, &GPIO_InitStruct);
    $ M  A8 C% O7 V3 Y; F. K
  19. 5 f, C8 c. ^9 |: Y' m/ Q
  20.   /* Peripheral clock enable */
    $ x" N2 D# z% {
  21.   LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_I2C1);
    0 w2 y; @# m- h) e- J. f/ O- I4 R

  22. & s. J6 w) _6 W0 U1 P9 ~
  23.   /** I2C Initialization ) e' c  ?# ^# n0 m
  24.   */& {* ~# s; g$ X+ E: `. `5 q9 l
  25.   I2C_InitStruct.PeripheralMode = LL_I2C_MODE_I2C;' |# i+ p3 G, V2 J
  26.   I2C_InitStruct.Timing = 0x00303D5B;  d7 M  \$ M5 [, k' _2 m
  27.   I2C_InitStruct.AnalogFilter = LL_I2C_ANALOGFILTER_ENABLE;; P  i; {" w# E" B
  28.   I2C_InitStruct.DigitalFilter = 0;
    ! }. e  y+ X' @% Q/ {9 m3 r& L8 d- K
  29.   I2C_InitStruct.OwnAddress1 = 0;  Y7 g9 @- E! C' F
  30.   I2C_InitStruct.TypeAcknowledge = LL_I2C_ACK;
    3 m2 D4 U$ y2 k9 L- S% I
  31.   I2C_InitStruct.OwnAddrSize = LL_I2C_OWNADDRESS1_7BIT;0 l* u) q4 E$ G4 t/ F6 ]
  32.   LL_I2C_Init(I2C1, &I2C_InitStruct);
    6 E6 Q8 _7 t1 u2 q  G- A: s$ ~# ~
  33.   LL_I2C_EnableAutoEndMode(I2C1);2 o, m& P. |* L6 D5 ~5 T' L) Z7 r/ u% l
  34.   LL_I2C_SetOwnAddress2(I2C1, 0, LL_I2C_OWNADDRESS2_NOMASK);! ]9 u( d% F: B. N
  35.   LL_I2C_DisableOwnAddress2(I2C1);% \2 d# l3 g; r4 y; ?
  36.   LL_I2C_DisableGeneralCall(I2C1);
    6 a2 Y3 `! n' Y) A& M) g" s
  37.   LL_I2C_EnableClockStretching(I2C1);& x! P2 l* U0 M( U
  38.   LL_I2C_Enable(I2C1);/ J9 g: G0 W& z% m
  39. }
复制代码
, y2 K4 k* X" d7 d; F
由于LL库未提供与HAL类似的I2C多数据读取的函数接口,所以需要自行编写函数,我这里是参照HAL库内的HAL_I2C_Mem_Write和HAL_I2C_Mem_Read写的LL库可使用的相对应函数。
0 q- S7 d, i' b8 }6 M+ Q
4 F0 M; D4 ?0 T( w" B$ DI2C读多个数据:, j/ Y9 \; p9 H9 O. N( d7 v
& d6 H, T5 }" I( t" `4 L) n
  1. void STM32I2C1_MasterRead(uint8_t device_7BitAddr, uint16_t mem_address,uint16_t mem_size,uint8_t *pdata,uint8_t length)
    - G; d( d- D7 g/ n$ `
  2. {' L# a& }- ]) }  r2 h8 o: {$ z. {9 ^
  3.     //等待iic空闲
    & @5 w  |/ Y- J8 E7 E
  4.     while(LL_I2C_IsActiveFlag_BUSY(I2C1));/ D3 H( l% R# t! M& m$ E
  5.     //确认iic是否使能
    * P$ Q+ B0 {/ L: C9 E+ k9 d
  6.     if(!LL_I2C_IsEnabled(I2C1))
    . x8 M" V2 U! G3 W' c
  7.     {( W0 F+ a2 Q  y9 b
  8.         LL_I2C_Enable(I2C1);2 d  @, s# ]& I$ U& S6 c# O
  9.     }
      m' U% w5 K; A3 t0 [2 S
  10.     //配置+ Z3 Q8 p" ?, [- r/ _+ W
  11.     LL_I2C_HandleTransfer(I2C1,device_7BitAddr,LL_I2C_ADDRSLAVE_7BIT,mem_size,I2C_SOFTEND_MODE,I2C_GENERATE_START_WRITE);
    ' J  h7 N# r( P% F4 e2 H4 U
  12.     while(!LL_I2C_IsActiveFlag_TXIS(I2C1));; H0 n, _% p) x2 b

  13. : A1 v8 \! L" `5 H$ U
  14.     //写入从设备寄存器地址4 p* l# x. d  s& f+ L
  15.     ucBSP_I2C1_WriteMemAddr(mem_address,mem_size);
    3 d6 K( t( l2 l' l7 V
  16.     while(!LL_I2C_IsActiveFlag_TC(I2C1));2 N2 i0 ?8 A5 v3 R5 e  a, q1 g

  17. # l* m8 l6 k9 M! ^% }
  18.     //配置
    " [6 \- n; Z0 y8 ~/ C5 r5 c+ y( u6 i
  19.     LL_I2C_HandleTransfer(I2C1,device_7BitAddr,LL_I2C_ADDRSLAVE_7BIT,length,I2C_AUTOEND_MODE,I2C_GENERATE_START_READ);
    9 B( v/ ?  @4 J! w  u" m2 Q
  20. * ^: ?1 p3 e- X& x1 n1 n0 F) z
  21.     //读取数据
    ) A! f+ V' G% k' t) F/ C
  22.     ucBSP_I2C1_ReadMultipleData(pdata,length);  o* {$ O3 ~* i" ]

  23. , ^4 o2 `) W8 B7 K# r
  24.     //等待停止完成  R$ v$ l( n9 T0 E% V$ x
  25.     while(!LL_I2C_IsActiveFlag_STOP(I2C1));- t. s$ T3 Z$ Q# C" |' `* U, \
  26.     LL_I2C_ClearFlag_STOP(I2C1);/ P8 q8 H9 K( {% a: ^
  27. }
复制代码
/ t: A7 k* _! ^
I2C写多个数据:. x6 C1 D" j. ?0 R0 b5 P

5 {- }( D7 U5 @. \- Z+ }
  1. void STM32I2C1_MasterWrite(uint8_t device_7BitAddr, uint16_t mem_address,uint16_t mem_size,uint8_t *pdata,uint8_t length)
    7 V5 K$ H: G. s
  2. {% Q& R8 d8 y- k" T' D
  3.     //等待iic空闲
    ; R7 Z/ r& b+ y, Q
  4.     while(LL_I2C_IsActiveFlag_BUSY(I2C1));; _3 R- ?1 L, n4 g, z
  5.     //确认iic是否使能
    & O3 q0 A4 z: x  J
  6.     if(!LL_I2C_IsEnabled(I2C1))+ ?. h- t, ]- N6 b$ `" A5 ?+ }
  7.     {! G+ \. J4 A7 |8 L& O& R$ l
  8.         LL_I2C_Enable(I2C1);. v+ [( v* `) R! F$ n
  9.     }2 l+ d4 I3 e# t% v! Q
  10.     //配置为写0 `7 T. l; t1 d9 E. m
  11.     LL_I2C_HandleTransfer(I2C1,device_7BitAddr,LL_I2C_ADDRSLAVE_7BIT,mem_size,I2C_RELOAD_MODE,I2C_GENERATE_START_WRITE);2 v  Q* m# G# @- t- r
  12.     while(!LL_I2C_IsActiveFlag_TXIS(I2C1));4 M1 }9 @6 k+ F3 D" w7 P. x
  13. 8 J2 x& v$ T- V7 v
  14.     //写入从设备寄存器地址: ~( j4 F4 Z. D. g" O+ r9 {
  15.     ucBSP_I2C1_WriteMemAddr(mem_address,mem_size);
    / M- e4 P/ U# ?. ?. i, t8 {
  16.     while(!LL_I2C_IsActiveFlag_TCR(I2C1));
    & a' f) ~0 B' F

  17. " e9 ^' D' ?  k) Z
  18.     //重新配置为自动停止模式
    0 @% o5 J. i9 ]2 Z
  19.     LL_I2C_HandleTransfer(I2C1,device_7BitAddr,LL_I2C_ADDRSLAVE_7BIT,length,I2C_AUTOEND_MODE,I2C_NO_STARTSTOP);
    8 O0 Y# F: |. I+ q) B; z

  20. ( i  s% \* j, T: o4 K
  21.     //写数据
    8 h8 d1 ]9 L/ F7 i
  22.     ucBSP_I2C1_WriteMultipleData(pdata,length);! K7 ]: u1 d0 G  s

  23. + f; e4 B% `" O, i/ }1 a9 b
  24.     //等待停止完成* p2 C+ C( b5 s; ^+ J
  25.     while(!LL_I2C_IsActiveFlag_STOP(I2C1));. V' v: r! J( {
  26.     LL_I2C_ClearFlag_STOP(I2C1);
      U( G  ~) i* |% x" Z0 a7 F
  27. }
复制代码
# B( k' |* y: n' y
为了减少代码重复和增加可读性,对读写的一些过程另作了函数;: D+ V# M3 e: Z. s- L. o

+ q$ N; X9 K- V6 r写寄存器地址:, ^6 N) y% l' U5 C5 {% e5 ]
9 S6 S1 q, c3 ~) v" E/ h0 f
  1. void STM32I2C1_WriteMemAddr(uint16_t mem_address,uint16_t mem_size)
    6 L6 t$ \6 p& ?( P( `/ p& p2 U
  2. {0 K2 I' t6 C# _3 O& E
  3.     uint8_t MemAddrLSB = I2C_MEM_ADD_LSB(mem_address);;
    4 Q! J3 r/ D0 ]& I
  4.     uint8_t MemAddrMSB = I2C_MEM_ADD_MSB(mem_address);;7 O2 B, A8 M. m2 W$ N
  5. - G1 j$ A( y2 C  }- m
  6.     //发送器件寄存器地址. o" G$ j( z: \" b6 v* {9 X6 @
  7.     if(mem_size == I2C_MEMADD_SIZE_8BIT)
    : G, V$ y3 k9 ?' I4 j% u/ f  S
  8.     {
      n' y0 g2 L& x$ S% m  K, K+ T
  9.         LL_I2C_TransmitData8(I2C1, MemAddrLSB);0 H6 G, `/ i- r3 L# p3 F. }
  10.     }else{
    & }4 I. u  q- F' P
  11.         LL_I2C_TransmitData8(I2C1, MemAddrMSB);
    ( g+ b1 y2 n) R1 D; n# |; @( C
  12.         //等待发送完成
      s8 E) U6 K" I$ C' ~
  13.         while(!LL_I2C_IsActiveFlag_TXIS(I2C1));5 g4 o- w9 F( ]
  14.         LL_I2C_TransmitData8(I2C1, MemAddrLSB);
    * G8 t6 B2 R5 C+ ^/ I
  15.     }
    ! Z; y4 J8 h. Y$ a; H0 X/ s
  16. }
复制代码

6 d, z1 u) o( ]. l* Y5 p) ~; g% ~连续写入小于255个数据:
! A' @; G, |2 X+ O* T$ A$ q5 U1 W$ X0 c- Z3 M" K0 n" l# E# |
  1. void STM32I2C1_WriteMultipleData(uint8_t *pdata,uint8_t length)
    % p/ p" A  l% Y+ a" e. ^
  2. {2 [' a' {, S2 z) M4 S8 O; x
  3.     uint8_t count;
    # E; y+ T6 c3 i1 D- W' s
  4.     for(count=0;count<length; count++)
    1 @5 j' p( S' U; G6 z( B
  5.     {6 u7 `, i8 `' O1 O$ V1 [$ S# ?
  6.         //等待发送完成  C2 u; k& _% [0 Z
  7.         while(!LL_I2C_IsActiveFlag_TXIS(I2C1));
    9 ?" D2 n( W7 ]/ n6 P/ _' e; J
  8.         LL_I2C_TransmitData8(I2C1, *(pdata+count));! f- E: H. z( @& b
  9.     }
    0 ]' R# F% z4 n" Q  ?
  10. }
复制代码
% {1 C4 z6 l2 \( Z8 I( O
连续读取小于255个数据:) B" v; ?+ D- U- J2 M

8 X/ n  y* S  S& Z7 n' @
  1. void STM32I2C1_ReadMultipleData(uint8_t *pdata,uint8_t length)5 s* a. H* E7 B8 v
  2. {
    + p& b. n- Y  t6 m- A0 C* \
  3.     uint8_t count;3 `$ p5 J, A) \' x. J
  4.     for(count=0;count<length; count++)
    $ y& C% v6 T" ^, p1 l4 y' O
  5.     {
    ) @( _2 H1 L' z7 h* N" ]5 ~- m+ u
  6.         //等待接收非空
    * D, H- p( n8 `$ L6 d  G" K
  7.         while(!LL_I2C_IsActiveFlag_RXNE(I2C1));
    4 k! V( X; p) i; G" }
  8.         *(pdata+count) = LL_I2C_ReceiveData8(I2C1);
    ) s- ]% W9 f& T$ ~2 K
  9.     }
    " k2 h) P$ v. O0 H0 K* Z
  10. }
    6 V. V4 Y# D8 k9 l% R0 @. T! v$ k. S
复制代码

& Q2 _* k. q1 [
& E  ]! J5 }# p
收藏 评论2 发布时间:2021-11-10 22:53

举报

2个回答
Spring_ly 回答时间:2023-1-12 13:32:15
你好,我想问一下,HAL库自带的函数可以连续写入256个字节,为什么改写的LL库的这个不能连续写入256个字节?
submer 回答时间:2023-4-27 15:53:32

有收获,感谢分享。

所属标签

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