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

STM32CubeMx入门教程(7) I2C的读写应用

[复制链接]
STMCU小助手 发布时间:2021-1-6 10:19
STM32CubeMx入门教程(7) I2C的读写应用
- k& P  v. O! ~
导语“本次 教程使用CubeMx配置I2C进行I2C总线设备的数据读写操作,使用EEPROM作为实验对象”
01
------------第一节 系统要求----------
9 K" f! T- c% A( s) E
•硬件
野火指南者开发板

( t' F/ A: m% G0 T
•软件
8 B# G3 o+ v& v1 D7 o! V% I" ?
CubeMx & MDK & 串口调试助手
& e) I6 V# ^/ T! w
•原理图
2.1.png
: U2 c; e, l5 _4 ^2 ]

5 d8 G5 R3 j2 L' B8 \; i% [, H/ M
1 m( d: v8 s/ F# `9 a
' {0 K+ i- l* }9 V
  R* K7 f. ]: C6 m  e
我们可以从原理图中得到使用的I2C1,AT24C02的设备地址的第三位是000,容量是256个字节。设备地址从下图得到:
2.2.png
7 b  W+ e" v: Y$ M
. b, b$ m- x8 u* l
% R/ _" H% ~! y" K' ]8 R
& h4 s& u' F; G% `& G
不带读写方向的使用左移得到的地址为0b10100000->0xA0, 读地址为:0xA1,写地址为0xA0;

  l; F$ p! Q  m# Y# P; J
注意:(1) 操作ATC02的时候,多字节写入的时候没写入一个字节,延时最小5ms, 多字节读的时候没有要求,页写入的时候每8个字节为一页,共32页。

1 D! v& j- ?3 W& m- z! M+ K
02
------------第二节 CubeMx的配置----------
' t* g! f9 D- `- R  U) {. V

+ z: S$ ]9 G- _8 J' z
我们依然使用之前的USART的项目,在此基础上进行I2C的配置,串口的使用是进行EEPROM读写数据显示在控制台上,使用CubeMx进行I2C的配置:
2.3.png
/ }5 N& U' F& h# M& @4 A2 R. `8 N! j

; J6 v4 r1 A0 H9 n" q6 O" ?0 p, W; i; X
# q+ f: L1 C/ N! G) V2 x
I2C的配置很简单,完成上述配置后生成代码。
8 L% J$ F- f# w7 N# j+ S
, S9 e$ d6 d1 S
03
------------第三节MDK的代码编写----------
使用MDK打开CubeMx生成的代码进行应用代码编写。
(1)在main.c 中进行AT24C02的相关宏定义和变量定义:

  q" {! D! `: m
  1. #define ADDR_AT24C_Write 0xA0" u6 `/ ?/ S: J8 l/ D
  2. #define ADDR_AT24C_Read  0xA19 @' r8 w. |( U+ H3 e
  3. #define DEV_ADDR_ATC02   0xA0 //0x50 左移得到的。1 s! {' L9 l2 W5 q; X6 J
  4. #define ATC02_BufferSize 256   // 256
    ( I4 X* C9 n1 Z' Q5 V- E1 o
  5. #define I2C_TIMEOUT                0xFF, N$ D( `* r" o8 S: r
  6. #define AT_I2C              hi2c1
    7 o& z0 V2 ]6 X% h' C
  7. uint8_t AT24_WriteBuffer[ATC02_BufferSize],AT24_ReadBuffer[ATC02_BufferSize];
复制代码
8 F- L* ^% N# q" ]  {
  @  }1 R: E/ g8 a. u# ?. k2 p4 c8 M
(2) 应用函数申明:

% B( l% r9 U5 u$ R
  1. HAL_StatusTypeDef I2C_Write_Buffer(I2C_HandleTypeDef *hi2c,\, r) c$ b4 @5 a/ K9 J, K
  2. uint16_t DevAddress, uint16_t MemAddress,\6 H& _; K  Z8 A% N% G5 i; N# j* s
  3. uint16_t MemAddSize, uint8_t *pData, uint16_t Size,\
    5 U! |3 t8 ~+ K( g
  4. uint32_t Timeout);
    1 }* v  Q1 z" }, O; m
  5. HAL_StatusTypeDef I2C_Read_Buffer(I2C_HandleTypeDef *hi2c,\) H  v6 T5 s6 i  [8 L+ }
  6. uint16_t DevAddress, uint16_t MemAddress,\
    " |3 C9 L; m# c  Y6 z6 c4 w# {
  7. uint16_t MemAddSize, uint8_t *pData, uint16_t Size,\) l2 Q- c  f; S5 p
  8. uint32_t Timeout);
复制代码

, Q& S. g& a; \" a4 ]0 c
1 }8 S8 B; L3 V- ]& k) k
I2CWriteBuffer()是自定义的任意字节写入I2C-AT24C02的函数,I2CReadBuffer()是任意字节读写函数。这两个函数的实现采用HAL库的这两个函数:
1)HALStatusTypeDefHALI2CMemWrite(I2CHandleTypeDef *hi2c, uint16t DevAddress, uint16t MemAddress,uint16t MemAddSize, uint8t *pData, uint16t Size, uint32_t Timeout);
- x6 g% p; u6 g, H
参数依次是:(I2C句柄,AT24C02的设备地址,设备中数据地址,数据地址的大小,写的数据,数据大小,超时时间)
0 s3 H8 e7 \4 n3 K
2)HALStatusTypeDefHALI2CMemRead(I2CHandleTypeDef *hi2c, uint16t DevAddress, uint16t MemAddress,uint16t MemAddSize, uint8t *pData, uint16t Size, uint32_t Timeout);

5 \  H, Z; l* u8 H& T8 I
参数依次是:(I2C句柄,AT24C02的设备地址,设备中数据地址,数据地址的大小,读出数据,数据大小,超时时间)
9 v' J3 N5 k- B( q$ b
为什么不直接使用库函数呢?是因为在测试中AT24C02读写不正常,查看AT24C02的手册发现,单个字节写入没问题,多字节的写入需要每个字节延时5ms, 其实多字节的读没有问题,这个从新实现了下。可以连续8个字节的页写入,这个不需要延时。

