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

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

. B- P/ p. p. e1 O
微信图片_20230701190856.png

, u8 U; T' p) a9 W2 w* P# y$ c8 i
I2C协议层:I2C总线在传送数据的过程中共有三种类型信号,在这些信号中,起始信号是必需的,结束和应答信号可以不要;I2C总线寻址按照从机地址可分为7位和10位(寻址字节)寻址两种,D7~D1位组成从机的地址,D0位是数据传送方向(0表示主机向从机写数据/1表示主机由从机读数据)

    & Q  x! @) Y( m; X( C3 s) h, W+ t2 \/ f3 T& y$ P0 u
  • 开始信号:SCL为高电平时,SDA由高电平向低电平跳变,开始传送数据
  • 结束信号:SCL为高电平时,SDA由低电平向高电平跳变,结束传送数据
    ! a9 ~8 ^  [% s9 G1 v
  • 应答信号:接收数据的IC在接收到8位数据后,向发送数据的IC发出特定的低电平脉冲,表示已经收到数据。CPU向受控单元发出一个信号后,等待受控单元发出一个应答信号,CPU接收到应答信号后,根据实际情况作出是否继续传递信号的判断。若为收到应答性,判断为受控单元故障
    3 r  v, H4 G# W' d! B8 \

      R' f6 m( T. m" t
微信图片_20230701190853.png

" m7 V2 U* C) u- L) l! q6 K
% U' b$ C7 u  ?9 m' R
1.2 AT24C02芯片简介
AT24C02是一个2K位串行CMOS,内部含有256个字节,此芯片具有I2C通讯接口,芯片内保存的数据在掉电的情况下不丢失(EEPROM),常用于存放比较重要的数据。本实验使用的是SOP-8封装的AT24C02芯片,其引脚说明见下图
9 r" j/ e/ o3 `" @, s
微信图片_20230701190849.png

% x4 c4 Z7 Z+ c. G# z
AT24C02芯片的器件地址为7位,高4位固定为1010,低3位有上表中的A0/A1/A2引脚的电平决定,还有一位(最低位R/W)用来选择读写方向。本实验中A0/A1/A2引脚接在GND上了,因此器件地址为1010000;加上最低位的读写方向位后,写器件地址为10100000(0xA0),读器件地址为10100001(0xA1)
4 ]1 G* n1 ]; u2 f& o" S4 ?
微信图片_20230701190846.png
' a$ c8 g/ l- m8 J' L

- J8 e+ g: W2 I9 ?. ^
下图为AT24C02的总线时序图和时间参数
4 k1 I, _2 G' Q% j! [
微信图片_20230701190842.png
" i8 M/ c6 b" F. _0 ]' }
微信图片_20230701190839.png

