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

基于STM32CubeMX的I2C总线经验分享

[复制链接]
攻城狮Melo 发布时间:2023-7-1 19:09
1.I2C总线及AT24C02芯片
1.1 I2C总线简介
I2C(Inter-Integrated Circuit)总线是由PHILIPS公司开发的两线式串行总线,用于连接微控制器及其外围设备。是由数据线SDA和时钟线SCL构成的串行总线,可发送和接收数据。在CPU与被控IC之间、IC与IC之间进行双向传送,高速I2C总线一般可达400kbps以上。下面从物理层和协议层两方面来了解I2C:
I2C物理层:可连接多个I2C通讯设备,支持多个通讯主机和从机;每个连接到总线的设备都有一个独立的地址,主机利用这个地址进行不同设备之间的访问;总线通过上拉电阻接到电源,当I2C设备空闲时会输出高阻态;多主机同时使用总线时,利用仲裁方式觉得由哪个设备占用总线;有三种传输模式,标准模式(100kbit/s)、快速模式(400kbit/s)、高速模式(3.4Mbit/s 多数I2C设备不支持);连接到相同总线的I2C数量受最大电容400pF限制

; E. Z) C1 a" u" d: `
微信图片_20230701190856.png

3 ?4 Y& x( t2 ~0 \" a
I2C协议层:I2C总线在传送数据的过程中共有三种类型信号,在这些信号中,起始信号是必需的,结束和应答信号可以不要;I2C总线寻址按照从机地址可分为7位和10位(寻址字节)寻址两种,D7~D1位组成从机的地址,D0位是数据传送方向(0表示主机向从机写数据/1表示主机由从机读数据)

      }0 N; I" ~  G9 K/ f# V$ \
    ' S  n  G: ]* i0 H
  • 开始信号:SCL为高电平时,SDA由高电平向低电平跳变,开始传送数据
  • 结束信号:SCL为高电平时,SDA由低电平向高电平跳变,结束传送数据
    & g) E# V6 ~; _( A* L& t# f
  • 应答信号:接收数据的IC在接收到8位数据后,向发送数据的IC发出特定的低电平脉冲,表示已经收到数据。CPU向受控单元发出一个信号后,等待受控单元发出一个应答信号,CPU接收到应答信号后,根据实际情况作出是否继续传递信号的判断。若为收到应答性,判断为受控单元故障
    : Z& A# i$ f1 V& `4 p, E/ I. F5 J
    * p0 c$ V5 b) P+ w  N+ D% u
