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

基于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限制

5 _- Y2 L7 o9 R5 s  \
微信图片_20230701190856.png
$ u: D0 c# x6 O# y: s
⏩ I2C协议层:I2C总线在传送数据的过程中共有三种类型信号,在这些信号中,起始信号是必需的,结束和应答信号可以不要;I2C总线寻址按照从机地址可分为7位和10位(寻址字节)寻址两种,D7~D1位组成从机的地址,D0位是数据传送方向(0表示主机向从机写数据/1表示主机由从机读数据)
    " S; Z3 m2 y  c5 F. q: r  @7 {5 n
    - s0 f! ^( G" }8 L4 Q' \2 `/ l# t
  • 开始信号:SCL为高电平时,SDA由高电平向低电平跳变,开始传送数据
  • 结束信号:SCL为高电平时,SDA由低电平向高电平跳变,结束传送数据

    2 Q% q" `! J6 l
  • 应答信号:接收数据的IC在接收到8位数据后,向发送数据的IC发出特定的低电平脉冲,表示已经收到数据。CPU向受控单元发出一个信号后,等待受控单元发出一个应答信号,CPU接收到应答信号后,根据实际情况作出是否继续传递信号的判断。若为收到应答性,判断为受控单元故障

    9 w0 Y: i+ r+ A9 W6 |& J$ R
    7 X% o8 T& O; `2 Z5 {, M& P- I
微信图片_20230701190853.png
) T+ j1 Y4 z9 v( J
, x. D2 d# H1 `8 V  y4 c
1.2 AT24C02芯片简介
AT24C02是一个2K位串行CMOS,内部含有256个字节,此芯片具有I2C通讯接口,芯片内保存的数据在掉电的情况下不丢失(EEPROM),常用于存放比较重要的数据。本实验使用的是SOP-8封装的AT24C02芯片,其引脚说明见下图
+ A( |7 {# |6 F1 C/ t1 @
微信图片_20230701190849.png
1 |9 v' [" w; n9 s$ I
AT24C02芯片的器件地址为7位,高4位固定为1010,低3位有上表中的A0/A1/A2引脚的电平决定,还有一位(最低位R/W)用来选择读写方向。本实验中A0/A1/A2引脚接在GND上了,因此器件地址为1010000;加上最低位的读写方向位后,写器件地址为10100000(0xA0),读器件地址为10100001(0xA1)

$ ?! T- V, @) C; Q7 T9 I: y8 h
微信图片_20230701190846.png

6 b! J- Z1 `7 C3 `. C& h# V$ z2 y; |" P6 ]! j2 c, X9 s
下图为AT24C02的总线时序图和时间参数

. g' N* z( J" z
微信图片_20230701190842.png
# o- v  Z" n( X% p
微信图片_20230701190839.png

3 S) T, I1 Z3 u

6 E) X- b) [/ f2 G! K
2.硬件设计
D1指示灯用来提示系统运行状态,K_UP按键用来控制24C02的数据写入,K_DOWN按键用来控制24C02的数据读取,数据的写入与读取信息通过串口1打印出来

    5 v% @- i5 A; A3 k
    # V" O) o+ z- p- d4 L
  • 指示灯D1
  • USART1串口
  • AT24C02

    # ?, w! x% n( D8 I
  • K_UP和K_DOWN按键* l$ q+ \; @2 \% P, ]8 n

    - W5 i2 g0 F7 _
    " F4 e  x+ l" q1 H) q# ]. n