5 d3 c+ y5 B1 C. B' _, v* G! ]
(3)多字节的读写函数:
( y, U) e8 i7 v: ~2 y
  1. /*这里自己实现多字节的ATC02的写操作*/  C, _4 U2 c+ w! k
  2. HAL_StatusTypeDef I2C_Write_Buffer(I2C_HandleTypeDef *hi2c,\9 q1 E' \7 l* H( g5 v+ q! ]
  3. uint16_t DevAddress, uint16_t MemAddress,\9 R' N6 O" F& u) B
  4. uint16_t MemAddSize, uint8_t *pData, uint16_t Size,\
    ) _( T& f0 A0 f2 k
  5. uint32_t Timeout)# J6 z' R$ e6 d9 `
  6. {9 R2 b- z' P' @; q
  7.        uint16_t count=0;1 `$ F3 U' M* ?
  8.        for(count=0;count. Y  e, A8 W  A' l* k
  9.        {
    9 E" q  `) \( `3 ]/ ?. j( z# w$ v
  10.               if(HAL_I2C_Mem_Write(hi2c,DevAddress,MemAddress, MemAddSize,pData,1,Timeout)==HAL_OK). u) Q1 A5 F9 ~  N1 ?1 P' S
  11.               {0 {$ t, \" g. `! g) i, o
  12.                      MemAddress ++;
    3 N3 y/ d+ {9 h
  13.                      pData ++;- s5 C& W$ R' R. t* _
  14.                      HAL_Delay(5);8 v. ^& Z! d+ B5 z2 z
  15.               }
    " [8 P3 |/ \  I. F
  16.               else; H! e5 C; {) d) z* L* s+ u
  17.               {
    . A2 h- d4 o, v9 B1 t& C" Y
  18.                      printf("i2c write is error \t\n");; z. n- D" c: W/ [
  19.                      return HAL_ERROR;' u' K) C$ e  f; j8 j
  20.               }; W% L3 x2 v! e# r1 U6 w% H
  21.        }$ m) N7 N; |- D" U
  22.        return HAL_OK;3 C" v( m0 r7 ~+ U, P
  23. }/ R/ ^8 N$ X# h# Z. {
  24. /*这里自己实现多字节的ATC02的读操作*/$ P' ^1 X0 L1 H
  25. HAL_StatusTypeDef I2C_Read_Buffer(I2C_HandleTypeDef *hi2c,\
    1 M3 H0 p: T% p* b- r8 p5 A0 R
  26. uint16_t DevAddress, uint16_t MemAddress,\
    ' V- G" ^+ W+ u; m8 n
  27. uint16_t MemAddSize, uint8_t *pData, uint16_t Size,\( F; L0 M5 T! R3 y1 R$ x
  28. uint32_t Timeout). p! U  ]# \3 J' W% D$ [$ D
  29. {6 c7 N+ P+ i: u: T) W! M
  30.        uint16_t count=0;( m+ L6 n: E; A! d, W& w7 R
  31.        for(count=0;count<Size;count ++)3 p* ^6 v8 {. C* b' B% X
  32.        {, j# D9 X0 k+ @" c4 Y# ~
  33.               if(HAL_I2C_Mem_Read(hi2c,DevAddress,MemAddress, MemAddSize,pData,1,Timeout)==HAL_OK)8 E: }6 }) \" ]* [9 O4 O+ M
  34.               {
    * L0 \2 K1 w; `: \5 ?
  35.                      MemAddress ++;
    - s* s( Z$ l; Q. ]6 L/ k4 b
  36.                      pData ++;$ S# b& k# J  K$ Z0 \/ k% `' t
  37.                      //HAL_Delay(5);  h' I, D) E5 [
  38.               }
    8 |8 k1 P7 o  e9 B1 Z7 Y
  39.               else
    / Y# l# v1 g2 v6 P* L3 d
  40.               {' m% E  L. ]2 v% Z
  41.                      printf("i2c read is error \n");
    2 a- p# y1 Y! y
  42.                      return HAL_ERROR;9 v9 L7 ~: P7 m: |! y
  43.               }+ @7 r& k8 M8 j$ }+ a
  44.        }
    ( h1 i* z6 w1 l7 T0 ]4 b; X
  45.        return HAL_OK;
    1 ?& \- l7 H2 H( W8 ^. t8 O
  46. }
复制代码