微信图片_20230701190853.png
) F: L% u7 I3 i7 h: `8 B/ O" I

' Z# t8 {0 ]' [$ I: z2 q, d  r
1.2 AT24C02芯片简介
AT24C02是一个2K位串行CMOS,内部含有256个字节,此芯片具有I2C通讯接口,芯片内保存的数据在掉电的情况下不丢失(EEPROM),常用于存放比较重要的数据。本实验使用的是SOP-8封装的AT24C02芯片,其引脚说明见下图

$ F/ y6 G4 A4 V- D+ I$ u
微信图片_20230701190849.png
% S/ G/ J7 ]* d6 ~8 N- s; w
AT24C02芯片的器件地址为7位,高4位固定为1010,低3位有上表中的A0/A1/A2引脚的电平决定,还有一位(最低位R/W)用来选择读写方向。本实验中A0/A1/A2引脚接在GND上了,因此器件地址为1010000;加上最低位的读写方向位后,写器件地址为10100000(0xA0),读器件地址为10100001(0xA1)
- @: X, q2 `2 @. s2 L! }9 H( n
微信图片_20230701190846.png

4 o# J& R. \6 f7 c& ?2 W3 H1 F8 A" T, j
下图为AT24C02的总线时序图和时间参数

0 L6 C. J( e* U" f% Q! S
微信图片_20230701190842.png

8 g; K; d; ~8 \' \  _7 |( e
微信图片_20230701190839.png

/ ]& ^/ Z- H1 P4 k2 X' `7 X5 C9 I8 ?. I
" W/ L' z. U+ P- M; J
2.硬件设计
D1指示灯用来提示系统运行状态,K_UP按键用来控制24C02的数据写入,K_DOWN按键用来控制24C02的数据读取,数据的写入与读取信息通过串口1打印出来
    * b4 S: b  ~/ v" A  y7 U) i9 X

    $ g( A% w5 d' f/ o4 U$ c
  • 指示灯D1
  • USART1串口
  • AT24C02

    & n* A3 D+ U, A" Y0 w/ H
  • K_UP和K_DOWN按键
    + v# B- W0 D/ j  S( {

    , Z3 b+ y0 A/ _/ r
    6 ~1 L0 s+ d5 [$ o2 ~
微信图片_20230701190835.png
) B- F2 ~0 w; k, A6 p9 e+ B
. j* |% H+ e3 g/ T6 H
3.软件设计
3.1 STM32CubeMX设置
➡️ RCC设置外接HSE,时钟设置为72M
➡️ PC0设置为GPIO推挽输出模式、上拉、高速、默认输出电平为高电平
➡️ USART1选择为异步通讯方式,波特率设置为115200Bits/s,传输数据长度为8Bit,无奇偶校验,1位停止位
➡️ PA0设置为GPIO输入模式、下拉模式;PE3设置为GPIO输入模式、上拉模式
➡️ 激活I2C2,选择标准传输模式,选择7位寻址地址,其余默认设置
➡️输入工程名,选择路径(不要有中文),选择MDK-ARM V5;勾选Generated periphera initialization as a pair of ‘.c/.h’ files per IP ;点击GENERATE CODE,生成工程代码

' b$ c& h# I1 g! L+ u# P9 u& A8 [
微信图片_20230701190831.png
3 H; b+ T( b; }7 A$ _
3.2 MDK-ARM软件编程
➡️ 在i2c.c文件下可以看到I2C初始化函数
  1. void MX_I2C2_Init(void){' B* z9 a- U3 o# Z5 g) z9 V4 R7 j
  2.   hi2c2.Instance = I2C2;
    . G% E- g+ {" A: I2 k, F+ }
  3.   hi2c2.Init.ClockSpeed = 100000;9 j! G; u  U/ ~: ~
  4.   hi2c2.Init.DutyCycle = I2C_DUTYCYCLE_2;0 I) [; n! m% I2 c9 a) L
  5.   hi2c2.Init.OwnAddress1 = 0;7 _7 T6 Q7 v  ]& A' q* s. Y
  6.   hi2c2.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;" h8 P* k. `" r2 |
  7.   hi2c2.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
    / {* w" f0 E( J) L* v6 U2 \& A7 p5 ]
  8.   hi2c2.Init.OwnAddress2 = 0;( J2 \2 l/ c  }! Q
  9.   hi2c2.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;0 }! H( e; @/ b, D* u" E  X
  10.   hi2c2.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
    # K5 U4 }$ _9 \1 G$ X& Q
  11.   if (HAL_I2C_Init(&hi2c2) != HAL_OK){) `, a1 X$ \4 O3 M6 Y/ g& c. l! I; W* |
  12.     Error_Handler();
    6 \+ j- @9 P& \" ?) }
  13.   }
      ^% x' D7 ]( M8 E, u3 t
  14. }  n6 G- |0 H+ |: q
  15. % i, x! N: M0 L
  16. void HAL_I2C_MspInit(I2C_HandleTypeDef* i2cHandle){
    $ k' _/ s7 U9 s0 r' g
  17.   GPIO_InitTypeDef GPIO_InitStruct = {0};
    ; G' X: `# ^8 h( w3 _: q, G
  18.   if(i2cHandle->Instance==I2C2){$ h* E6 P. e" C
  19.     __HAL_RCC_GPIOB_CLK_ENABLE();
    * ?0 B  ]+ u/ J7 h/ g$ J5 T7 s7 o; ?/ H
  20.     /**I2C2 GPIO Configuration    # D& c) ^0 e' Q& L2 P/ p
  21.     PB10     ------> I2C2_SCL0 w; m" x- [) ^& E/ J4 M, K! n
  22.     PB11     ------> I2C2_SDA*/3 Q+ h' N' h; Y  }# V
  23.     GPIO_InitStruct.Pin = GPIO_PIN_10|GPIO_PIN_11;4 g: B6 ^( [0 V" h  d1 Q
  24.     GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;9 J6 N6 O  ]$ \' ~  X
  25.     GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    ( A6 e- J  F- b8 r) A7 H
  26.     HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);; v- Y. t- |7 }. y7 d# I8 M8 R
  27.     /* I2C2 clock enable */, H0 m% D, J7 s4 M/ S: c; D
  28.     /*网上看到很多资料说此处的I2C时钟初始化函数应该放在GPIO
    # ^# f8 A5 Q  L- k: A$ o. Q2 ?
  29.       初始化之前,但是这里没有调整也能够正常读写EEPROM*/+ _1 G# @! a- e9 D0 p1 B
  30.     __HAL_RCC_I2C2_CLK_ENABLE();        : l' n8 Y) }! W' [8 o# N
  31.   }
复制代码
➡️ 创建按键驱动文件key.c 和相关头文件key.h,参考[color=var(--weui-LINK)]按键输入例程
➡️ 创建AT24C02驱动文件24cxx.c和24cxx.h
  1. #define ADDR_24CXX_WRITE 0XA0
    7 {0 D* g5 {6 r# m2 X
  2. #define ADDR_24CXX_READ  0XA1# }, C# d) ]8 s
  3. void AT24CXX_Init(void){8 ]9 G( \$ \* j
  4.   MX_I2C2_Init();        . H% S, Y# A0 f% M$ k/ H0 z
  5.   while(AT24CXX_Check()){, F+ J- i% Z1 {$ L/ q
  6.     printf("AT24C02 Checked Failed!\r\n");
    " d6 H; L2 j, d% O% k; [+ |9 A
  7.     HAL_Delay(500);" L/ [4 g# u* R7 |* u: p; P1 f
  8.   }
    8 z7 S  b) U" L' p. I
  9.   printf("AT24C02 Checked Sucessed!\r\n");  c. `" I. \* @$ m, E
  10. }3 y1 M1 \. J; k& C$ A/ h9 m# ^3 s
  11. ' o4 Z% f  T; W: S& U2 Y* X* ^
  12. uint8_t AT24CXX_Check(void){
    : M; K0 H* W5 B% R
  13.   uint8_t temp;: B0 U/ u2 R- ]7 x
  14.   HAL_I2C_Mem_Read(&hi2c2,ADDR_24CXX_READ,255,I2C_MEMADD_SIZE_8BIT,&temp,1,0xff);                                  
    . q4 C; G& `/ h( S* A+ b
  15.   if(temp==0x36)        : N7 Z& e4 m3 [6 f( ]4 ]
  16.     return 0;                  
    / z. x0 Y: u9 m: o- v
  17.   else{$ s: N7 i% V+ I+ f: e! I1 `
  18.     uint8_t data = 0x36;
    * w# d- E2 c& |& E
  19.     HAL_I2C_Mem_Write(&hi2c2,ADDR_24CXX_WRITE,255,I2C_MEMADD_SIZE_8BIT,&data,1,0xff);5 z/ M$ m/ E& E4 k
  20.     HAL_I2C_Mem_Read(&hi2c2,ADDR_24CXX_READ,255,I2C_MEMADD_SIZE_8BIT,&temp,1,0xff);          
    6 f6 Z  @( p7 b, u' _
  21.     if(temp==0x36)       
    6 q. e1 ~( w. Z
  22.       return 0;
    # M; ?( `  C/ N/ h3 \' O
  23.   }
    - w3 i, ?9 f; z3 ^* A
  24.   return 1;                                                                                          3 ^0 z8 w3 o& {0 \  p
  25. }
复制代码

) M9 l+ {6 K8 Q( P/ I
➡️ 在main.c文件下编写I2C测试代码

AT24C02的2Kbit分为32页,每页8个字节。而EEPROM也可以按页写入,本例使用了按页写入的方式,分32次写入。注意每次写入完毕需要延时5ms,是AT24C02芯片的要求;读取数据没有页的限制,可以一次全部读取256个字节

  1. /* USER CODE BEGIN PV */
    % [3 z! R# q. e( w0 [) y: ?- [0 l
  2. #define ADDR_24CXX_WRITE 0XA0
    3 F( H1 A, n: R$ f. T
  3. #define ADDR_24CXX_READ  0XA1
    5 ^& t( e$ y3 Z. g. a9 r
  4. uint8_t WriteBuf[256];
    # r$ e6 w9 i. O6 ?/ v
  5. uint8_t ReadBuf[256];5 [1 V6 s5 \5 g+ x& ^" V
  6. uint16_t i,j;) ]) a' a' X3 I0 i2 |
  7. /* USER CODE END PV */! g# [5 o- z9 X. V# A. r  k
  8. int main(void){
    ; a" t9 M& q7 ]7 d8 T
  9.   uint8_t key;
    ; r' p# _% G. S( I" D* J5 B  {% ]3 X
  10.   HAL_Init();
    % q8 g% t8 X6 Z, t& s- O/ W
  11.   SystemClock_Config();6 H. l; X6 m% u7 E/ v
  12.   MX_GPIO_Init();9 C; M2 q1 l: Z; A: D: l
  13.   MX_I2C2_Init();% O, P& ^+ J- s
  14.   MX_USART1_UART_Init();
    & f$ D5 j1 f7 L* M; |
  15.   /* USER CODE BEGIN 2 */5 h: Q/ D" @/ U" s) j% h" p5 g- H
  16.   AT24CXX_Init(void);1 x  @: c3 @. V0 {
  17.   printf("\r\n*********STM32CubeMX I2C AT24C02 Example*********\r\n");! m2 N, R- i: ?: B! y5 G7 T
  18.   for(i = 0;i < 256; i++){         //初始化写数据缓冲区
    4 }4 Q3 Q5 B7 l5 e5 N
  19.     WriteBuf[i] = i;
    ( j  q  X. J4 h$ f  \1 L
  20.   }' e9 a- k& H6 i
  21.   /* USER CODE END 2 */9 m7 P8 i) F% O) e$ G2 s( ~
  22.   while (1){. z3 ^9 ^$ g0 H2 @7 P! U
  23.     key = KEY_Scan(0);3 E7 K% _- O8 y* ]7 J8 o/ h
  24.     if(key == KEY_UP_PRES){
    6 q, k2 O8 m% B3 }$ z0 X) ?
  25.       for(j = 0;j < 32;j++){        //按页写入EEPROM,分32次写入- r3 i; J" f3 p$ ^
  26.         if(HAL_I2C_Mem_Write(&hi2c2,ADDR_24CXX_WRITE,8*j,I2C_MEMADD_SIZE_8BIT,WriteBuf+8*j,8,0xFF) == HAL_OK){3 t& }4 X5 V; T/ I; E
  27.           printf("\r\nEEPROM 24C02 Write Test OK!\r\n");1 p2 T8 t5 H% H" C- J
  28.           HAL_Delay(5);# B( K# \0 L+ j5 M. K- @5 D: \! J
  29.         }. Q7 g7 n7 C% S( R& K% p
  30.         else{
    ! f! ~* K- c1 l" Z3 E
  31.           printf("\r\nEEPROM 24C02 Write Test False!\r\n");% P. A1 w  Y5 S/ g% I
  32.           HAL_Delay(5);                                        1 L/ d/ c& z6 u) @* I8 ?) h
  33.         }( C) H+ {0 J& S2 O+ K
  34.       }0 X1 H  c/ L0 j3 k! x) A
  35.     }
    # m/ |+ s/ s$ r4 L) m' n
  36.     //EEPROM读取没有页限制,可以一次读取256个字节       
    # r" K* j- t$ q+ O( @) n
  37.     if(key == KEY_DOWN_PRES){       
    & h  e, X8 d) \% Q6 n/ x
  38.       HAL_I2C_Mem_Read(&hi2c2,ADDR_24CXX_READ,0,I2C_MEMADD_SIZE_8BIT,ReadBuf,256,0xFF);5 F% G8 t5 O0 ^8 _. Y
  39.       for(i=0;i<256;i++){
    ; W+ a, j& [  N6 H+ E/ b. n
  40.         printf("0x%02X ",ReadBuf[i]);
    - R2 o+ d# D- W. t8 X5 p9 U3 u
  41.       }. c5 \. `1 x( T
  42.       //通过内存比较,判断读取和写入的数据是否相同       
    1 q' t+ L- _2 U+ ~9 z
  43.       if(memcmp(WriteBuf,ReadBuf,256) == 0){        / y' t( `$ ~! N0 }
  44.         printf("\r\nEEPROM 24C02 Read Test OK!\r\n");# C& y7 o5 `$ H) t
  45.       }
    , F& C; I& C* c
  46.       else{; H% I! P% K8 z; R" j
  47.         printf("\r\nEEPROM 24C02 Read Test False!\r\n");
    7 d1 s: L* ~9 }
  48.       }
    9 x1 b5 f2 o, L) t
  49.     }
    9 g9 d* K: v6 _+ p
  50.         " c! |  x0 ]6 j+ A  f# z
  51.     HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_0);
    . J: ~$ |% C" T: h" H% B0 Z
  52.     HAL_Delay(500);
    # X; d( B+ Y$ s3 {- R) Q) }7 j7 g$ \
  53.   }5 j- |: A4 Z$ w7 r: B" a/ `
  54. }
复制代码
6 c' d& r' t; B: u' E7 x# }. k. |
4.下载验证
编译无误下载到开发板后,可以看到D1指示灯不断闪烁,当按下K_UP按键后数据写入到24C02芯片内,当按下K_DOWN按键后读取24C02芯片的值,同时串口打印出相应信息
1 Y$ M% H+ T  \" o' Z0 n
微信图片_20230701190826.png

) o7 J9 ~$ ~1 }. U8 n, y5 t: Y; s
, L3 T' a, z/ x9 b! w
转载自:嵌入式攻城狮

2 h1 P# n1 z8 h& y" G; E' Y

2 ]) p) _( }! v
如有侵权请联系删除
3 T. I; \5 |2 B3 F3 f
/ r* \( E9 P, k8 q

5 @- e6 E. ~6 C9 m* {
收藏 评论0 发布时间:2023-7-1 19:09

举报

0个回答

所属标签

相似技术帖

官网相关资源

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