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

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

[复制链接]
STMCU小助手 发布时间:2021-11-10 22:53
说明:驱动基于STm32G031K6,其他型号需自行做改动。
" t- f! Z; ^2 c2 ?0 [1 R6 o2 F  X/ q$ C: g' V9 H
注:因为之前项目暂未用到LL库的IIC,所以此驱动未经过实机验证。欢迎反馈使用中的问题。
9 c- L/ X8 }- d% X; M+ ^
  O( R. ~% Z) g0 V* u+ \( ?6 PIIC的初始化: CubeMX生成. d4 ]; ?$ n/ p& A6 d& I

: F  c2 F% e8 r; ]
  1. void STM32LLI2C1_Init(void)
      |6 U' j9 v/ i5 N; r
  2. {
    0 E" t- v2 L$ ^9 |$ j- z
  3.   LL_I2C_InitTypeDef I2C_InitStruct = {0};
    & X2 }8 K) u6 Z" D
  4. 2 a/ Y- K, d" V; s/ ]
  5.   LL_GPIO_InitTypeDef GPIO_InitStruct = {0};5 m* H4 X! b7 A8 X: C$ V4 Q
  6. * H& [* Z1 [0 X# F" W( C/ A
  7.   LL_IOP_GRP1_EnableClock(LL_IOP_GRP1_PERIPH_GPIOA);0 Y4 G8 A: @9 |8 q1 ^6 f
  8.   /**I2C1 GPIO Configuration  & Q8 q: `; K( \, w
  9.   PA9   ------> I2C1_SCL! v' \, y$ _0 Q+ S, V+ i. q& H& ]2 L
  10.   PA10   ------> I2C1_SDA
    . |& L4 q* j/ r; p) o
  11.   *// w3 j& o$ Z+ }. j" T: H3 k
  12.   GPIO_InitStruct.Pin = LL_GPIO_PIN_9|LL_GPIO_PIN_10;
    # C6 `! }" F" b  h5 C2 _  N
  13.   GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
    7 ?/ O7 \# q( c% M0 K5 d8 s" o4 _
  14.   GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_LOW;) f; O1 D# K! f6 {- t
  15.   GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_OPENDRAIN;& u' ~/ A+ T6 M' m  d% [4 h
  16.   GPIO_InitStruct.Pull = LL_GPIO_PULL_UP;
    8 Z- E4 A# ^7 t9 s; |
  17.   GPIO_InitStruct.Alternate = LL_GPIO_AF_6;9 T4 x2 l1 Q  m2 [
  18.   LL_GPIO_Init(GPIOA, &GPIO_InitStruct);+ V0 H& H5 o# f0 ]& r, p  N
  19. . {2 F- l4 G% P
  20.   /* Peripheral clock enable */7 o+ z0 Y# ~: Q+ [5 a% @. t
  21.   LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_I2C1);
    8 Z8 J4 E* U) p7 T
  22. 6 a7 @; v: R( O; K
  23.   /** I2C Initialization * A' D' ^/ K  A( b! T( n  x- B
  24.   */
    1 u; f) g' d* W$ Z& j
  25.   I2C_InitStruct.PeripheralMode = LL_I2C_MODE_I2C;$ q9 b: [' M1 z3 Q
  26.   I2C_InitStruct.Timing = 0x00303D5B;
    1 G0 R- d; P) F: b  i! s6 d
  27.   I2C_InitStruct.AnalogFilter = LL_I2C_ANALOGFILTER_ENABLE;
    & ^1 |+ K# A% M. N* {
  28.   I2C_InitStruct.DigitalFilter = 0;
    1 ]/ E+ J. m  X4 A& B8 v
  29.   I2C_InitStruct.OwnAddress1 = 0;& {2 X8 ~4 Q. ?% b4 g/ z+ i% S
  30.   I2C_InitStruct.TypeAcknowledge = LL_I2C_ACK;
    0 ]4 ~  y$ C% Q/ H2 B" d! z: [
  31.   I2C_InitStruct.OwnAddrSize = LL_I2C_OWNADDRESS1_7BIT;# b/ W8 q4 X, W& @
  32.   LL_I2C_Init(I2C1, &I2C_InitStruct);( q% N7 w6 s' K0 e3 D6 o7 z
  33.   LL_I2C_EnableAutoEndMode(I2C1);
    - q# \3 f, n, R+ E& j9 x
  34.   LL_I2C_SetOwnAddress2(I2C1, 0, LL_I2C_OWNADDRESS2_NOMASK);
    3 \# n& b0 C' |! \: `# n6 t: t
  35.   LL_I2C_DisableOwnAddress2(I2C1);. S: [9 T. R$ X! ?
  36.   LL_I2C_DisableGeneralCall(I2C1);
      n6 D2 g1 B0 Y& i6 k* G
  37.   LL_I2C_EnableClockStretching(I2C1);
    8 M; b" l3 K; _) T+ ]
  38.   LL_I2C_Enable(I2C1);+ n" a: h/ i) f# E" K
  39. }
复制代码

! \! X7 w4 d0 h  @由于LL库未提供与HAL类似的I2C多数据读取的函数接口,所以需要自行编写函数,我这里是参照HAL库内的HAL_I2C_Mem_Write和HAL_I2C_Mem_Read写的LL库可使用的相对应函数。
3 \4 b2 e0 C9 u2 B+ w& ~* j- z+ Y; A! ~9 ~1 V' t  y8 y
I2C读多个数据:
: y& @2 k7 k" s# Y) L4 b
7 o, k/ n* C- M2 o% V2 ]5 E& a
  1. void STM32I2C1_MasterRead(uint8_t device_7BitAddr, uint16_t mem_address,uint16_t mem_size,uint8_t *pdata,uint8_t length)
    ' q+ v5 s# J* x# l
  2. {
    1 X4 o' a: _" \# X+ D: Q! L4 a8 q
  3.     //等待iic空闲3 z6 E& f( D& c& E* U) Z3 D, v
  4.     while(LL_I2C_IsActiveFlag_BUSY(I2C1));
    - E! @! E& T0 G2 P) M0 w
  5.     //确认iic是否使能5 w5 m- }0 E; E4 C7 n
  6.     if(!LL_I2C_IsEnabled(I2C1))+ z6 _9 S# M1 }& D& F0 S. a
  7.     {9 E3 j4 Z* E) o. Y: @
  8.         LL_I2C_Enable(I2C1);
    2 N7 d! ~1 P& Y, E' q2 t4 Y
  9.     }
    6 v$ ]# ?: C2 s! v# }" h: O
  10.     //配置
    2 j# L; _) U7 Z4 V) j( F
  11.     LL_I2C_HandleTransfer(I2C1,device_7BitAddr,LL_I2C_ADDRSLAVE_7BIT,mem_size,I2C_SOFTEND_MODE,I2C_GENERATE_START_WRITE);
    ' p' C# r7 X. X3 _3 A' Z
  12.     while(!LL_I2C_IsActiveFlag_TXIS(I2C1));# ?9 w( D. d8 s# B) w
  13. * J3 b, B# x$ l0 G4 S
  14.     //写入从设备寄存器地址
    8 m9 s4 V1 S, E. D6 n4 h
  15.     ucBSP_I2C1_WriteMemAddr(mem_address,mem_size);
    * O) S! L# I. x$ P, v
  16.     while(!LL_I2C_IsActiveFlag_TC(I2C1));
    ; ]7 K! j6 _6 x  W  I+ J

  17. " X' c' d+ d5 N8 ^# F' Z8 C
  18.     //配置
    ' x& Y9 a# v8 h1 d
  19.     LL_I2C_HandleTransfer(I2C1,device_7BitAddr,LL_I2C_ADDRSLAVE_7BIT,length,I2C_AUTOEND_MODE,I2C_GENERATE_START_READ);
    5 e. r3 u* T0 x$ q. V4 t8 m
  20. 8 B% F* [( {- C% k: D0 k9 p
  21.     //读取数据9 c/ K2 u+ G4 L. L" U
  22.     ucBSP_I2C1_ReadMultipleData(pdata,length);
    3 D, N: c; [0 o' L+ N6 H
  23. 6 `; d4 j- @4 I: I7 @7 D6 @; b
  24.     //等待停止完成
    ! P! Y! `7 Q1 z) s
  25.     while(!LL_I2C_IsActiveFlag_STOP(I2C1));% d7 ^) W, @& ^8 L, P
  26.     LL_I2C_ClearFlag_STOP(I2C1);+ K" P9 @- P$ y3 u9 E
  27. }
复制代码

! E7 I+ K, b) ~" OI2C写多个数据:7 n$ z' @8 j8 A# C
6 o  M$ C& j' R6 i4 Y- g
  1. void STM32I2C1_MasterWrite(uint8_t device_7BitAddr, uint16_t mem_address,uint16_t mem_size,uint8_t *pdata,uint8_t length)
    1 o% M, E  `5 V& o+ p; w  u
  2. {/ F  j& ~# k, X" y; i0 d
  3.     //等待iic空闲7 w! h" }6 W4 C* Y. g
  4.     while(LL_I2C_IsActiveFlag_BUSY(I2C1));: b3 C. j7 D! a/ s% z9 O
  5.     //确认iic是否使能0 p1 x" i2 ]  e4 J9 G( y
  6.     if(!LL_I2C_IsEnabled(I2C1))
    1 E# ^3 ?  j" J
  7.     {
    3 g5 _: ^" `7 Q2 i
  8.         LL_I2C_Enable(I2C1);
    7 A3 p6 x7 {) o1 Y
  9.     }
    , }2 U  \3 D7 x3 i; w! F  m
  10.     //配置为写
    ( K, Q. l% u; T1 n7 j: X
  11.     LL_I2C_HandleTransfer(I2C1,device_7BitAddr,LL_I2C_ADDRSLAVE_7BIT,mem_size,I2C_RELOAD_MODE,I2C_GENERATE_START_WRITE);1 R+ ?, M9 \) b  S
  12.     while(!LL_I2C_IsActiveFlag_TXIS(I2C1));6 J" p" b1 V4 Y3 P. @+ t

  13. 9 S8 N( k! Y9 ~1 g
  14.     //写入从设备寄存器地址
    ) V1 u# B$ X! y1 r% Y' Z
  15.     ucBSP_I2C1_WriteMemAddr(mem_address,mem_size);
    4 D! R% P- p8 `/ Q( f* V
  16.     while(!LL_I2C_IsActiveFlag_TCR(I2C1));
    * E; C+ ~. g- G" D4 n9 P2 ~
  17. + y0 `; Q) o8 d) ?7 A) t' R
  18.     //重新配置为自动停止模式
    , F5 ]+ L: j/ @& V9 n2 [) W
  19.     LL_I2C_HandleTransfer(I2C1,device_7BitAddr,LL_I2C_ADDRSLAVE_7BIT,length,I2C_AUTOEND_MODE,I2C_NO_STARTSTOP);( }0 S2 x4 s: G$ z

  20. & V7 l9 ]9 m$ L3 M* F5 t
  21.     //写数据5 ^1 i+ s" o+ M+ |- u
  22.     ucBSP_I2C1_WriteMultipleData(pdata,length);
    + x- u2 I# j5 ]) r( {" j1 w  R
  23. ' H) \3 w5 E; S: {5 u, P
  24.     //等待停止完成
    5 X0 r5 X* \$ H
  25.     while(!LL_I2C_IsActiveFlag_STOP(I2C1));" r9 d- m7 `( f
  26.     LL_I2C_ClearFlag_STOP(I2C1);
    9 q! \) }# a0 k) P6 |
  27. }
