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

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

/ n2 \) \3 F4 Y- f3 N
微信图片_20230701190856.png
3 c0 G; x, I. R4 f
⏩ I2C协议层:I2C总线在传送数据的过程中共有三种类型信号,在这些信号中,起始信号是必需的,结束和应答信号可以不要;I2C总线寻址按照从机地址可分为7位和10位(寻址字节)寻址两种,D7~D1位组成从机的地址,D0位是数据传送方向(0表示主机向从机写数据/1表示主机由从机读数据)
    & P. S* ^8 y5 ^8 B, z

    / R, P, B: k" V: \' Y, S2 K
  • 开始信号:SCL为高电平时,SDA由高电平向低电平跳变,开始传送数据
  • 结束信号:SCL为高电平时,SDA由低电平向高电平跳变,结束传送数据
    % Q: S6 X) _" n, m! B# |
  • 应答信号:接收数据的IC在接收到8位数据后,向发送数据的IC发出特定的低电平脉冲,表示已经收到数据。CPU向受控单元发出一个信号后,等待受控单元发出一个应答信号,CPU接收到应答信号后,根据实际情况作出是否继续传递信号的判断。若为收到应答性,判断为受控单元故障

    ! f. s" s# D: P4 Q

    9 l% t  i1 X8 g
微信图片_20230701190853.png
4 W& H2 m' Z' `) e

& \2 a5 r6 C- L# ^" U5 F0 J
1.2 AT24C02芯片简介
AT24C02是一个2K位串行CMOS,内部含有256个字节,此芯片具有I2C通讯接口,芯片内保存的数据在掉电的情况下不丢失(EEPROM),常用于存放比较重要的数据。本实验使用的是SOP-8封装的AT24C02芯片,其引脚说明见下图
$ r" B9 X8 A& `
微信图片_20230701190849.png

1 q9 V% q3 m0 l% ~7 f
AT24C02芯片的器件地址为7位,高4位固定为1010,低3位有上表中的A0/A1/A2引脚的电平决定,还有一位(最低位R/W)用来选择读写方向。本实验中A0/A1/A2引脚接在GND上了,因此器件地址为1010000;加上最低位的读写方向位后,写器件地址为10100000(0xA0),读器件地址为10100001(0xA1)
4 c6 I6 f3 n3 w( ~; R
微信图片_20230701190846.png

$ c: ]: H9 x6 E2 o$ v8 L( z: J8 f0 ?- d) X5 H  I
下图为AT24C02的总线时序图和时间参数

6 U3 z) a0 M+ a2 P* c- H* A
微信图片_20230701190842.png
. o- z) n) f5 M2 O/ l/ W( f
微信图片_20230701190839.png

4 l0 w1 b5 u3 d9 ]* c

( F& P' e! N0 M0 l
2.硬件设计
D1指示灯用来提示系统运行状态,K_UP按键用来控制24C02的数据写入,K_DOWN按键用来控制24C02的数据读取,数据的写入与读取信息通过串口1打印出来

    : m! s0 }, X) c1 l8 F1 ~: P- \! d: w
  • 指示灯D1
  • USART1串口
  • AT24C02
    # O: T/ D& N, [4 I: d$ H. u
  • K_UP和K_DOWN按键, Y) y. B6 R' v, z/ S2 q# }' g

    . h- m/ A) v8 f# c2 d8 e7 `

    9 ]4 e4 |2 i/ o, l# Y2 ~% p
微信图片_20230701190835.png

( X8 W- ~2 l/ }" l- S, A