8 v3 `+ o3 T- F4 C
(4)在main函数中添加测试代码:

7 w4 i' S+ }; O1 C! y8 P
  1. uint16_t num_atc=0;
    8 s7 ^: j' a1 ^" c. T7 b
  2.        printf("this is test for I2C device read and write in ATC02\r\n");4 b* `( H1 _& ^2 p  [$ U
  3.        printf("/**--------------------开始I2C-------------------------**/\r\n");' D' g! \, |& U/ J: @/ b
  4.        for( num_atc=0;num_atc0 i3 g& z; ?4 d( |: G% @. W
  5.        {, e6 ~( f; |( d5 _
  6.               AT24_WriteBuffer[num_atc]=num_atc;0 X. u4 M7 C( t9 i" Y' O/ W
  7.               printf("0x%x\t",AT24_WriteBuffer[num_atc]);      
    . B" `# @3 `7 r) `7 X# Q# e2 O, j
  8.        }
    8 w3 P$ U: [. G% |  @- ~
  9.        if(I2C_Write_Buffer(&AT_I2C,DEV_ADDR_ATC02, 0, I2C_MEMADD_SIZE_8BIT,AT24_WriteBuffer,ATC02_BufferSize, I2C_TIMEOUT) == HAL_OK)
    + y" Q) \/ r) W2 _# `( s
  10.        {% G* W7 p( C# Z. [1 r/ j! G
  11.               printf("write i2c lots bytes is ok\t\n");
    6 Q3 H/ L$ v& k
  12.        }/ z1 Y4 c# D4 c; h5 p: {4 `8 V3 _
  13.        if(HAL_I2C_Mem_Read(&AT_I2C,DEV_ADDR_ATC02, 0, I2C_MEMADD_SIZE_8BIT,AT24_ReadBuffer,ATC02_BufferSize,I2C_TIMEOUT)== HAL_OK). H3 w6 j$ e, n! Y* o' f9 l
  14.        {
    : f/ n) X1 |+ `8 v
  15.               printf("\r\n EEPROM 24C02 read data Test OK \r\n");* g. `9 {9 S+ z/ y" D8 g
  16.        }
    6 |6 r9 i; K9 o% h. a, U
  17.        else
    3 J  z; j9 k% |/ B( P" }8 `
  18.        {
    ) j  l2 J" Y# V) W  B
  19.               printf("\r\n EEPROM 24C02 read data Test False \r\n");
    ' |( j, ]- ^6 n% I# A5 ~" \3 S+ J8 J
  20.        }
    + |1 b1 ~5 Z" q5 Y4 A4 q
  21. /*这里使用自定义多字节读函数也是正常的*/5 K3 L" V  Q! p: k$ G
  22. /*
    " e% Y- E: u. L; o
  23.        if(I2C_Read_Buffer(&AT_I2C,DEV_ADDR_ATC02, 0,               I2C_MEMADD_SIZE_8BIT,AT24_ReadBuffer,ATC02_BufferSize,I2C_TIMEOUT)== HAL_OK)' I  `  g9 ]( H* Q, k- h- u( R- n9 T
  24.        {) O- h4 F: ~- I4 P! M4 F
  25.               printf("i2c read lots is ok\t\n");
    : M0 X; S9 [7 o! @
  26.        }
    & }/ F) T- B* L! J( ?) j
  27. */1 P- R. P, X1 L. s  v+ g
  28.        for(num_atc=0; num_atc<ATC02_BufferSize; num_atc++)
    * D+ ?8 @8 x, m; B5 p1 u1 A
  29.        {! t1 I7 F& E+ s: ~6 b
  30.               printf("0x%x\t",AT24_ReadBuffer[num_atc]);
    6 @% `5 U% D& V$ ]. l- f
  31.        }
    4 Z2 A+ B( q2 B
  32.        if(memcmp(AT24_WriteBuffer,AT24_ReadBuffer,ATC02_BufferSize) == 0 ) /* check date */; x& ]5 P' M3 C4 d, B# h: x
  33.        {
    2 X' N, m5 `1 s% m: s* c
  34.               printf("\r\n EEPROM 24C02 Read and write Test OK\r\n");
    * N  `/ ~6 V3 ^* |8 W$ h( ?* j
  35.        }) e" T7 k  o0 p
  36.        else
    0 Q3 X4 u. M9 D+ A5 d5 u0 J; m
  37.        {* i: }8 Y6 Z8 x! z! X
  38.     printf("\r\n EEPROM 24C02 Read and write Test False\r\n");
    3 L0 l5 a; T; o
  39.        }       + m) N. O6 m6 h! a* \2 X
  40.        printf("/**--------------------结束I2C-----------------**/\r\n");
复制代码

% C2 k+ E% t/ Z' q& S( l5 n
6 L& d) o' c  v' O7 S# _$ {: v5 r2 V
编译上述程序后下载。
04
------------第四节效果演示----------

- k- o4 T$ |: R! H$ z
使用串口观察写入的数据和读出的数据是否一致?
2.4.png

, ?5 Q3 P. ?9 \3 J2 Z# q; A, e5 R' E* B: g. `
可以看到I2C操作EEPROM进行读写都是正常的。
文章出处: 小鸟的早晨
4 y9 o& y. O3 M9 f: y: }* Z$ P

' p& K9 D# K& L  s/ e
收藏 1 评论0 发布时间:2021-1-6 10:19

举报

0个回答

所属标签

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版