复制代码
3 |0 h* M2 X+ r+ e8 y9 B+ ~* H
为了减少代码重复和增加可读性,对读写的一些过程另作了函数;
8 @5 t1 p) \+ j. x0 x, O+ G5 f$ j; ]% t1 o
写寄存器地址:" I3 }: a5 p( K* f1 s
$ ]3 P5 w4 }& Z+ c% q
  1. void STM32I2C1_WriteMemAddr(uint16_t mem_address,uint16_t mem_size)' T( v6 g  u* {- a( M3 E3 a
  2. {! i" ]* q) V4 n2 d/ L
  3.     uint8_t MemAddrLSB = I2C_MEM_ADD_LSB(mem_address);;7 G4 U0 a9 R# g) R0 [9 j2 A- h5 r# S
  4.     uint8_t MemAddrMSB = I2C_MEM_ADD_MSB(mem_address);;" G- e) t  `8 a9 ?7 i8 R, ^
  5. 1 j; ~& H: s$ U6 r3 k9 p
  6.     //发送器件寄存器地址
      u' }, W0 I) c8 e8 ]5 R
  7.     if(mem_size == I2C_MEMADD_SIZE_8BIT)3 \' E8 o- i8 n/ M  x
  8.     {) m* {: h, P) k. z
  9.         LL_I2C_TransmitData8(I2C1, MemAddrLSB);
    5 d3 N/ H9 m( n7 Q
  10.     }else{
    1 t. N) s- V7 D3 y- E
  11.         LL_I2C_TransmitData8(I2C1, MemAddrMSB);
    / P' n8 Z; C/ c# ?: N
  12.         //等待发送完成; y. W' p/ N4 p' f( f) D7 n
  13.         while(!LL_I2C_IsActiveFlag_TXIS(I2C1));4 f1 i+ C6 p+ M: G
  14.         LL_I2C_TransmitData8(I2C1, MemAddrLSB);4 K+ _' ]/ I, u
  15.     }. b4 O) }% I, h
  16. }
