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

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

0 i8 O4 O7 j9 }* a4 I
微信图片_20230701190856.png
; K, i; ?; S. c4 G8 ~4 t5 n5 K1 ^9 K
⏩ I2C协议层:I2C总线在传送数据的过程中共有三种类型信号,在这些信号中,起始信号是必需的,结束和应答信号可以不要;I2C总线寻址按照从机地址可分为7位和10位(寻址字节)寻址两种,D7~D1位组成从机的地址,D0位是数据传送方向(0表示主机向从机写数据/1表示主机由从机读数据)

    - f0 ^& `" S% p1 i* S% W1 T4 i, K  ]
  • 开始信号:SCL为高电平时,SDA由高电平向低电平跳变,开始传送数据
  • 结束信号:SCL为高电平时,SDA由低电平向高电平跳变,结束传送数据
    : N  O( A; u. o3 E
  • 应答信号:接收数据的IC在接收到8位数据后,向发送数据的IC发出特定的低电平脉冲,表示已经收到数据。CPU向受控单元发出一个信号后,等待受控单元发出一个应答信号,CPU接收到应答信号后,根据实际情况作出是否继续传递信号的判断。若为收到应答性,判断为受控单元故障
    3 A; `  Y# h& g! |' W

    ' N- ^9 b/ N& b4 ?
微信图片_20230701190853.png

; A6 ?" Z8 ?/ B( _2 l7 I' J0 p
0 k3 f6 y2 E! s+ q' {
1.2 AT24C02芯片简介
AT24C02是一个2K位串行CMOS,内部含有256个字节,此芯片具有I2C通讯接口,芯片内保存的数据在掉电的情况下不丢失(EEPROM),常用于存放比较重要的数据。本实验使用的是SOP-8封装的AT24C02芯片,其引脚说明见下图

