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

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

[复制链接]
STMCU小助手 发布时间:2021-1-6 10:19
STM32CubeMx入门教程(7) I2C的读写应用

$ d4 r3 p3 R: x8 Z" P8 U( n2 B+ X
导语“本次 教程使用CubeMx配置I2C进行I2C总线设备的数据读写操作,使用EEPROM作为实验对象”
01
------------第一节 系统要求----------

3 b( k# ]# ]: v- L5 O) u" U/ v
•硬件
野火指南者开发板

# C. B. L4 ?4 n  i) E9 O! e
•软件
6 L" Y1 z, v- a1 \3 `
CubeMx & MDK & 串口调试助手

1 ]  Q- r' T+ a% j# I
•原理图
2.1.png
( {0 R( g, b- H7 ?

/ i1 `8 i$ ^* S4 g8 f
  E) T0 o3 G2 \# N1 Y' F6 C: D. S9 W4 X" c+ Z

9 m, C8 C8 N/ ~9 J/ d
我们可以从原理图中得到使用的I2C1,AT24C02的设备地址的第三位是000,容量是256个字节。设备地址从下图得到:
2.2.png
$ |( o- U. H; p; }# U7 A/ F& h$ y7 k0 l
0 @7 {$ P0 r0 ?* n- H

( a* p& `0 C4 M0 ?4 a0 S
/ ^  p, C: K6 h# x" d' ]
不带读写方向的使用左移得到的地址为0b10100000->0xA0, 读地址为:0xA1,写地址为0xA0;

% U" \+ |" H. v- W! i
注意:(1) 操作ATC02的时候,多字节写入的时候没写入一个字节,延时最小5ms, 多字节读的时候没有要求,页写入的时候每8个字节为一页,共32页。
" J. p3 |  f4 O% F) e+ X1 `5 ]
02
------------第二节 CubeMx的配置----------

% c. C& ^$ G) Q2 B/ n6 t6 w$ W  W- ~2 Z7 m. r, C9 q
我们依然使用之前的USART的项目,在此基础上进行I2C的配置,串口的使用是进行EEPROM读写数据显示在控制台上,使用CubeMx进行I2C的配置:
2.3.png

# g6 c. F7 j/ C
0 |; I4 S. G8 u
8 l1 X2 n* m: J4 F. R
# }& F0 I) J& H* O9 g
I2C的配置很简单,完成上述配置后生成代码。
: c9 ~5 ~+ k- e& q6 P# l

5 p  M6 D( c$ O$ a4 J6 R. Y0 s3 @/ |
03
------------第三节MDK的代码编写----------
使用MDK打开CubeMx生成的代码进行应用代码编写。
(1)在main.c 中进行AT24C02的相关宏定义和变量定义:

: B1 Y2 M4 q' I. d
  1. #define ADDR_AT24C_Write 0xA0
    2 P9 e" E8 G; M# g. A+ K* w
  2. #define ADDR_AT24C_Read  0xA1
    ! i6 L# T5 N; r% L0 V  ?( u+ A, B
  3. #define DEV_ADDR_ATC02   0xA0 //0x50 左移得到的。  s1 O1 ?5 h! M; b+ @6 G
  4. #define ATC02_BufferSize 256   // 256
    " h5 B5 c! F" _6 _. g+ I
  5. #define I2C_TIMEOUT                0xFF& U) w# A5 W" A; q) u
  6. #define AT_I2C              hi2c1
    3 n, K% w0 l" _2 \5 G5 Y
  7. uint8_t AT24_WriteBuffer[ATC02_BufferSize],AT24_ReadBuffer[ATC02_BufferSize];
复制代码
3 v' [" s& w; F9 X. _( D1 G2 V
0 b& Z. A/ y* d( }
(2) 应用函数申明:
% X# w" [$ N0 d; a) P0 @. O/ L6 \
  1. HAL_StatusTypeDef I2C_Write_Buffer(I2C_HandleTypeDef *hi2c,\
    5 c5 z  T" T3 e$ n$ v& F
  2. uint16_t DevAddress, uint16_t MemAddress,\
    7 m/ H& o5 h$ ]* ]1 C& ]
  3. uint16_t MemAddSize, uint8_t *pData, uint16_t Size,\
    / v1 K0 W8 H/ L" V9 a' ^, R
  4. uint32_t Timeout);
    + ~7 n0 R$ D/ w; C3 s* [: u
  5. HAL_StatusTypeDef I2C_Read_Buffer(I2C_HandleTypeDef *hi2c,\: p. \) e- Q1 `2 }4 x
  6. uint16_t DevAddress, uint16_t MemAddress,\& B# x# J9 f+ J( U; ?; r/ b
  7. uint16_t MemAddSize, uint8_t *pData, uint16_t Size,\
    6 k2 Z3 e( x$ `. Y
  8. uint32_t Timeout);