复制代码

. F( ^$ k1 i7 n& N连续写入小于255个数据:
0 j3 \0 T+ a6 o% o$ w/ c
* Z3 x9 c# k$ {+ X5 o4 a
  1. void STM32I2C1_WriteMultipleData(uint8_t *pdata,uint8_t length)) t$ k0 |4 h2 E. U" @: x, _6 \
  2. {
    + B4 h- X( \  x* R( Q& I
  3.     uint8_t count;5 f! s2 E8 S, `4 d" x
  4.     for(count=0;count<length; count++)
    : _% D9 x6 S8 @- }
  5.     {3 b; v8 [! H0 U7 r: o" B
  6.         //等待发送完成1 n" m. U2 p. G2 G4 ]7 A4 q: P
  7.         while(!LL_I2C_IsActiveFlag_TXIS(I2C1));
    : H6 n! [/ j8 E% t0 X
  8.         LL_I2C_TransmitData8(I2C1, *(pdata+count));  b7 H8 p4 }" P. K/ g. n; y
  9.     }
    8 S( Y4 m# A2 o% I* S5 d8 s1 b% B  @
  10. }
复制代码
5 L! R) F& R# h9 Y
连续读取小于255个数据:8 i( ]& X! N# t5 A9 d; Z0 p9 V; V+ m

% w/ R- s, x- l1 M# o
  1. void STM32I2C1_ReadMultipleData(uint8_t *pdata,uint8_t length)
    / k1 N" H5 p8 Z2 q# A, z) S: K
  2. {
    , ~$ A" L7 |+ V$ l
  3.     uint8_t count;/ ~& j+ T/ M' n# N
  4.     for(count=0;count<length; count++)0 L6 L! u; s9 C, q6 x. y
  5.     {3 m: |; x+ z% k7 R. u6 |5 d
  6.         //等待接收非空
    , _. ^) v' N" R: F# D5 Z+ u* g, H" V
  7.         while(!LL_I2C_IsActiveFlag_RXNE(I2C1));5 N5 h( R8 Z0 i2 V0 K3 Z
  8.         *(pdata+count) = LL_I2C_ReceiveData8(I2C1);- D) U# Z+ O" A2 P4 L
  9.     }
    8 i8 a' L0 _* }1 i
  10. }( I" e7 G; |1 O. H4 E
复制代码

1 x3 F  s. x* m0 o; a9 f
- B% A" j# O/ Z2 @
收藏 评论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管理
行使您的权利
官方最新发布
STM32Cube扩展软件包
意法半导体边缘AI套件
ST - 理想汽车豪华SUV案例
ST意法半导体智能家居案例
STM32 ARM Cortex 32位微控制器
关注我们
st-img 微信公众号
st-img 手机版