|
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 ; 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 ?
; A6 ?" Z8 ?/ B( _2 l7 I' J0 p0 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
, 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
* J7 a0 c; Q+ c" q! i- W3 z5 s% t; N; O6 c
下图为AT24C02的总线时序图和时间参数
9 [. B j9 x8 r7 d
* i% O0 T% Z" p$ p) D
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; @
2 Z6 \" a9 T; w3 M5 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
/ v& U9 ^1 i }8 |4 t+ t
3.2 MDK-ARM软件编程 ➡️ 在i2c.c文件下可以看到I2C初始化函数 - void MX_I2C2_Init(void){5 ?' X( f3 l/ J# S: j1 ~9 b4 A
- hi2c2.Instance = I2C2;! ^3 y9 O7 h7 z0 Z
- hi2c2.Init.ClockSpeed = 100000;
# C% b, r9 M6 U; v. v - hi2c2.Init.DutyCycle = I2C_DUTYCYCLE_2;
" ?; U0 t1 e: c) [' d% ` - hi2c2.Init.OwnAddress1 = 0;
M- G2 H2 `* U - hi2c2.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;. ? J# W2 p" D% x3 I R% }0 u. q
- hi2c2.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;8 k( O9 b( D/ s/ E1 D' C4 E: {
- hi2c2.Init.OwnAddress2 = 0;1 a; Z, @) B5 P" `
- hi2c2.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
, C4 }* O. A) Y3 l; T9 L - hi2c2.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
1 {; F: Q# l. q+ k' n - if (HAL_I2C_Init(&hi2c2) != HAL_OK){
# |8 M* K7 g9 Q - Error_Handler();
5 m! P9 O( A. S# x; \* V- Y - }
% N, |* z" f F+ r+ Q, I - }+ s8 A: ^3 M; c1 R7 o. D4 b2 m
- * y5 T* g* T* D J& ~! r
- void HAL_I2C_MspInit(I2C_HandleTypeDef* i2cHandle){
4 f `; ?' S9 u3 o+ D* x - GPIO_InitTypeDef GPIO_InitStruct = {0};
1 n" o9 B" m3 l8 b' C4 t - if(i2cHandle->Instance==I2C2){
$ R( l3 s# d8 a - __HAL_RCC_GPIOB_CLK_ENABLE();0 W$ L& E( H) p6 u& u+ E$ _8 [
- /**I2C2 GPIO Configuration
J6 }9 `7 C3 k% a+ f# E( A6 p - PB10 ------> I2C2_SCL
3 \2 R2 B6 s4 c- @ - PB11 ------> I2C2_SDA*/
+ ^4 [1 d8 S9 x - GPIO_InitStruct.Pin = GPIO_PIN_10|GPIO_PIN_11;
9 K4 c$ S6 p9 Y - GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
% f3 G( M) T+ a+ {% B' p% ` - GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;6 N) p/ B9 M1 _1 Z' C
- HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
$ S2 J- j6 v2 H3 C, k - /* I2C2 clock enable */5 f& C/ b4 o" ^4 T6 n
- /*网上看到很多资料说此处的I2C时钟初始化函数应该放在GPIO
/ k: m" M, j# S ` - 初始化之前,但是这里没有调整也能够正常读写EEPROM*/
4 M8 z A( k2 X - __HAL_RCC_I2C2_CLK_ENABLE(); 0 Q" g% u" Q x. e
- }
复制代码➡️ 创建按键驱动文件key.c 和相关头文件key.h,参考[color=var(--weui-LINK)]按键输入例程 ➡️ 创建AT24C02驱动文件24cxx.c和24cxx.h - #define ADDR_24CXX_WRITE 0XA0
, F' P) D9 p, w- w& c! l - #define ADDR_24CXX_READ 0XA1
. ?8 ?9 u% R& u+ [. N - void AT24CXX_Init(void){' C, l( I1 V, t7 C# L8 `- _
- MX_I2C2_Init(); - Z* x% g; K; X; `7 ]8 a
- while(AT24CXX_Check()){
2 c8 f% S) ?5 b( j8 s - printf("AT24C02 Checked Failed!\r\n");8 Q; _! `( h5 R/ ~' g- L
- HAL_Delay(500);) L( o6 z- Q" U! t
- }
( P) A7 F4 D( v& K) l* M) V - printf("AT24C02 Checked Sucessed!\r\n");
" u7 i4 j+ Q( @; ? - }
* o! ~1 b4 W7 w7 \ d* ^
, }& f# U& s- t% Z8 a/ v" ]0 j- uint8_t AT24CXX_Check(void){! q! H+ P) w1 B8 ?
- uint8_t temp;- p( d6 Y6 L; ^: B3 n
- HAL_I2C_Mem_Read(&hi2c2,ADDR_24CXX_READ,255,I2C_MEMADD_SIZE_8BIT,&temp,1,0xff);
1 v# B; W& E9 A( E C - if(temp==0x36) 8 C- r* F( b W6 {2 I& _+ u
- return 0; 6 z6 c& b5 O; f7 Q* F Z
- else{, f/ _, s6 Y8 j# h( n
- uint8_t data = 0x36;
6 t% a3 b1 O$ z5 H3 z# { - 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$ @
- HAL_I2C_Mem_Read(&hi2c2,ADDR_24CXX_READ,255,I2C_MEMADD_SIZE_8BIT,&temp,1,0xff); . o( T+ a0 X" T# b
- if(temp==0x36)
( ^9 U9 n$ x8 n7 P8 k - return 0;: k8 U! [: Z7 p( C4 {1 k8 f
- }( \$ M- q+ ]) b2 e9 T4 k2 u
- return 1;
/ J& a* {) W$ y5 n/ [ - }
复制代码
' a9 y- G4 [! ]# @* r) I7 Y9 D
➡️ 在main.c文件下编写I2C测试代码 AT24C02的2Kbit分为32页,每页8个字节。而EEPROM也可以按页写入,本例使用了按页写入的方式,分32次写入。注意每次写入完毕需要延时5ms,是AT24C02芯片的要求;读取数据没有页的限制,可以一次全部读取256个字节 - /* USER CODE BEGIN PV */
0 X. T* N5 z: Y+ L/ T - #define ADDR_24CXX_WRITE 0XA0* G+ f6 Z1 j- q% r
- #define ADDR_24CXX_READ 0XA1
9 U5 E2 E5 H+ K9 s, ^ - uint8_t WriteBuf[256];/ ]. \1 _ ?2 |( F3 G* v
- uint8_t ReadBuf[256];) }2 w: U! r) X; t8 p
- uint16_t i,j;
' ^, |5 Q0 c2 _/ s, ^% K - /* USER CODE END PV */7 e3 }, L/ S8 ~( I
- int main(void){
4 ~9 }) c1 b7 g+ Z% V6 W8 Z0 v - uint8_t key;
0 p5 J+ P E, ^7 C2 W - HAL_Init();
# j& e* x' c( f - SystemClock_Config();
$ d, `8 Z+ q R4 Y) Q% M% I - MX_GPIO_Init();% j. O& X2 |( w6 R* S$ B
- MX_I2C2_Init();
) R) H; Y0 u: ^: h - MX_USART1_UART_Init();
4 N7 G7 d# g9 K - /* USER CODE BEGIN 2 */
( I# Y3 ~' m6 H: z/ q6 s! t# E - AT24CXX_Init(void);
% t) r2 ?3 I4 L5 j6 W4 h - printf("\r\n*********STM32CubeMX I2C AT24C02 Example*********\r\n");
- u# O/ f5 K1 b3 m b" N) O& p - for(i = 0;i < 256; i++){ //初始化写数据缓冲区
2 m7 a" M/ Y- R/ J, A2 q4 i - WriteBuf[i] = i;
0 y* a! i& V+ z! r% @ - }& g+ f' _$ `3 n. O, e! x/ Z
- /* USER CODE END 2 */' v0 Y J; X/ |+ h+ e
- while (1){) P9 O7 F J i* {2 ?
- key = KEY_Scan(0);' i2 y* @8 i- l# A t
- if(key == KEY_UP_PRES){/ Y2 e% L4 t2 i3 I
- for(j = 0;j < 32;j++){ //按页写入EEPROM,分32次写入' T4 U) n! M% g4 Q% {+ k
- 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: [ - printf("\r\nEEPROM 24C02 Write Test OK!\r\n");/ C# A3 [1 E" {7 q: A
- HAL_Delay(5);$ ?. t1 Y& v$ V* f
- } \6 u: D$ T. b- f
- else{
4 ^& n3 \! T4 S5 n- T" T - printf("\r\nEEPROM 24C02 Write Test False!\r\n");
) F, P z7 N# ?+ V/ _( G - HAL_Delay(5);
- E5 W4 n, f# n1 q7 E - }
. {5 o+ [2 z7 Y/ V - }
9 A3 z7 j) R# @: S9 ~3 `- }; i, ^ - }
) j+ @# h! Z3 y8 ~% B - //EEPROM读取没有页限制,可以一次读取256个字节
/ R0 E$ a2 M) l: U, f - if(key == KEY_DOWN_PRES){ 0 _! ]/ C. T0 a7 b7 z8 J( _: j
- HAL_I2C_Mem_Read(&hi2c2,ADDR_24CXX_READ,0,I2C_MEMADD_SIZE_8BIT,ReadBuf,256,0xFF);3 Q0 g" C- C, R G
- for(i=0;i<256;i++){
5 v: y+ G1 |; n( V - printf("0x%02X ",ReadBuf[i]);
( m1 [+ L5 T1 M; ^" O6 |3 `$ T; w9 D - }/ d# e- ]. `9 Y9 _2 [
- //通过内存比较,判断读取和写入的数据是否相同
! O1 v& @1 S p S - if(memcmp(WriteBuf,ReadBuf,256) == 0){ 2 k+ _7 Q! u: `) ?" O
- printf("\r\nEEPROM 24C02 Read Test OK!\r\n");
( @7 S# z7 w' H& z, H; O* A/ `, _ - }6 k8 {: ]% d/ h5 c$ K4 N
- else{
: [1 T7 C# O( U& d- p( ^, b - printf("\r\nEEPROM 24C02 Read Test False!\r\n");6 J# X) Y6 I6 o% t* Z) T
- }- j+ T2 Z9 w% G( x
- }
0 h" [0 d. j K. Y2 \: ~; v" c -
4 t" L0 x5 p. ~ - HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_0);
+ i& n$ S& ]' K. ?# R - HAL_Delay(500);
9 q! x$ k8 O9 X6 C T1 k$ k - }1 W5 d; Q. K. v" O2 m# r
- }
复制代码
9 Q' I! ^4 _+ _! O
4.下载验证 编译无误下载到开发板后,可以看到D1指示灯不断闪烁,当按下K_UP按键后数据写入到24C02芯片内,当按下K_DOWN按键后读取24C02芯片的值,同时串口打印出相应信息
- D/ h; J$ [$ |6 P! {( X$ i
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% ] |