复制代码

. @. O4 B# n# ?9 v+ j
$ j$ _# E* e! @
I2CWriteBuffer()是自定义的任意字节写入I2C-AT24C02的函数,I2CReadBuffer()是任意字节读写函数。这两个函数的实现采用HAL库的这两个函数:
1)HALStatusTypeDefHALI2CMemWrite(I2CHandleTypeDef *hi2c, uint16t DevAddress, uint16t MemAddress,uint16t MemAddSize, uint8t *pData, uint16t Size, uint32_t Timeout);

$ |* P+ a, f" S& u
参数依次是:(I2C句柄,AT24C02的设备地址,设备中数据地址,数据地址的大小,写的数据,数据大小,超时时间)

& ]/ P- }, n5 M$ Q9 A9 j
2)HALStatusTypeDefHALI2CMemRead(I2CHandleTypeDef *hi2c, uint16t DevAddress, uint16t MemAddress,uint16t MemAddSize, uint8t *pData, uint16t Size, uint32_t Timeout);
$ c. D: m& T  W2 m4 j1 L
参数依次是:(I2C句柄,AT24C02的设备地址,设备中数据地址,数据地址的大小,读出数据,数据大小,超时时间)

) x8 m8 {" A$ S# ~& O4 J( V3 W
为什么不直接使用库函数呢?是因为在测试中AT24C02读写不正常,查看AT24C02的手册发现,单个字节写入没问题,多字节的写入需要每个字节延时5ms, 其实多字节的读没有问题,这个从新实现了下。可以连续8个字节的页写入,这个不需要延时。

/ k- O- O* N1 g2 ?. t
(3)多字节的读写函数:

" J# K5 f" c7 h- Z, ]
  1. /*这里自己实现多字节的ATC02的写操作*/4 S$ i3 b" n% A. p
  2. HAL_StatusTypeDef I2C_Write_Buffer(I2C_HandleTypeDef *hi2c,\
    3 o, n% ]# i$ F8 L3 E
  3. uint16_t DevAddress, uint16_t MemAddress,\
    1 U! h' ]8 Q  U4 c0 u' q
  4. uint16_t MemAddSize, uint8_t *pData, uint16_t Size,\- {5 t; ~8 ^& w) o" j! k; j, Q9 u
  5. uint32_t Timeout)
    - G# E" |9 v9 t7 ?" _4 r/ @: ^
  6. {/ B5 \2 Y. }5 A# e' |" L/ H/ u7 {+ q
  7.        uint16_t count=0;
      ~  b5 h# x# ]0 N
  8.        for(count=0;count& Z$ x  `, K+ V+ y
  9.        {0 B) @) k. f+ m, L. x- i' [
  10.               if(HAL_I2C_Mem_Write(hi2c,DevAddress,MemAddress, MemAddSize,pData,1,Timeout)==HAL_OK)
    9 L- {6 D7 V/ K2 s3 z2 f( z
  11.               {
    - b; ~3 s+ F! @  D
  12.                      MemAddress ++;
      T# P- |( I- G: m
  13.                      pData ++;
    # G: @! w. ^% v
  14.                      HAL_Delay(5);7 V% [; R+ \0 g6 _* u/ [& ~, }% \! U
  15.               }
    ! o3 p7 s4 T- |# w* M# N* N" _: |
  16.               else
    * [9 ^/ O, y3 \$ L8 ?
  17.               {
    # g2 a9 H! T8 ^& X4 n! e; x  k9 [
  18.                      printf("i2c write is error \t\n");# B% s5 V  K- ]
  19.                      return HAL_ERROR;  P, R5 w) |" O4 u8 f" i$ G1 S1 e, T
  20.               }
    " l; D. n; M( I, D# j- }
  21.        }/ f- b6 q+ t  V: T, U% M+ g# q
  22.        return HAL_OK;
    9 B6 v; e- j# y; w
  23. }
    ) x. N1 ]4 ^# B9 c7 ]$ u" u# A5 H
  24. /*这里自己实现多字节的ATC02的读操作*/
    7 x9 |2 j( T+ s# m4 @
  25. HAL_StatusTypeDef I2C_Read_Buffer(I2C_HandleTypeDef *hi2c,\
    ' N5 g7 M* r, y7 p/ X( C$ Z
  26. uint16_t DevAddress, uint16_t MemAddress,\
    * y! x/ r# p+ j2 ~
  27. uint16_t MemAddSize, uint8_t *pData, uint16_t Size,\% Y- r  M% q# \
  28. uint32_t Timeout)
    6 c+ X7 a4 E  Q% J
  29. {3 ]1 [( W  _2 R
  30.        uint16_t count=0;
    0 q2 @# O  ]4 t
  31.        for(count=0;count<Size;count ++)
    2 w* f/ ^# i, V' E( t
  32.        {* ~+ n& Y* m1 J' D2 @. H; ?
  33.               if(HAL_I2C_Mem_Read(hi2c,DevAddress,MemAddress, MemAddSize,pData,1,Timeout)==HAL_OK)3 \% N+ B$ H; j8 R* Y
  34.               {
    - V3 h, X1 Z$ A) N# A& v9 Y
  35.                      MemAddress ++;( K; r. V, B& n( p
  36.                      pData ++;
    7 }+ P: w: {: {6 I- W3 p  ~
  37.                      //HAL_Delay(5);( T) t- ~2 J* U5 q6 F: N
  38.               }
    ! h* K! I# P3 c$ Z) O
  39.               else
    / s# s% y+ L5 A' M7 k( ]2 e" r
  40.               {
    ( u6 u/ v6 u! S% u3 n' ~) _: _' I
  41.                      printf("i2c read is error \n");
    8 h* ~3 P9 q1 @* ]) \% H# u' J
  42.                      return HAL_ERROR;
    3 I5 H, L5 G% E
  43.               }; V% j; l7 P' f. G' \" Q
  44.        }& W% I1 _# N$ K; I, Q& x( \
  45.        return HAL_OK;
    9 |5 [( j# f; C8 i# \2 t  _7 j
  46. }
复制代码

( ^! g5 ~. T5 z7 R8 Z: g0 c3 h
(4)在main函数中添加测试代码:
6 a. q# ?5 g6 w7 {9 U
  1. uint16_t num_atc=0;, w3 J: Z3 S( {. }! t5 c& S8 w7 B% n
  2.        printf("this is test for I2C device read and write in ATC02\r\n");+ V/ G, y1 Z0 ^. N  |
  3.        printf("/**--------------------开始I2C-------------------------**/\r\n");2 B. f0 [3 q1 Y( Y
  4.        for( num_atc=0;num_atc) D; N# S/ c& }, b4 N9 v1 x
  5.        {
    4 J1 [! Z1 U2 s9 a5 J# Q; V
  6.               AT24_WriteBuffer[num_atc]=num_atc;3 X4 h$ g% K& N6 t3 _! x
  7.               printf("0x%x\t",AT24_WriteBuffer[num_atc]);       $ e1 p/ K! Z6 g6 z
  8.        }6 ~4 C7 x) j* c: n; A) _8 z
  9.        if(I2C_Write_Buffer(&AT_I2C,DEV_ADDR_ATC02, 0, I2C_MEMADD_SIZE_8BIT,AT24_WriteBuffer,ATC02_BufferSize, I2C_TIMEOUT) == HAL_OK)/ S+ S. y* V, S* ~) [
  10.        {& Z4 _* F5 i: A/ m' o0 q
  11.               printf("write i2c lots bytes is ok\t\n");
    : ^. L' ]2 M' ?7 S2 ?
  12.        }5 b- S/ J; h1 J8 ]' E- Y7 g) f
  13.        if(HAL_I2C_Mem_Read(&AT_I2C,DEV_ADDR_ATC02, 0, I2C_MEMADD_SIZE_8BIT,AT24_ReadBuffer,ATC02_BufferSize,I2C_TIMEOUT)== HAL_OK)
    , r* V2 t# L! D/ ]
  14.        {
    % w* s( U/ z/ R4 x  Q) ]
  15.               printf("\r\n EEPROM 24C02 read data Test OK \r\n");
    $ @* g  n# s3 s8 y/ E. z* S
  16.        }
    $ k5 H5 T- I6 A
  17.        else
    ( K/ M0 P  `5 m; d
  18.        {: V+ c" G( @) ^+ G3 p5 x5 d1 X
  19.               printf("\r\n EEPROM 24C02 read data Test False \r\n");
    3 [* V) i  _+ Y* {
  20.        }( Y8 z2 e9 I+ ?$ s8 q5 M
  21. /*这里使用自定义多字节读函数也是正常的*/( M6 S, l& Q8 d1 a  _
  22. /*
    2 Y1 c, L8 ?, W9 w% J* c- Q4 P
  23.        if(I2C_Read_Buffer(&AT_I2C,DEV_ADDR_ATC02, 0,               I2C_MEMADD_SIZE_8BIT,AT24_ReadBuffer,ATC02_BufferSize,I2C_TIMEOUT)== HAL_OK)
    & v/ w( {& ?. P7 M, v0 N  |: a
  24.        {) @/ m0 M3 _1 A9 Z! }
  25.               printf("i2c read lots is ok\t\n");# h) k# c1 `! Z! K7 M) A
  26.        }, V+ r) r* R1 K% }7 g6 N
  27. */) z; f( D' ?, H- d& T
  28.        for(num_atc=0; num_atc<ATC02_BufferSize; num_atc++)
    3 O% l0 g) V% y+ p3 Y# H8 M4 C. T5 g
  29.        {
    & n+ `; I9 T3 D8 C; X  S7 ~
  30.               printf("0x%x\t",AT24_ReadBuffer[num_atc]);/ ~3 I. U8 z9 N  c1 Z0 o' Y* W
  31.        }( ~8 H: X* i4 _% O( Y0 D
  32.        if(memcmp(AT24_WriteBuffer,AT24_ReadBuffer,ATC02_BufferSize) == 0 ) /* check date */
    % }1 V( F! R% s5 z# ~
  33.        {0 Z; d1 H1 y$ [& \- |8 B
  34.               printf("\r\n EEPROM 24C02 Read and write Test OK\r\n");0 y0 q- a: ]& N7 C: I
  35.        }+ C4 a6 ^9 t& @% @' [* ]* |2 R3 l2 Z
  36.        else; r) F% P8 w) s9 r) }2 Y: F
  37.        {  c  ?( O) H' v& I7 B) J
  38.     printf("\r\n EEPROM 24C02 Read and write Test False\r\n");' v, @. I" w4 O$ f/ e9 T/ G
  39.        }      
    / g4 M: U1 Z' w! J8 y7 G
  40.        printf("/**--------------------结束I2C-----------------**/\r\n");
复制代码
1 @" j/ T- F2 E* d+ _  O. p
: ^* ^& {& v) e, }( ^- ~" E8 @0 q
编译上述程序后下载。
04
------------第四节效果演示----------

! y: i0 ~% k& j$ y
使用串口观察写入的数据和读出的数据是否一致?
2.4.png

5 N' e8 c; x; N+ {
& m/ T1 o2 O, j' Y
可以看到I2C操作EEPROM进行读写都是正常的。
文章出处: 小鸟的早晨

4 Y7 r7 v9 i. i2 X9 K; p7 e! {( p, y9 Q3 w3 T
赞 收藏 1 评论0 发布时间:2021-1-6 10:19

举报

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