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

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

[复制链接]
STMCU小助手 发布时间:2021-11-10 22:53
说明:驱动基于STm32G031K6,其他型号需自行做改动。
$ Y: W  U) x/ k) P* p. ?1 @' \3 G- I3 q7 T  G# p/ f# R
注:因为之前项目暂未用到LL库的IIC,所以此驱动未经过实机验证。欢迎反馈使用中的问题。
$ a5 Q, ^; D8 O( H6 U2 m, W" O; P" I9 V% J5 D$ q
IIC的初始化: CubeMX生成
! `( _/ ?4 G4 L" G' C* W1 f/ R$ f  u$ Z, [
  1. void STM32LLI2C1_Init(void)
    ' j4 }& r, R( v" q- A. E$ g: b. T
  2. {
    ! C0 o4 N8 t6 u. E* J
  3.   LL_I2C_InitTypeDef I2C_InitStruct = {0};9 A4 @2 P3 @  R$ E2 n5 \
  4. 0 C$ e5 Z% V! r3 T9 Q
  5.   LL_GPIO_InitTypeDef GPIO_InitStruct = {0};4 D: p) @" J* X, B

  6.   ~6 t+ v0 C# s
  7.   LL_IOP_GRP1_EnableClock(LL_IOP_GRP1_PERIPH_GPIOA);, a/ n& Q( z& q1 [" L
  8.   /**I2C1 GPIO Configuration  
    : g4 ^+ _- z9 g( ]# _" ^7 [7 b
  9.   PA9   ------> I2C1_SCL' r& E8 ?" L; d6 X9 a
  10.   PA10   ------> I2C1_SDA . r2 k7 W% k" Q9 ?3 a7 E- j8 w) U
  11.   */2 ]5 w' u# M7 O' J9 `2 v' t% s& h
  12.   GPIO_InitStruct.Pin = LL_GPIO_PIN_9|LL_GPIO_PIN_10;
    $ n, `8 y" `  y6 c  A
  13.   GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
    - g8 i3 w# z  W  e
  14.   GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_LOW;
    - C% i, v' ]0 u+ m: m
  15.   GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_OPENDRAIN;- {* e+ F- T8 v( @& o" E+ g
  16.   GPIO_InitStruct.Pull = LL_GPIO_PULL_UP;
      v% X5 o* N. d; l' Z& G
  17.   GPIO_InitStruct.Alternate = LL_GPIO_AF_6;6 b0 }+ m/ n( f7 p+ k3 q4 f) \
  18.   LL_GPIO_Init(GPIOA, &GPIO_InitStruct);
    ! C/ x7 e! D) X7 {: d' l
  19.   s% m7 P. r% h
  20.   /* Peripheral clock enable */) @+ ^7 M0 G: N% P# X: ~" @/ V, {
  21.   LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_I2C1);. V* x1 M/ q2 x
  22. # Q' J2 V0 ^: S0 _% A
  23.   /** I2C Initialization
    % O" _5 N6 o4 E- h  E  M, D
  24.   */
    8 t) n, ]% N/ H  P+ S0 N; t
  25.   I2C_InitStruct.PeripheralMode = LL_I2C_MODE_I2C;0 m- J/ ]" h( s& ?  _, z0 ^
  26.   I2C_InitStruct.Timing = 0x00303D5B;
    " Y) |# w1 ^# v* m
  27.   I2C_InitStruct.AnalogFilter = LL_I2C_ANALOGFILTER_ENABLE;3 J) h  }" t5 V! R, u  }4 X5 J
  28.   I2C_InitStruct.DigitalFilter = 0;
    * v9 J: l+ \! ?& |& I8 B, M/ v, e) H6 o
  29.   I2C_InitStruct.OwnAddress1 = 0;
    7 |- m4 ]' V( |3 ~
  30.   I2C_InitStruct.TypeAcknowledge = LL_I2C_ACK;3 J1 m6 o! P' m) I+ G. M
  31.   I2C_InitStruct.OwnAddrSize = LL_I2C_OWNADDRESS1_7BIT;
    6 ^5 J; |/ X7 G3 ], ]8 \! D
  32.   LL_I2C_Init(I2C1, &I2C_InitStruct);
    " u) `: P( f  [8 C0 f
  33.   LL_I2C_EnableAutoEndMode(I2C1);
    5 F3 c/ h' N0 G/ a
  34.   LL_I2C_SetOwnAddress2(I2C1, 0, LL_I2C_OWNADDRESS2_NOMASK);) |& z4 \1 |6 c5 P  G% z
  35.   LL_I2C_DisableOwnAddress2(I2C1);; _, Y- N( m& _
  36.   LL_I2C_DisableGeneralCall(I2C1);: b; M2 X3 @" o' Y. @
  37.   LL_I2C_EnableClockStretching(I2C1);
    - v& _$ O) s: l' ?% i$ J" `
  38.   LL_I2C_Enable(I2C1);
    8 `% t, n# E! C" E$ J6 b
  39. }
复制代码

3 ]2 F; m, i) t8 o- n8 o4 A4 R由于LL库未提供与HAL类似的I2C多数据读取的函数接口,所以需要自行编写函数,我这里是参照HAL库内的HAL_I2C_Mem_Write和HAL_I2C_Mem_Read写的LL库可使用的相对应函数。
- |9 F$ F. S3 o$ ?% K
: _- X. P, ]6 O( FI2C读多个数据:- a# @( A: b2 [2 t1 y5 T0 [
3 W) S# d$ x% ~7 _1 Y2 j* g
  1. void STM32I2C1_MasterRead(uint8_t device_7BitAddr, uint16_t mem_address,uint16_t mem_size,uint8_t *pdata,uint8_t length)0 W2 T( ~4 r' a: T
  2. {
    8 n& h- s5 W1 g  T/ N5 \( S) a. s0 y
  3.     //等待iic空闲7 U8 w6 t& w4 b
  4.     while(LL_I2C_IsActiveFlag_BUSY(I2C1));
    2 C: l2 [1 n' {' p( p# v
  5.     //确认iic是否使能' B- b7 C2 p( ~* Q& v: o$ \# E& o7 I
  6.     if(!LL_I2C_IsEnabled(I2C1))& R6 h2 s: |) r$ Z8 u
  7.     {
    6 B, W$ L/ J& j1 R
  8.         LL_I2C_Enable(I2C1);
    : _" S8 s. t/ O5 }
  9.     }
    / B3 v# `0 R8 g
  10.     //配置5 C# Q2 e3 \& C) A% g
  11.     LL_I2C_HandleTransfer(I2C1,device_7BitAddr,LL_I2C_ADDRSLAVE_7BIT,mem_size,I2C_SOFTEND_MODE,I2C_GENERATE_START_WRITE);
    & E1 ~% F% g4 a: B0 U6 [" D/ J$ J# @
  12.     while(!LL_I2C_IsActiveFlag_TXIS(I2C1));
    9 m8 G$ Q! M+ |

  13. & S5 D, Y; h6 p; L4 Q6 J% ]
  14.     //写入从设备寄存器地址
    ( K; Z5 a2 ]4 U1 C
  15.     ucBSP_I2C1_WriteMemAddr(mem_address,mem_size);& f2 D* n5 v. ]% R! s
  16.     while(!LL_I2C_IsActiveFlag_TC(I2C1));
    * w: W& F& z2 f. O8 |

  17. % `% w5 L) P# z7 P1 Z7 \5 @1 k
  18.     //配置
    ) X9 `5 T+ o7 l2 o: R
  19.     LL_I2C_HandleTransfer(I2C1,device_7BitAddr,LL_I2C_ADDRSLAVE_7BIT,length,I2C_AUTOEND_MODE,I2C_GENERATE_START_READ);
    6 v! d1 k6 ]' p+ r
  20. , A+ l6 j3 c  [$ D
  21.     //读取数据+ C2 D( @- z  V6 c' i2 u/ I1 u
  22.     ucBSP_I2C1_ReadMultipleData(pdata,length);, A, P5 q1 E; ?; @! w+ U; W
  23. ! c5 e7 Y/ Z) z8 m4 J# L- w0 M( p3 N3 T
  24.     //等待停止完成5 A$ @8 Z$ Z0 a3 d3 k
  25.     while(!LL_I2C_IsActiveFlag_STOP(I2C1));
    * m, P$ ]9 A! @* W- d, d3 M
  26.     LL_I2C_ClearFlag_STOP(I2C1);  b6 J7 l! G( a1 Q
  27. }