0 G" F6 {$ X1 ]. J" [3 i& S
微信图片_20230701190849.png

, v% Z9 b! v( Q; W# @9 b, b$ l* L
AT24C02芯片的器件地址为7位,高4位固定为1010,低3位有上表中的A0/A1/A2引脚的电平决定,还有一位(最低位R/W)用来选择读写方向。本实验中A0/A1/A2引脚接在GND上了,因此器件地址为1010000;加上最低位的读写方向位后,写器件地址为10100000(0xA0),读器件地址为10100001(0xA1)
; Q, W7 z# a  C
微信图片_20230701190846.png

* J7 a0 c; Q+ c" q! i- W3 z5 s% t; N; O6 c
下图为AT24C02的总线时序图和时间参数

9 [. B  j9 x8 r7 d
微信图片_20230701190842.png

* i% O0 T% Z" p$ p) D
微信图片_20230701190839.png

4 ?, o# z- e4 z0 p2 S' m

! r* @* E, J1 {+ M' r( N6 T# C5 Q
2.硬件设计
D1指示灯用来提示系统运行状态,K_UP按键用来控制24C02的数据写入,K_DOWN按键用来控制24C02的数据读取,数据的写入与读取信息通过串口1打印出来

    0 A7 w- Q. q- u  k, b3 N! @$ f9 |$ h  g2 q: P
  • 指示灯D1
  • USART1串口
  • AT24C02
    2 T8 h1 U! N* Y% t* t" ^
  • K_UP和K_DOWN按键! O' J% \$ ~0 n, H2 C2 ?
    0 j$ @& C, s& T- H' d0 Q- t

    1 @! K4 K: T! K; @
微信图片_20230701190835.png

2 Z6 \" a9 T; w3 M
5 M0 K2 p/ U9 c  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,生成工程代码

% m: G8 f/ a+ a8 ?' x% j0 w
微信图片_20230701190831.png

/ v& U9 ^1 i  }8 |4 t+ t
3.2 MDK-ARM软件编程
➡️ 在i2c.c文件下可以看到I2C初始化函数
  1. void MX_I2C2_Init(void){5 ?' X( f3 l/ J# S: j1 ~9 b4 A
  2.   hi2c2.Instance = I2C2;! ^3 y9 O7 h7 z0 Z
  3.   hi2c2.Init.ClockSpeed = 100000;
    # C% b, r9 M6 U; v. v
  4.   hi2c2.Init.DutyCycle = I2C_DUTYCYCLE_2;
    " ?; U0 t1 e: c) [' d% `
  5.   hi2c2.Init.OwnAddress1 = 0;
      M- G2 H2 `* U
  6.   hi2c2.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;. ?  J# W2 p" D% x3 I  R% }0 u. q
  7.   hi2c2.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;8 k( O9 b( D/ s/ E1 D' C4 E: {
  8.   hi2c2.Init.OwnAddress2 = 0;1 a; Z, @) B5 P" `
  9.   hi2c2.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
    , C4 }* O. A) Y3 l; T9 L
  10.   hi2c2.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
    1 {; F: Q# l. q+ k' n
  11.   if (HAL_I2C_Init(&hi2c2) != HAL_OK){
    # |8 M* K7 g9 Q
  12.     Error_Handler();
    5 m! P9 O( A. S# x; \* V- Y
  13.   }
    % N, |* z" f  F+ r+ Q, I
  14. }+ s8 A: ^3 M; c1 R7 o. D4 b2 m
  15. * y5 T* g* T* D  J& ~! r
  16. void HAL_I2C_MspInit(I2C_HandleTypeDef* i2cHandle){
    4 f  `; ?' S9 u3 o+ D* x
  17.   GPIO_InitTypeDef GPIO_InitStruct = {0};
    1 n" o9 B" m3 l8 b' C4 t
  18.   if(i2cHandle->Instance==I2C2){
    $ R( l3 s# d8 a
  19.     __HAL_RCC_GPIOB_CLK_ENABLE();0 W$ L& E( H) p6 u& u+ E$ _8 [
  20.     /**I2C2 GPIO Configuration   
      J6 }9 `7 C3 k% a+ f# E( A6 p
  21.     PB10     ------> I2C2_SCL
    3 \2 R2 B6 s4 c- @
  22.     PB11     ------> I2C2_SDA*/
    + ^4 [1 d8 S9 x
  23.     GPIO_InitStruct.Pin = GPIO_PIN_10|GPIO_PIN_11;
    9 K4 c$ S6 p9 Y
  24.     GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
    % f3 G( M) T+ a+ {% B' p% `
  25.     GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;6 N) p/ B9 M1 _1 Z' C
  26.     HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
    $ S2 J- j6 v2 H3 C, k
  27.     /* I2C2 clock enable */5 f& C/ b4 o" ^4 T6 n
  28.     /*网上看到很多资料说此处的I2C时钟初始化函数应该放在GPIO
    / k: m" M, j# S  `
  29.       初始化之前,但是这里没有调整也能够正常读写EEPROM*/
    4 M8 z  A( k2 X
  30.     __HAL_RCC_I2C2_CLK_ENABLE();        0 Q" g% u" Q  x. e
  31.   }
复制代码
➡️ 创建按键驱动文件key.c 和相关头文件key.h,参考[color=var(--weui-LINK)]按键输入例程
➡️ 创建AT24C02驱动文件24cxx.c和24cxx.h
  1. #define ADDR_24CXX_WRITE 0XA0
    , F' P) D9 p, w- w& c! l
  2. #define ADDR_24CXX_READ  0XA1
    . ?8 ?9 u% R& u+ [. N
  3. void AT24CXX_Init(void){' C, l( I1 V, t7 C# L8 `- _
  4.   MX_I2C2_Init();        - Z* x% g; K; X; `7 ]8 a
  5.   while(AT24CXX_Check()){
    2 c8 f% S) ?5 b( j8 s
  6.     printf("AT24C02 Checked Failed!\r\n");8 Q; _! `( h5 R/ ~' g- L
  7.     HAL_Delay(500);) L( o6 z- Q" U! t
  8.   }
    ( P) A7 F4 D( v& K) l* M) V
  9.   printf("AT24C02 Checked Sucessed!\r\n");
    " u7 i4 j+ Q( @; ?
  10. }
    * o! ~1 b4 W7 w7 \  d* ^

  11. , }& f# U& s- t% Z8 a/ v" ]0 j
  12. uint8_t AT24CXX_Check(void){! q! H+ P) w1 B8 ?
  13.   uint8_t temp;- p( d6 Y6 L; ^: B3 n
  14.   HAL_I2C_Mem_Read(&hi2c2,ADDR_24CXX_READ,255,I2C_MEMADD_SIZE_8BIT,&temp,1,0xff);                                  
    1 v# B; W& E9 A( E  C
  15.   if(temp==0x36)        8 C- r* F( b  W6 {2 I& _+ u
  16.     return 0;                   6 z6 c& b5 O; f7 Q* F  Z
  17.   else{, f/ _, s6 Y8 j# h( n
  18.     uint8_t data = 0x36;
    6 t% a3 b1 O$ z5 H3 z# {
  19.     HAL_I2C_Mem_Write(&hi2c2,ADDR_24CXX_WRITE,255,I2C_MEMADD_SIZE_8BIT,&data,1,0xff);2 a, b& Y( Z( d4 m  a' M$ @
  20.     HAL_I2C_Mem_Read(&hi2c2,ADDR_24CXX_READ,255,I2C_MEMADD_SIZE_8BIT,&temp,1,0xff);          . o( T+ a0 X" T# b
  21.     if(temp==0x36)       
    ( ^9 U9 n$ x8 n7 P8 k
  22.       return 0;: k8 U! [: Z7 p( C4 {1 k8 f
  23.   }( \$ M- q+ ]) b2 e9 T4 k2 u
  24.   return 1;                                                                                          
    / J& a* {) W$ y5 n/ [
  25. }
复制代码

' a9 y- G4 [! ]# @* r) I7 Y9 D
➡️ 在main.c文件下编写I2C测试代码

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

  1. /* USER CODE BEGIN PV */
    0 X. T* N5 z: Y+ L/ T
  2. #define ADDR_24CXX_WRITE 0XA0* G+ f6 Z1 j- q% r
  3. #define ADDR_24CXX_READ  0XA1
    9 U5 E2 E5 H+ K9 s, ^
  4. uint8_t WriteBuf[256];/ ]. \1 _  ?2 |( F3 G* v
  5. uint8_t ReadBuf[256];) }2 w: U! r) X; t8 p
  6. uint16_t i,j;
    ' ^, |5 Q0 c2 _/ s, ^% K
  7. /* USER CODE END PV */7 e3 }, L/ S8 ~( I
  8. int main(void){
    4 ~9 }) c1 b7 g+ Z% V6 W8 Z0 v
  9.   uint8_t key;
    0 p5 J+ P  E, ^7 C2 W
  10.   HAL_Init();
    # j& e* x' c( f
  11.   SystemClock_Config();
    $ d, `8 Z+ q  R4 Y) Q% M% I
  12.   MX_GPIO_Init();% j. O& X2 |( w6 R* S$ B
  13.   MX_I2C2_Init();
    ) R) H; Y0 u: ^: h
  14.   MX_USART1_UART_Init();
    4 N7 G7 d# g9 K
  15.   /* USER CODE BEGIN 2 */
    ( I# Y3 ~' m6 H: z/ q6 s! t# E
  16.   AT24CXX_Init(void);
    % t) r2 ?3 I4 L5 j6 W4 h
  17.   printf("\r\n*********STM32CubeMX I2C AT24C02 Example*********\r\n");
    - u# O/ f5 K1 b3 m  b" N) O& p
  18.   for(i = 0;i < 256; i++){         //初始化写数据缓冲区
    2 m7 a" M/ Y- R/ J, A2 q4 i
  19.     WriteBuf[i] = i;
    0 y* a! i& V+ z! r% @
  20.   }& g+ f' _$ `3 n. O, e! x/ Z
  21.   /* USER CODE END 2 */' v0 Y  J; X/ |+ h+ e
  22.   while (1){) P9 O7 F  J  i* {2 ?
  23.     key = KEY_Scan(0);' i2 y* @8 i- l# A  t
  24.     if(key == KEY_UP_PRES){/ Y2 e% L4 t2 i3 I
  25.       for(j = 0;j < 32;j++){        //按页写入EEPROM,分32次写入' T4 U) n! M% g4 Q% {+ k
  26.         if(HAL_I2C_Mem_Write(&hi2c2,ADDR_24CXX_WRITE,8*j,I2C_MEMADD_SIZE_8BIT,WriteBuf+8*j,8,0xFF) == HAL_OK){
    + Z- d$ j& ^3 H. R+ x+ ]. f: [
  27.           printf("\r\nEEPROM 24C02 Write Test OK!\r\n");/ C# A3 [1 E" {7 q: A
  28.           HAL_Delay(5);$ ?. t1 Y& v$ V* f
  29.         }  \6 u: D$ T. b- f
  30.         else{
    4 ^& n3 \! T4 S5 n- T" T
  31.           printf("\r\nEEPROM 24C02 Write Test False!\r\n");
    ) F, P  z7 N# ?+ V/ _( G
  32.           HAL_Delay(5);                                       
    - E5 W4 n, f# n1 q7 E
  33.         }
    . {5 o+ [2 z7 Y/ V
  34.       }
    9 A3 z7 j) R# @: S9 ~3 `- }; i, ^
  35.     }
    ) j+ @# h! Z3 y8 ~% B
  36.     //EEPROM读取没有页限制,可以一次读取256个字节       
    / R0 E$ a2 M) l: U, f
  37.     if(key == KEY_DOWN_PRES){        0 _! ]/ C. T0 a7 b7 z8 J( _: j
  38.       HAL_I2C_Mem_Read(&hi2c2,ADDR_24CXX_READ,0,I2C_MEMADD_SIZE_8BIT,ReadBuf,256,0xFF);3 Q0 g" C- C, R  G
  39.       for(i=0;i<256;i++){
    5 v: y+ G1 |; n( V
  40.         printf("0x%02X ",ReadBuf[i]);
    ( m1 [+ L5 T1 M; ^" O6 |3 `$ T; w9 D
  41.       }/ d# e- ]. `9 Y9 _2 [
  42.       //通过内存比较,判断读取和写入的数据是否相同       
    ! O1 v& @1 S  p  S
  43.       if(memcmp(WriteBuf,ReadBuf,256) == 0){        2 k+ _7 Q! u: `) ?" O
  44.         printf("\r\nEEPROM 24C02 Read Test OK!\r\n");
    ( @7 S# z7 w' H& z, H; O* A/ `, _
  45.       }6 k8 {: ]% d/ h5 c$ K4 N
  46.       else{
    : [1 T7 C# O( U& d- p( ^, b
  47.         printf("\r\nEEPROM 24C02 Read Test False!\r\n");6 J# X) Y6 I6 o% t* Z) T
  48.       }- j+ T2 Z9 w% G( x
  49.     }
    0 h" [0 d. j  K. Y2 \: ~; v" c
  50.        
    4 t" L0 x5 p. ~
  51.     HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_0);
    + i& n$ S& ]' K. ?# R
  52.     HAL_Delay(500);
    9 q! x$ k8 O9 X6 C  T1 k$ k
  53.   }1 W5 d; Q. K. v" O2 m# r
  54. }
复制代码

9 Q' I! ^4 _+ _! O
4.下载验证
编译无误下载到开发板后,可以看到D1指示灯不断闪烁,当按下K_UP按键后数据写入到24C02芯片内,当按下K_DOWN按键后读取24C02芯片的值,同时串口打印出相应信息

- D/ h; J$ [$ |6 P! {( X$ i
微信图片_20230701190826.png

3 Z' l' Z  w* i9 f7 s& \$ P0 O! y  o
转载自:嵌入式攻城狮
: i7 B, p8 ^: j7 _* p2 X% T) z
" l- I9 d" @% G
如有侵权请联系删除
8 c5 _$ G; I8 l; E2 V& p

( Q/ f% [5 W& ]3 y1 J
% Q6 r7 j+ o7 F' B% ]
赞 收藏 评论0 发布时间:2023-7-1 19:09

举报

0个回答

所属标签

相似技术帖

官网相关资源

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