. X+ V7 u7 K6 A5 w1 L- n6 b1 V! g
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,生成工程代码
2 \" r+ Q4 J& Z& w. o- q
微信图片_20230701190831.png
# W) R% U/ h+ l4 ?# ~' _+ [
3.2 MDK-ARM软件编程
➡️ 在i2c.c文件下可以看到I2C初始化函数
  1. void MX_I2C2_Init(void){
    2 R$ o0 a9 q3 N5 ~' y# G1 f
  2.   hi2c2.Instance = I2C2;8 k! S8 x( W) F5 A: g# Q4 ]! E2 y
  3.   hi2c2.Init.ClockSpeed = 100000;- v3 h& x, w" x
  4.   hi2c2.Init.DutyCycle = I2C_DUTYCYCLE_2;
    1 b! N6 x# {  [
  5.   hi2c2.Init.OwnAddress1 = 0;$ |% D- Y1 l% f( P7 F
  6.   hi2c2.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
    - d1 U9 A7 p# D& t) i3 Z
  7.   hi2c2.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;, \0 B9 _4 V1 Z" g, [$ X* [4 p; z5 k
  8.   hi2c2.Init.OwnAddress2 = 0;
    : R# U0 C- j+ O; S" U2 b( @! S
  9.   hi2c2.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
    4 u6 X8 X6 T0 b2 A/ @5 Y5 t
  10.   hi2c2.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;; P3 c: q: u" c, z7 l& x
  11.   if (HAL_I2C_Init(&hi2c2) != HAL_OK){
    1 \* q7 X2 n5 s( @/ E( O9 y
  12.     Error_Handler();
    4 F& [3 P8 {# \& M8 i
  13.   }
    - V8 l8 b) ]1 V9 K0 J& P/ k0 M
  14. }7 C* `. W5 y& k! p

  15. 2 a6 m/ f1 Q4 s5 S# g- l8 W
  16. void HAL_I2C_MspInit(I2C_HandleTypeDef* i2cHandle){
    ' I! r) x7 U8 ~& a% F8 l6 x
  17.   GPIO_InitTypeDef GPIO_InitStruct = {0};8 a' A& T! `& V3 `$ Q
  18.   if(i2cHandle->Instance==I2C2){6 M: S8 Z3 e, R7 T7 h
  19.     __HAL_RCC_GPIOB_CLK_ENABLE();9 M9 P) {7 d0 s
  20.     /**I2C2 GPIO Configuration   
    , N" j& B6 p0 l7 f8 {5 G
  21.     PB10     ------> I2C2_SCL
    / Y# j+ A) Q& S* W
  22.     PB11     ------> I2C2_SDA*/5 ]* \) x3 h" n6 R
  23.     GPIO_InitStruct.Pin = GPIO_PIN_10|GPIO_PIN_11;
    6 f$ i0 B* ]0 \6 x& X
  24.     GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
    ( f; L- O( W5 ^# ]
  25.     GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    & L. q1 y4 b: }  A8 U$ I# W" l' a
  26.     HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
    4 g* ]/ j# m# S) L  g, Z3 F
  27.     /* I2C2 clock enable */
    . ^/ h; k1 _# {$ k% I0 @/ J6 x
  28.     /*网上看到很多资料说此处的I2C时钟初始化函数应该放在GPIO+ V; N" T' `- S9 u' g
  29.       初始化之前,但是这里没有调整也能够正常读写EEPROM*/
    & G+ Y! ^+ E7 S. B
  30.     __HAL_RCC_I2C2_CLK_ENABLE();        2 V( C# v3 g  ?3 A, q
  31.   }
复制代码
➡️ 创建按键驱动文件key.c 和相关头文件key.h,参考[color=var(--weui-LINK)]按键输入例程
➡️ 创建AT24C02驱动文件24cxx.c和24cxx.h
  1. #define ADDR_24CXX_WRITE 0XA0
    ( O6 C1 i" @2 l# J; m# Z+ _) ]0 B- G
  2. #define ADDR_24CXX_READ  0XA1& B4 j: T" e7 i1 \- v& N1 w' c9 {9 P
  3. void AT24CXX_Init(void){
    3 z( T4 U5 V% s
  4.   MX_I2C2_Init();       
    0 ]4 i+ `) G! H. ?# O- H
  5.   while(AT24CXX_Check()){
    ( x; ^0 ^4 H) m" d
  6.     printf("AT24C02 Checked Failed!\r\n");
    9 c$ q# A, n! F/ a
  7.     HAL_Delay(500);9 Z" W- k" D$ _
  8.   }
    " b( ~  t' u6 t5 k2 B; K* H: ~
  9.   printf("AT24C02 Checked Sucessed!\r\n");
    ! v* E9 k8 B8 }$ W
  10. }# _  G( s7 I( J9 z/ @7 V

  11. 6 E8 A4 S5 r8 o, m
  12. uint8_t AT24CXX_Check(void){
    ! ?* D( p& v/ y& n/ w( c- }
  13.   uint8_t temp;  u7 t! H1 E: f! b
  14.   HAL_I2C_Mem_Read(&hi2c2,ADDR_24CXX_READ,255,I2C_MEMADD_SIZE_8BIT,&temp,1,0xff);                                  
    6 r) e! C& E5 c8 b# i$ @. L
  15.   if(temp==0x36)       
    ) O& e  Y5 Y5 X) w9 I4 K3 l
  16.     return 0;                   ' Q4 W5 ~8 K6 X, N
  17.   else{+ Y8 t) T) ]+ I
  18.     uint8_t data = 0x36;
    . J% d% {4 S/ e- H/ L# T) u0 W) A
  19.     HAL_I2C_Mem_Write(&hi2c2,ADDR_24CXX_WRITE,255,I2C_MEMADD_SIZE_8BIT,&data,1,0xff);
    $ T. o$ o  e, {+ G
  20.     HAL_I2C_Mem_Read(&hi2c2,ADDR_24CXX_READ,255,I2C_MEMADD_SIZE_8BIT,&temp,1,0xff);          
    5 E  C, y5 ?. A: V2 F4 b9 T  ~
  21.     if(temp==0x36)       
    2 {8 C6 O& W4 ^7 i5 m
  22.       return 0;6 @$ g3 I/ Y* T. P
  23.   }
    1 c3 L2 M/ |$ s6 U
  24.   return 1;                                                                                          5 O$ q, V% Z  K2 z: J- ]* K
  25. }
复制代码

" ^  ~; a. V/ [) P1 a
➡️ 在main.c文件下编写I2C测试代码

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

  1. /* USER CODE BEGIN PV */
    3 m" @3 V# ]5 u5 y1 G( N
  2. #define ADDR_24CXX_WRITE 0XA0
    ' N; \8 b: P  M+ |  W0 D0 H
  3. #define ADDR_24CXX_READ  0XA1
    ) O3 E5 m# p/ _  b4 u
  4. uint8_t WriteBuf[256];
    4 j0 ^; u6 d& `* `' b
  5. uint8_t ReadBuf[256];
    ! F  ~7 ?/ V5 e: ?) S, r% ~
  6. uint16_t i,j;
    9 T) V' B3 ^: U5 E, I3 z
  7. /* USER CODE END PV */
    ; X) ~" K( t; V2 N
  8. int main(void){
    " s1 j5 y& C8 J( F; }: [
  9.   uint8_t key;3 h+ J3 i5 |7 y" G2 q% @
  10.   HAL_Init();
    8 Z" n: f6 S) {7 v$ C
  11.   SystemClock_Config();
    - B4 h6 A! H# j* O
  12.   MX_GPIO_Init();- c" Y" }7 o4 h7 U( {9 D8 G
  13.   MX_I2C2_Init();- E# Y! w3 c( \6 F* F( v1 T  A! I
  14.   MX_USART1_UART_Init();
    ) n0 F; R4 |6 u0 r
  15.   /* USER CODE BEGIN 2 */
    6 P- C: E/ l) m* E% y4 ~. E: T
  16.   AT24CXX_Init(void);; u  f+ e9 ^% p4 {# U
  17.   printf("\r\n*********STM32CubeMX I2C AT24C02 Example*********\r\n");
    4 L) x$ L: z! e( G0 C' V1 R. _
  18.   for(i = 0;i < 256; i++){         //初始化写数据缓冲区
    ; b& R( N7 [% `& f& C( c0 {  X
  19.     WriteBuf[i] = i;& j- A7 h/ o) h
  20.   }" E5 X" G5 p, i: U
  21.   /* USER CODE END 2 */
    & `. h# R: H/ W8 f/ X
  22.   while (1){6 L' `$ z+ j. r; S" R: `1 W
  23.     key = KEY_Scan(0);
    & v1 x% q+ u0 m1 k
  24.     if(key == KEY_UP_PRES){% K1 u9 i- U5 V. S2 D, W
  25.       for(j = 0;j < 32;j++){        //按页写入EEPROM,分32次写入8 R8 n2 Z/ `$ o  T
  26.         if(HAL_I2C_Mem_Write(&hi2c2,ADDR_24CXX_WRITE,8*j,I2C_MEMADD_SIZE_8BIT,WriteBuf+8*j,8,0xFF) == HAL_OK){
    1 ^1 x! {1 @; l
  27.           printf("\r\nEEPROM 24C02 Write Test OK!\r\n");
    * N' Y+ I  c) s- a; o
  28.           HAL_Delay(5);
    9 b# d' d" G% m6 k+ K! t0 w
  29.         }
    6 A7 G  h& y+ w& a8 T
  30.         else{, K' ~  x, h; F
  31.           printf("\r\nEEPROM 24C02 Write Test False!\r\n");3 C) @3 W6 x% {
  32.           HAL_Delay(5);                                       
    9 w9 a: Y7 Q' N4 A
  33.         }
    5 N$ t# `. z) a- z) s6 h$ v* B* [
  34.       }' n" z4 j: H; H6 ~4 }
  35.     }6 J: A5 }1 S% G
  36.     //EEPROM读取没有页限制,可以一次读取256个字节       
    0 O4 u0 H! X: b+ k
  37.     if(key == KEY_DOWN_PRES){        3 T& J/ v' l* V# f+ c6 x
  38.       HAL_I2C_Mem_Read(&hi2c2,ADDR_24CXX_READ,0,I2C_MEMADD_SIZE_8BIT,ReadBuf,256,0xFF);
    8 H$ ?$ F. A. b/ P! k
  39.       for(i=0;i<256;i++){: {2 F: l6 q$ g) u$ e1 I3 a
  40.         printf("0x%02X ",ReadBuf[i]);; E( K1 T! L  M" l+ L; Z
  41.       }
    3 N8 w8 ?* U7 \, z' \, G8 A" J
  42.       //通过内存比较,判断读取和写入的数据是否相同        9 w( W1 P4 K3 |  `6 Q& k/ s
  43.       if(memcmp(WriteBuf,ReadBuf,256) == 0){        2 q  h+ C9 {6 o5 f7 n" \! a
  44.         printf("\r\nEEPROM 24C02 Read Test OK!\r\n");$ {$ k/ i3 x+ N" g3 e$ t/ B
  45.       }) V$ i8 E5 l+ L+ P& D
  46.       else{
    " j" f% o: x2 S: |: I
  47.         printf("\r\nEEPROM 24C02 Read Test False!\r\n");
    & T; J6 u1 v2 Z+ s7 B  `* H
  48.       }
    ' l* [5 x" x3 \& F, b
  49.     }4 }! S4 w! t) g* m3 P3 {
  50.        
      I* J5 }( o# J2 ~7 N' F4 H
  51.     HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_0);
      h& b$ F" n* k- v! ^
  52.     HAL_Delay(500);
    3 t) i# n- w* }# Y  w# z
  53.   }
    2 o: g. }5 }3 x, H* x
  54. }
复制代码
# S& s6 h; `$ B: a
4.下载验证
编译无误下载到开发板后,可以看到D1指示灯不断闪烁,当按下K_UP按键后数据写入到24C02芯片内,当按下K_DOWN按键后读取24C02芯片的值,同时串口打印出相应信息

, N) D& R4 F/ ~2 v( N
微信图片_20230701190826.png

0 q& v+ z4 |( h+ A  {' O  }! R& F: \9 Z/ r) ]. b
转载自:嵌入式攻城狮
) z+ b( [4 `% p* A' J) M

% N2 Q9 `9 f% i: g; {
如有侵权请联系删除
! g- N) \# r( v7 {# I
0 s2 Y; e8 M# h9 y0 D

! }7 i  n7 T. K
赞 收藏 评论0 发布时间:2023-7-1 19:09

举报

0个回答

所属标签

相似技术帖

官网相关资源

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