5 L/ r/ e5 X" D* ]; `1 b
" J3 G( i( x7 T5 E1 @
2.硬件设计
D1指示灯用来提示系统运行状态,K_UP按键用来控制24C02的数据写入,K_DOWN按键用来控制24C02的数据读取,数据的写入与读取信息通过串口1打印出来

    0 z. r5 b' F0 L% D3 j. L2 D3 y+ o5 w2 |$ K
  • 指示灯D1
  • USART1串口
  • AT24C02

    ) f0 z( {1 B, O3 Y
  • K_UP和K_DOWN按键9 h0 U( K  \7 _) c: K# S
    ' n+ F: @8 d2 F$ Z# d& ~

    + ?6 i% C- Y9 o, g: C2 C, C
微信图片_20230701190835.png
5 ?9 n8 h2 ?" k2 r6 x' ~1 S
% {1 L& S) p) a! n1 `- Q
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,生成工程代码

5 P8 i* s' ?# ~, q8 o* K% Q
微信图片_20230701190831.png

" v% n2 h- S0 g
3.2 MDK-ARM软件编程
➡️ 在i2c.c文件下可以看到I2C初始化函数
  1. void MX_I2C2_Init(void){9 A; ~8 v/ D2 `2 I' X
  2.   hi2c2.Instance = I2C2;" W2 Y6 u3 g" }) W- o- _/ b
  3.   hi2c2.Init.ClockSpeed = 100000;% `1 g: X1 K2 m, v+ ]  q. U
  4.   hi2c2.Init.DutyCycle = I2C_DUTYCYCLE_2;
    6 u3 C0 _1 v& Z3 T0 b2 k
  5.   hi2c2.Init.OwnAddress1 = 0;4 D/ e% G1 N% @" \" ~
  6.   hi2c2.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;- U' E: M" |' J. U8 f1 Y
  7.   hi2c2.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
    ( Q5 s6 b& \3 Z. F  U2 T
  8.   hi2c2.Init.OwnAddress2 = 0;
    + U: J5 f' \+ x+ C! r
  9.   hi2c2.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
    $ n. P8 ]$ j7 c% v) G+ O
  10.   hi2c2.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;' c# f) g) {% A; M5 V
  11.   if (HAL_I2C_Init(&hi2c2) != HAL_OK){
    / i( K2 Y2 |6 V3 C" v/ w! ]' O3 k
  12.     Error_Handler();1 d8 U  Q( a; E) U
  13.   }: I/ k3 Y1 q1 _3 N
  14. }6 J! w8 T- I1 A( j3 n. I; P
  15. # O; S" d5 T8 R, j
  16. void HAL_I2C_MspInit(I2C_HandleTypeDef* i2cHandle){& Z% w2 z0 Z) Y
  17.   GPIO_InitTypeDef GPIO_InitStruct = {0};& P' v4 A5 I  u
  18.   if(i2cHandle->Instance==I2C2){9 x9 Q, k' p6 r/ O$ W
  19.     __HAL_RCC_GPIOB_CLK_ENABLE();
    , _! l2 `) O: _6 B% b7 G
  20.     /**I2C2 GPIO Configuration   
    $ `- Y! K2 D5 N) T' B3 ]9 B8 ?) I
  21.     PB10     ------> I2C2_SCL
    - F2 S6 r- u/ J* N
  22.     PB11     ------> I2C2_SDA*/1 b; E' I8 f& N3 K1 m# Y& M
  23.     GPIO_InitStruct.Pin = GPIO_PIN_10|GPIO_PIN_11;
    6 y% R) z9 J( _2 f; {1 p
  24.     GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;* X& i( P/ M: T8 f
  25.     GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;, x" W4 k: n* }
  26.     HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);5 c  q0 \0 b5 p9 ]7 }6 y5 [- W
  27.     /* I2C2 clock enable */
    5 i1 a% T1 z: D# {1 k4 u) z
  28.     /*网上看到很多资料说此处的I2C时钟初始化函数应该放在GPIO
    ! ~$ |3 n2 B! ?# n4 ~
  29.       初始化之前,但是这里没有调整也能够正常读写EEPROM*/
    3 p0 a5 s9 o% r
  30.     __HAL_RCC_I2C2_CLK_ENABLE();        4 V7 n. \0 i2 e7 u* Q4 J
  31.   }