复制代码
" C7 G/ o* g% S2 d! }, d
I2C写多个数据:
4 r$ \& S- s; |& x
, w  @6 n$ u4 A1 S- i- X8 w
  1. void STM32I2C1_MasterWrite(uint8_t device_7BitAddr, uint16_t mem_address,uint16_t mem_size,uint8_t *pdata,uint8_t length)! V) y7 K. K7 D% e% s+ ~5 ?
  2. {
    0 E, u9 K* i: U: T  {/ t8 }! A
  3.     //等待iic空闲
    : @% e; W$ @( C/ Z9 S
  4.     while(LL_I2C_IsActiveFlag_BUSY(I2C1));6 E4 a: d+ `0 ?; x: A# V. y" b4 S
  5.     //确认iic是否使能
    $ F! h9 ?$ ]; R% F
  6.     if(!LL_I2C_IsEnabled(I2C1))
      t0 S- j5 ]. }6 ~
  7.     {
    " Y- V# ^. I# P, D/ v
  8.         LL_I2C_Enable(I2C1);- a, z( ~/ n; ~3 H
  9.     }1 M" i: g6 y9 T" `: z# A* I
  10.     //配置为写- Q9 F$ m. j4 f! r" c& o
  11.     LL_I2C_HandleTransfer(I2C1,device_7BitAddr,LL_I2C_ADDRSLAVE_7BIT,mem_size,I2C_RELOAD_MODE,I2C_GENERATE_START_WRITE);# T6 f+ _, `# c/ ~1 k* I# C
  12.     while(!LL_I2C_IsActiveFlag_TXIS(I2C1));& v+ ]* b: j. _( L! T
  13. 6 |2 p5 k# s: r" ]3 G) {
  14.     //写入从设备寄存器地址% g( @- e/ p6 B8 P' Q* U; V
  15.     ucBSP_I2C1_WriteMemAddr(mem_address,mem_size);
    1 o% L" Z. M$ W6 r( |( g, l
  16.     while(!LL_I2C_IsActiveFlag_TCR(I2C1));
    - Z, A# K5 T) Q9 ]+ X4 W9 k

  17. 4 Y$ _8 q4 N1 b
  18.     //重新配置为自动停止模式
    1 R, b7 `4 A7 x" B2 P5 K
  19.     LL_I2C_HandleTransfer(I2C1,device_7BitAddr,LL_I2C_ADDRSLAVE_7BIT,length,I2C_AUTOEND_MODE,I2C_NO_STARTSTOP);
    , i& j5 E% ~$ ]9 s' \8 ~3 O
  20. , E: w0 D1 [7 @6 X  Q
  21.     //写数据
    3 v; y, h# G- |
  22.     ucBSP_I2C1_WriteMultipleData(pdata,length);
    " h, L2 r- q5 N7 p+ V) }4 j

  23. # Q6 ?: l! ]8 I+ t/ P
  24.     //等待停止完成8 f6 @- J3 r: @% D6 S
  25.     while(!LL_I2C_IsActiveFlag_STOP(I2C1));
    3 A, Q0 p& ]- u: e* L
  26.     LL_I2C_ClearFlag_STOP(I2C1);: }9 F) s6 ?; c) W2 K) j9 z! G8 I) X
  27. }
复制代码

# c" t3 c" F: g6 e  i9 g为了减少代码重复和增加可读性,对读写的一些过程另作了函数;9 U2 E/ Z9 k3 b( N6 C
  E1 t" E" \( M2 [
写寄存器地址:
" t$ g1 h' ]7 i1 J, z2 _6 j1 o6 R/ |8 @% b, ?1 k, _5 q
  1. void STM32I2C1_WriteMemAddr(uint16_t mem_address,uint16_t mem_size)2 |! e6 _& J9 F2 k# f' t6 H" L; x7 n
  2. {. o: @6 {( |8 G+ _4 h' t5 @
  3.     uint8_t MemAddrLSB = I2C_MEM_ADD_LSB(mem_address);;5 a/ }) H' `! a3 ?2 h! [( @; v
  4.     uint8_t MemAddrMSB = I2C_MEM_ADD_MSB(mem_address);;
    8 W. Z% m& g) X
  5. & E7 F( z% j8 B0 b" m7 h+ M4 p, H
  6.     //发送器件寄存器地址& J: `0 q1 {7 j+ L; H, l$ n
  7.     if(mem_size == I2C_MEMADD_SIZE_8BIT)
    6 [, W  |! }' x
  8.     {
    1 I, t$ ~; l$ @% @. r, H1 m
  9.         LL_I2C_TransmitData8(I2C1, MemAddrLSB);
    - G* L: V5 T' h: e, ~2 @6 P- m2 {
  10.     }else{
    # E* Q! k* F( a. C: r+ W+ N7 e& A" A
  11.         LL_I2C_TransmitData8(I2C1, MemAddrMSB);" \2 P; [( L* c  _" Y1 H
  12.         //等待发送完成
    3 I7 T/ V) Z! S
  13.         while(!LL_I2C_IsActiveFlag_TXIS(I2C1));& L# M5 h* l# Q& G, K0 L- o
  14.         LL_I2C_TransmitData8(I2C1, MemAddrLSB);2 V. j% k6 b3 ]6 m' h
  15.     }
    5 R* M. ]" h5 L* S
  16. }