微信图片_20230701190835.png
1 x$ Q; _% d2 E4 [9 b  C
( O0 F, I6 X  V2 A4 u9 _; A6 x9 f5 b0 \
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,生成工程代码
6 h$ S- O" Q' |! b" u
微信图片_20230701190831.png
$ _2 m9 |# G) y+ u$ \( |4 d1 u5 w% S
3.2 MDK-ARM软件编程
➡️ 在i2c.c文件下可以看到I2C初始化函数
  1. void MX_I2C2_Init(void){* a" I% E8 n4 A1 @, X
  2.   hi2c2.Instance = I2C2;
    - W9 E+ o; ^- m2 L0 N; N  ]
  3.   hi2c2.Init.ClockSpeed = 100000;  R0 u+ C- T3 B) R- d6 L- G
  4.   hi2c2.Init.DutyCycle = I2C_DUTYCYCLE_2;
      ?$ O! b8 ~8 p
  5.   hi2c2.Init.OwnAddress1 = 0;1 b+ L: w% k6 k. `, l$ s) |$ k
  6.   hi2c2.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
    . n: t4 X, @& p0 N$ A* c: E
  7.   hi2c2.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
    0 A/ }: }2 G4 C( C2 A: l; h2 X8 [% ^4 R
  8.   hi2c2.Init.OwnAddress2 = 0;
    2 X3 Q0 _) r  V2 v6 A
  9.   hi2c2.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;, J* o' z, q0 T# j( S
  10.   hi2c2.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;: O/ Z7 E6 `, W4 ~* u  {% q
  11.   if (HAL_I2C_Init(&hi2c2) != HAL_OK){) G/ L/ J4 T! t+ Z6 Y; x& c
  12.     Error_Handler();6 c) X# V, W' @# M. Z
  13.   }
    $ P5 V- o. l6 k! A
  14. }
    * g/ U' J& X4 n/ @( N* o

  15. - F  I5 q; I! I% E& j1 P2 c3 Z* ~8 N
  16. void HAL_I2C_MspInit(I2C_HandleTypeDef* i2cHandle){
    ( |" L4 y1 F+ l" \4 ]$ z0 W
  17.   GPIO_InitTypeDef GPIO_InitStruct = {0};
    # R* _5 F" w- L# U6 v9 Y6 G% x- Y
  18.   if(i2cHandle->Instance==I2C2){
    5 d/ g) [. i) E1 m/ L6 d
  19.     __HAL_RCC_GPIOB_CLK_ENABLE();
    ) v, g( |" \& B( X. X- W/ r
  20.     /**I2C2 GPIO Configuration   
    . L+ r  ?7 s, M! Y  C) K
  21.     PB10     ------> I2C2_SCL8 D" u6 _/ h: n9 ?6 M
  22.     PB11     ------> I2C2_SDA*/  |$ ~; r+ U, K$ y  M9 c
  23.     GPIO_InitStruct.Pin = GPIO_PIN_10|GPIO_PIN_11;1 o. z& d) I: L# v# @+ Z4 Z& P
  24.     GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;4 Q8 R4 R* y& B  @2 @2 d! p
  25.     GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;2 `+ W) W' O6 \0 Y
  26.     HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
    5 b) H2 A' K% [+ ^3 ~
  27.     /* I2C2 clock enable */
    . y- V+ o& w5 E" ]) V; M. p9 j
  28.     /*网上看到很多资料说此处的I2C时钟初始化函数应该放在GPIO/ o$ X$ ]- n2 C3 w# Q: y
  29.       初始化之前,但是这里没有调整也能够正常读写EEPROM*/
    ) A! g9 ?2 b* q# e9 n0 Z
  30.     __HAL_RCC_I2C2_CLK_ENABLE();        2 M6 O; v# _( J9 ?
  31.   }
复制代码
➡️ 创建按键驱动文件key.c 和相关头文件key.h,参考[color=var(--weui-LINK)]按键输入例程
➡️ 创建AT24C02驱动文件24cxx.c和24cxx.h
  1. #define ADDR_24CXX_WRITE 0XA0
    ! z- ^# V5 D- M" X# v& s7 Y
  2. #define ADDR_24CXX_READ  0XA1( c( ]9 y- ]. x7 L, r
  3. void AT24CXX_Init(void){
    / U! x9 M3 G1 \8 L- U  Z
  4.   MX_I2C2_Init();       
    & @9 [% C4 E4 {: m' [1 A; K( C
  5.   while(AT24CXX_Check()){- s* Q7 ^2 r+ o" `) @( Z
  6.     printf("AT24C02 Checked Failed!\r\n");6 Q0 M# O, O: r6 L$ d8 `7 j% w
  7.     HAL_Delay(500);
    5 J0 ?8 E; G- C6 {) }
  8.   }, _) P# e8 O- V  U5 U
  9.   printf("AT24C02 Checked Sucessed!\r\n");
    ( v- o( o! L1 o3 B- l3 H( a' A
  10. }6 [* @* a" z# M1 Q6 X) }: f! c
  11. * {9 B) B5 p9 g3 N0 s
  12. uint8_t AT24CXX_Check(void){6 \" y3 A( e9 l5 ?# `  W3 R9 ]
  13.   uint8_t temp;: F  o0 }  A# O' y; [. s6 o1 ]
  14.   HAL_I2C_Mem_Read(&hi2c2,ADDR_24CXX_READ,255,I2C_MEMADD_SIZE_8BIT,&temp,1,0xff);                                  
    : C8 y2 Y+ |7 @8 F/ G$ T
  15.   if(temp==0x36)       
    ' \1 |1 o+ I4 A2 T4 {! F
  16.     return 0;                   , A! D9 s/ M7 D& ?
  17.   else{
    3 U/ b8 \# M8 ~9 r4 j
  18.     uint8_t data = 0x36;1 h* S) f* K$ ^! f; y, O; \
  19.     HAL_I2C_Mem_Write(&hi2c2,ADDR_24CXX_WRITE,255,I2C_MEMADD_SIZE_8BIT,&data,1,0xff);
    3 J$ i/ N# X2 N: ~( Q; d& n/ o: @
  20.     HAL_I2C_Mem_Read(&hi2c2,ADDR_24CXX_READ,255,I2C_MEMADD_SIZE_8BIT,&temp,1,0xff);          . f0 x' s- A- y
  21.     if(temp==0x36)        * t0 M( ^' m: O- b8 i: p% I6 E
  22.       return 0;4 E* c8 |  o! |9 N
  23.   }  g1 y. L! ~: T, R8 H7 k
  24.   return 1;                                                                                          
    ' v  Z, l2 M, J2 f) m$ {
  25. }
复制代码

4 D5 U* }* |+ X- G5 k7 i
➡️ 在main.c文件下编写I2C测试代码

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

  1. /* USER CODE BEGIN PV */; l. Z# j$ w0 e9 D0 k* Y% ?* A
  2. #define ADDR_24CXX_WRITE 0XA0# [8 m: s6 g- Q: h
  3. #define ADDR_24CXX_READ  0XA1$ C' f# p3 M8 v5 b8 N
  4. uint8_t WriteBuf[256];1 p3 R; z& w( i
  5. uint8_t ReadBuf[256];
    " M2 F# `( k7 V% J! S1 J. h2 g
  6. uint16_t i,j;
    * W! ~- Y3 j" X) v9 e
  7. /* USER CODE END PV */! x( Q9 B1 S. V4 {! R
  8. int main(void){8 F8 H7 B& A: L. q
  9.   uint8_t key;
    4 F: d% y4 [* X9 x" F
  10.   HAL_Init();; u9 j! @. o1 O; E1 E* M; c+ h. |6 v
  11.   SystemClock_Config();
    7 g' n$ C* \/ Z% Q7 `
  12.   MX_GPIO_Init();! b& `( Y8 z( P! n% C: q
  13.   MX_I2C2_Init();3 E, L" T7 G1 x$ H2 Y# }) x) o& E0 h. ?. A
  14.   MX_USART1_UART_Init();
    , L( y6 j7 E2 u/ R7 G$ ]- s1 s
  15.   /* USER CODE BEGIN 2 */
    # `# s/ m& `* K
  16.   AT24CXX_Init(void);/ K" j& E' p' g5 J
  17.   printf("\r\n*********STM32CubeMX I2C AT24C02 Example*********\r\n");
    $ C9 Z& S; k( q/ z5 Q$ C5 }7 E
  18.   for(i = 0;i < 256; i++){         //初始化写数据缓冲区
    ( {* }8 r5 Z8 w! y/ P
  19.     WriteBuf[i] = i;, U5 ^3 b8 p* m8 |
  20.   }0 Z/ I# {" A3 a! H) I1 q4 u: c" L
  21.   /* USER CODE END 2 */- A) S( r/ t5 e  x* t
  22.   while (1){
    4 t& W& U9 K! s7 H) y, N
  23.     key = KEY_Scan(0);
    7 @( R- x+ _, G4 Q
  24.     if(key == KEY_UP_PRES){
    4 y6 ^4 |# `# x: t8 [3 s# t; }; O* k+ B
  25.       for(j = 0;j < 32;j++){        //按页写入EEPROM,分32次写入
    9 d3 {4 o0 q3 |0 h
  26.         if(HAL_I2C_Mem_Write(&hi2c2,ADDR_24CXX_WRITE,8*j,I2C_MEMADD_SIZE_8BIT,WriteBuf+8*j,8,0xFF) == HAL_OK){
    # F* v! P- i( w7 H1 r4 M5 d& |: z: g
  27.           printf("\r\nEEPROM 24C02 Write Test OK!\r\n");
    ! t4 [  `$ T2 s& l' [
  28.           HAL_Delay(5);) @1 ]$ {3 W& @+ d- m3 j2 y
  29.         }
    ; |/ C/ w* B; [1 V$ X2 V0 A' H4 z
  30.         else{$ @2 e8 W+ N2 T  b. x
  31.           printf("\r\nEEPROM 24C02 Write Test False!\r\n");: ~; Z+ ~0 g& Q% o6 j% [
  32.           HAL_Delay(5);                                       
    + J4 l+ D! S3 \1 C
  33.         }7 {2 l2 b4 ^( m1 V
  34.       }
    % r* _3 X% d7 V" n6 z8 Y
  35.     }, O+ P$ q2 O9 _& m- S2 _$ \6 X: i
  36.     //EEPROM读取没有页限制,可以一次读取256个字节        1 H5 G& U5 I, g" X" D: P! @" l
  37.     if(key == KEY_DOWN_PRES){        , F, V3 K+ h3 f% g
  38.       HAL_I2C_Mem_Read(&hi2c2,ADDR_24CXX_READ,0,I2C_MEMADD_SIZE_8BIT,ReadBuf,256,0xFF);6 c. E9 _$ a% o- z  \+ Z; o
  39.       for(i=0;i<256;i++){  Q; A& {3 o0 }( R, f0 t" d& f! C
  40.         printf("0x%02X ",ReadBuf[i]);
    & t/ Q/ f1 C4 {9 d: u# P9 P$ r% j
  41.       }& J7 ], }6 D/ e. l6 ?
  42.       //通过内存比较,判断读取和写入的数据是否相同          u! k1 \6 Z- K9 K5 C  l
  43.       if(memcmp(WriteBuf,ReadBuf,256) == 0){       
    4 Z- S/ a" ^& z4 D- F' T
  44.         printf("\r\nEEPROM 24C02 Read Test OK!\r\n");2 o+ J' N: D# P2 W8 U" D
  45.       }1 u/ p6 B3 f. ~+ ^
  46.       else{! {6 r  {9 O( H, p3 [$ e
  47.         printf("\r\nEEPROM 24C02 Read Test False!\r\n");
    % m! \8 f( ]. j, f  H  ?9 h
  48.       }8 {  f. I7 j, E: j  h
  49.     }- J2 G* k' A* _. s" K: R/ A+ z
  50.         ) {2 h: O  H1 Q1 {, i' C$ F8 i+ O
  51.     HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_0);
    0 A' g5 E* [/ ~8 a: M+ h: C
  52.     HAL_Delay(500);# T/ e6 l7 @" p3 r! a0 d5 t9 n0 U
  53.   }! `$ \/ i& h1 P0 @0 x' \
  54. }
复制代码

, Q$ N  v  X# V+ G2 l" w5 c
4.下载验证
编译无误下载到开发板后,可以看到D1指示灯不断闪烁,当按下K_UP按键后数据写入到24C02芯片内,当按下K_DOWN按键后读取24C02芯片的值,同时串口打印出相应信息
: E, I, P# z! B2 w( P8 x( Y
微信图片_20230701190826.png
1 \% p# S! M0 h2 H

/ C8 [# Z  Q/ O+ q2 P
转载自:嵌入式攻城狮

* ?3 n$ ~) g' Q- }$ R
' G/ G" B  @- G8 D/ j3 I
如有侵权请联系删除
  i$ z' j" x. g0 V
' f8 P2 ~8 B1 ]0 C: c
8 K4 r) m. `, e2 o8 G; x# t" L
赞 收藏 评论0 发布时间:2023-7-1 19:09

举报

0个回答

所属标签

相似技术帖

官网相关资源

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