复制代码
➡️ 创建按键驱动文件key.c 和相关头文件key.h,参考[color=var(--weui-LINK)]按键输入例程
➡️ 创建AT24C02驱动文件24cxx.c和24cxx.h
  1. #define ADDR_24CXX_WRITE 0XA0
    $ Q) C0 U- j& ]+ |9 N) A5 M
  2. #define ADDR_24CXX_READ  0XA1  Z- E) R5 b3 X
  3. void AT24CXX_Init(void){  z& k" _' }. i% t% p
  4.   MX_I2C2_Init();       
    + n1 Q; F$ x* G& ?2 ~: B
  5.   while(AT24CXX_Check()){: @* ?. j% t$ l# |8 e
  6.     printf("AT24C02 Checked Failed!\r\n");
    * Y% q. Z  M6 x
  7.     HAL_Delay(500);
    6 @# t# q5 r- ~+ Z3 r. _
  8.   }
    , ]6 h6 G: H# |* ~7 y
  9.   printf("AT24C02 Checked Sucessed!\r\n");
    8 z4 ]! j6 e( D% S3 L' l" V' k: J4 k
  10. }
    6 d: U6 j% _4 v) g
  11. ; g7 Y" t' K% X* O9 e
  12. uint8_t AT24CXX_Check(void){
    - g/ ~' J8 O; S. @0 W3 J
  13.   uint8_t temp;7 H) t9 A% z# T# N
  14.   HAL_I2C_Mem_Read(&hi2c2,ADDR_24CXX_READ,255,I2C_MEMADD_SIZE_8BIT,&temp,1,0xff);                                  
    7 n; L3 q( p, Z% G2 [  g
  15.   if(temp==0x36)       
    ! ~- r" }7 @' ]/ y  a) ]0 G2 G. G
  16.     return 0;                   ' n1 \1 g$ J' ^8 O4 m$ D
  17.   else{
    ! Z! ~+ U: f4 c6 C# B
  18.     uint8_t data = 0x36;
    1 R8 Q# `  }+ H6 x
  19.     HAL_I2C_Mem_Write(&hi2c2,ADDR_24CXX_WRITE,255,I2C_MEMADD_SIZE_8BIT,&data,1,0xff);
    ; l) K+ x1 r5 E$ x4 m" o. C
  20.     HAL_I2C_Mem_Read(&hi2c2,ADDR_24CXX_READ,255,I2C_MEMADD_SIZE_8BIT,&temp,1,0xff);          
    ( M9 v# U1 U0 J. d
  21.     if(temp==0x36)       
    3 ^* d( L# p$ a: P+ y+ \: l1 K$ z1 Y
  22.       return 0;
    ( d+ T  @: Y, }: w3 g2 B
  23.   }
    $ ^8 Q( C: V: Z; c/ M) b4 K) t
  24.   return 1;                                                                                          7 F& q* f1 W+ p/ r0 T; y6 c8 @
  25. }
复制代码

! g' N) y( y6 ~# Y/ R: B
➡️ 在main.c文件下编写I2C测试代码

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

  1. /* USER CODE BEGIN PV */
    , F1 K! X! e- ^2 Z9 b; _- b* ^
  2. #define ADDR_24CXX_WRITE 0XA0/ D0 k3 {- b8 y2 m  ]$ m
  3. #define ADDR_24CXX_READ  0XA1
    ( G  L! g1 ^1 o' n  r6 W
  4. uint8_t WriteBuf[256];
    3 [( [3 f9 `" i. r) J, }
  5. uint8_t ReadBuf[256];  ?& v8 @/ M: e. M$ Q( s1 y
  6. uint16_t i,j;0 t4 F" ^$ _' }* N
  7. /* USER CODE END PV */
    1 U% M% \: U2 I* F: d# y* ~+ `
  8. int main(void){
    / V; x6 G6 z. e2 z8 U
  9.   uint8_t key;
    ; u6 O$ `# ~* n; c& Z5 n  j: Q6 b: D
  10.   HAL_Init();# b6 k' b( ?3 H0 R( ]
  11.   SystemClock_Config();/ E3 r: p' \' u4 ?
  12.   MX_GPIO_Init();% d$ k& F) C; r. {' ~5 S
  13.   MX_I2C2_Init();
    ; S0 j3 s  G2 D& L2 W
  14.   MX_USART1_UART_Init();; O8 b5 n1 Q6 x) p. ^5 `7 [
  15.   /* USER CODE BEGIN 2 */
    0 H* C- S/ Y2 u1 a2 d
  16.   AT24CXX_Init(void);, j9 E  K+ D9 d; A" Z# I! }
  17.   printf("\r\n*********STM32CubeMX I2C AT24C02 Example*********\r\n");% {2 U# L/ R6 Z7 f' N1 H
  18.   for(i = 0;i < 256; i++){         //初始化写数据缓冲区
    1 |$ ?3 Y4 N8 |2 h' {) o
  19.     WriteBuf[i] = i;
    , @1 m& u, N6 n- U/ y) k
  20.   }
    6 H1 q, E  w) M7 i
  21.   /* USER CODE END 2 */
    1 N& w9 Y' J% d  X4 v
  22.   while (1){: b' k2 T6 P' G+ D& h1 C
  23.     key = KEY_Scan(0);
    / u! n) x3 p2 Z0 I0 V
  24.     if(key == KEY_UP_PRES){
    " Q, c7 N( b* {, E2 P1 ^
  25.       for(j = 0;j < 32;j++){        //按页写入EEPROM,分32次写入
    & ]( [5 T. \5 S0 R# g  [- I
  26.         if(HAL_I2C_Mem_Write(&hi2c2,ADDR_24CXX_WRITE,8*j,I2C_MEMADD_SIZE_8BIT,WriteBuf+8*j,8,0xFF) == HAL_OK){6 K7 I/ Z6 c% U* X9 w) n' V' _
  27.           printf("\r\nEEPROM 24C02 Write Test OK!\r\n");$ U: n7 e. v& t
  28.           HAL_Delay(5);
    + t. g8 R* _8 f9 S( }1 `: ^
  29.         }
    ' A. ?+ A1 K4 D* b8 O3 f; @
  30.         else{) b) }. W) L$ \1 @! g
  31.           printf("\r\nEEPROM 24C02 Write Test False!\r\n");
    0 N, U1 B2 p3 k5 e" }
  32.           HAL_Delay(5);                                        & @9 S) g  P) I' _# {+ e
  33.         }5 S" |( ~; R3 Z8 w# E5 k
  34.       }- k( z5 s9 M' e' ~6 |) }/ `9 k
  35.     }& t5 p3 h' h. t4 K) `5 i0 C  P! ]5 h
  36.     //EEPROM读取没有页限制,可以一次读取256个字节        5 Z+ _; h8 Y' C  }; E! H* c
  37.     if(key == KEY_DOWN_PRES){       
    0 S- d3 N0 v5 P, A+ t$ P. ~0 X
  38.       HAL_I2C_Mem_Read(&hi2c2,ADDR_24CXX_READ,0,I2C_MEMADD_SIZE_8BIT,ReadBuf,256,0xFF);
    - G* E  O, u+ E* v# q& C0 ?
  39.       for(i=0;i<256;i++){2 @& R$ U- Z  g) d6 e. g1 X
  40.         printf("0x%02X ",ReadBuf[i]);. I0 f# N8 J8 Z
  41.       }
    6 Z4 E# b3 C2 \8 `: Y; [
  42.       //通过内存比较,判断读取和写入的数据是否相同       
    ' b5 p5 G0 Q0 ?$ H
  43.       if(memcmp(WriteBuf,ReadBuf,256) == 0){        ' Q2 R" E% F! B7 e# J+ X' D6 H" }
  44.         printf("\r\nEEPROM 24C02 Read Test OK!\r\n");
    9 x( |4 H; ?% B" f
  45.       }" _) ^) ~* b& j. s* O
  46.       else{, C, ?: T8 g  G4 E' s
  47.         printf("\r\nEEPROM 24C02 Read Test False!\r\n");
    1 r% T- M# G5 S$ d+ E' i" g
  48.       }
    2 }! f' P* [7 ^& u- I0 R9 X) P
  49.     }
    8 B; \9 M+ d; z8 f' m2 N" V2 g
  50.        
    8 {  p! e! p+ ]2 T
  51.     HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_0);
    8 O, V  ^1 |/ P& L/ f9 F
  52.     HAL_Delay(500);+ f4 ?+ m. \$ u4 T# e
  53.   }
    . L; I: Z: _3 p0 g
  54. }
复制代码
- H) {( B0 i1 M7 h" D8 {# |4 u! I
4.下载验证
编译无误下载到开发板后,可以看到D1指示灯不断闪烁,当按下K_UP按键后数据写入到24C02芯片内,当按下K_DOWN按键后读取24C02芯片的值,同时串口打印出相应信息

  y, i/ q% ?1 u/ C! O+ B. L7 p# H
微信图片_20230701190826.png
7 Z" B$ v' j; ]6 O- l1 {

0 c6 N" T- w( o, a  E5 M2 Z2 g: v
转载自:嵌入式攻城狮
1 g! k/ u) a/ U$ F
8 J2 A$ S# s/ X9 A) N
如有侵权请联系删除* I8 p: ?: E* r

' w8 P. l% X$ @: n8 l& S/ U3 J% g9 G6 {
收藏 评论0 发布时间:2023-7-1 19:09

举报

0个回答

所属标签

相似分享

官网相关资源

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