复制代码

3 u- q0 n2 c  U连续写入小于255个数据:
* a2 X- K8 F  J0 _! ?, C1 {
+ o: T/ Q, Z7 I' s! p) Q+ A
  1. void STM32I2C1_WriteMultipleData(uint8_t *pdata,uint8_t length)& T7 T7 O) d) G+ ?4 K5 M
  2. {& R# N2 Y8 ]7 X4 ^; |
  3.     uint8_t count;! J2 z: N9 s. P
  4.     for(count=0;count<length; count++)
    : M& @- x  s$ r* G5 e5 z
  5.     {
    * d! }" A7 Z- U$ F( ~, T
  6.         //等待发送完成) g2 j- n# M& S9 s2 T! c2 F
  7.         while(!LL_I2C_IsActiveFlag_TXIS(I2C1));6 q: [5 }) A, g. |
  8.         LL_I2C_TransmitData8(I2C1, *(pdata+count));
    6 e4 M5 a" s# u' c2 P6 M0 \
  9.     }2 l$ ?4 z  l! V  W( {& W* u
  10. }
复制代码

4 u8 b8 W: p+ r3 Y3 s6 P连续读取小于255个数据:
8 t9 W  m  C! L) Z! Y2 O$ r8 {8 [) [* O" ?2 u
  1. void STM32I2C1_ReadMultipleData(uint8_t *pdata,uint8_t length)2 y5 b" p6 _& x% C! j, h
  2. {& A9 c5 T' P' \7 Q+ H1 K% A# o
  3.     uint8_t count;/ ~" [9 W; ^% h9 V* A8 ?; M
  4.     for(count=0;count<length; count++)
    ) x4 R  R. e9 C" J$ i$ L
  5.     {
    . [$ q* c# H( ~
  6.         //等待接收非空/ ?( g( O. B: ?" {+ J" l0 b
  7.         while(!LL_I2C_IsActiveFlag_RXNE(I2C1));" d2 ]5 r2 v+ n6 t9 V2 D  P
  8.         *(pdata+count) = LL_I2C_ReceiveData8(I2C1);  R/ X$ |  g8 B
  9.     }
    4 I4 ]/ c2 o: \+ b
  10. }, m( b  x) f$ Y1 v$ Z
复制代码
- A8 i% u% u$ j1 O9 q0 s2 [
, L9 t% c# W9 U7 k/ A& ?
赞 收藏 评论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 手机版