14_单片机_I2C_24C02

1. I2C:Inter-Integrated Circuit,是由Philips公司(现被NXP收购)开发,是一种同步、半双工的通信总线。

 I2C的通信速率:100Kbit/s(标准模式);400Kbit/s(快速模式);3.4Mbit/s(高速模式)

 标准的 I2C 需要两根信号线:

  a. SCL:Serial Clock,时钟线,时钟都是由主设备(Master)提供;

  b. SDA:Serial Data,双向数据线,发送数据或接收数据(收发不能同时进行)

2. I2C属于总线式架构,可以挂载多个参与通信的设备,即多机模式,且任何一个器件都可以作为主设备(Master),在多数情况下都是由微控制器作为主设备(Master)

 I2C:“主从式”方式,主设备(Master)发起通信及总线仲裁,从设备(Slave)被动响应。

 

3. I2C状态(1:表示高电平;0:表示低电平)

 a. 总线START(Start Data Transfer ):SCL=1;SDA发生跳变(由1变为0),开始传送数据

  

 b. 总线STOP(Stop Data Transfer):SCL=1;SDA发生跳变(由0变为1),停止数据传送

  

 c. 数据阶段:I2C数据在SDA上逐位地串行传输,从高位(MSB)开始

  进行数据传送时,在SCL=1时,SDA上的电平必须保持稳定,如下图所示。

  只有SCL为低电平期间,才允许SDA上的电平改变状态。

  

 d. 总线空闲(IDLE):SDA和SCL 同时处于 “高电平” 时,规定为总线的空闲状态,即释放总线,两条信号线被上拉电阻把电平拉高。

 e. ACK 与 NACK:I2C总线上的所有数据都是以8位字节传送的,Mater每发送一个字节,在第9个时钟脉冲期间释放数据线,由Slave反馈一个应答信号。

  应答信号为低电平,规定为有效应答位(ACK),表示Slave已经成功接收了该字节;

  应答信号为高电平,规定为非应答位(NACK),一般表示Slave接收该字节没有成功。

4. I2C的写操作

 

 a. Master 发起 START;

 b. Master 发送 设备地址和写操作,等待ACK;

 c. Slave 发送 ACK;

 d. Master 发送 寄存器地址,等待ACK;

 e. Slave 发送 ACK;

 f. Master 发送 data(8bit),即要写入寄存器中的数据,等待ACK;

 g. Slave 发送 ACK;

 步骤f 和 步骤g 可以重复多次,即顺序写多个寄存器

 h. Master 发起 STOP,结束传输

 

 

5. I2C的读操作

 

 a. Master 发起 START;

 b. Master 发送 设备地址 和 写操作,等待ACK;

 c. Slave 发送ACK;

 d. Master 发送 寄存器地址,等待ACK;

 e. Slave 发送 ACK;

 f. Master 发起 START;

 g. Master 发送 设备地址 和 读操作,等待ACK;

 h. Slave 发送 ACK;

 i. Slave 发送 data(8bit),即寄存器的值;等待ACK;

 j. Master 发送ACK

 k. 上述两步可以重复多次,即顺序读多个寄存器

 l. 当Master接收完数据后,由Mater发送NACK,告知Slave停止发送数据;

 m. Master 发起STOP 结束传输

  

 6. I2C 读写操作 对应的 零件数据表(24C02 EEPROM)

  

  

 7. EEPROM,24C02

 参考零件数据表:https://www.mouser.cn/ProductDetail/Microchip-Technology/24C02CT-ST?qs=WWgnj3qycflYpFNSapIRqA%3D%3D

 零件封装&Pin

 

8. 设备寻址:针对24C02,前4位固定为“1010”,后三位用来作为地址,也注定在同一根总线上,允许使用8个24C02设备

 当前单片机开发板上的E0、E1、E2都接地(即A0、A1、A2接地),设备地址:0xA0(写)、0xA1(读)

     


 9. 实现向EEPROM写入一部分数据,断电再上电,读取EEPROM,通过串口打印

  UART 头文件

 1 #ifndef __UART_H__
 2 #define __UART_H__
 3 
 4 #include <REG51.H>
 5 
 6 /***************函数声明**********************/
 7 void uart_init(void);
 8 void SendOneByte(unsigned char c);
 9 
10 #endif
View Code

 UART 源文件

 1 #include "uart.h"
 2 
 3 
 4 /*****************************************************************
 5 * Function        : uart_init
 6 * Description    : 串口初始化
 7 * Parameters    : None
 8 * Return Value: None
 9 *****************************************************************/
10 void uart_init(void)
11 {
12     TMOD = 0x20;
13     SCON = 0x50;
14     TH1 = 0xF3;
15     TL1 = TH1;
16     PCON = 0x80;    // 加倍波特率4800
17     EA = 1;
18     ES = 1;
19     TR1 = 1;
20 }
21 
22 /*****************************************************************
23 * Function        : SendOneByte
24 * Description    : 通过串口发送1个字节
25 * Parameters    : None
26 * Return Value: None
27 *****************************************************************/
28 void SendOneByte(unsigned char c)
29 {
30     SBUF = c;
31     while(!TI);
32     TI = 0;
33 }
34 
35 void UARTInterrupt(void) interrupt 4
36 {
37 }
View Code

 I2C 头文件

 1 #ifndef __I2C__H_
 2 #define __I2C__H_
 3 
 4 #include <reg51.h>
 5 
 6 /**************关键字重定义**************/
 7 #ifndef uchar
 8 #define uchar unsigned char
 9 #endif
10 
11 #ifndef uint
12 #define uint unsigned char
13 #endif
14 
15 /**************I/O定义**************/
16 sbit I2C_SCL = P0^0;
17 sbit I2C_SDA = P0^1;
18 
19 /**************函数声明**************/
20 void I2C_Delay10us(void);
21 void I2C_Start(void);
22 void I2C_Stop(void);
23 uchar I2C_SendByte(uchar dat);
24 uchar I2C_ReadByte(void);
25 
26 #endif
View Code

 I2C 源文件

  1 #include "I2C.h"
  2 
  3 
  4 /*****************************************************************
  5  * Function        : I2C_Delay10us
  6  * Description        : 延时10us,SDA需要保持4.7us以上
  7  * Parameters        : None
  8  * Return Value        : None
  9  *****************************************************************/
 10 void I2C_Delay10us(void)
 11 {
 12     uchar a, b;
 13     for(b=1; b>0; b--)
 14         for(a=2; a>0; a--);
 15 }
 16  
 17 /*****************************************************************
 18  * Function        : I2C_Start
 19  * Description        : I2C 发送 START
 20  * Parameters        : None
 21  * Return Value        : None
 22  *****************************************************************/
 23 void I2C_Start(void)
 24 {
 25     I2C_SDA = 1;
 26     I2C_Delay10us();
 27     I2C_SCL = 1;
 28     I2C_Delay10us();
 29      
 30     // 起始信号:SDA跳变 1->0
 31     I2C_SDA = 0;
 32     I2C_Delay10us();
 33      
 34     // SCL 复位
 35     I2C_SCL = 0;
 36     I2C_Delay10us();
 37 }
 38  
 39  /*****************************************************************
 40  * Function        : I2C_Stop
 41  * Description        : I2C 发送 STOP
 42  * Parameters        : None
 43  * Return Value        : None
 44  *****************************************************************/
 45 void I2C_Stop(void)
 46 {
 47     I2C_SDA = 0;
 48     I2C_Delay10us();
 49     I2C_SCL = 1;
 50     I2C_Delay10us();
 51      
 52     // 结束信号,SDA跳变 0->1
 53     I2C_SDA = 1;
 54     I2C_Delay10us();
 55 }
 56  
 57   /*****************************************************************
 58  * Function        : I2C_SendByte
 59  * Description        : 通过I2C发送1个字节
 60  * Parameters        : dat(字节数据)
 61  * Return Value        : 0-Fail;1-Pass
 62  *****************************************************************/
 63 uchar I2C_SendByte(uchar dat)
 64 {
 65     uchar i = 0,b = 0;        //最大255,一个机器周期为1us,最大延时255us
 66      
 67     // SCL=1期间,SDA上的电平需要保持稳定,I2C从MSB开始传输
 68     // START 中 SCL已复位0
 69     for(i=0; i<8; i++)
 70     {
 71         I2C_SDA = dat>>7;    // 右移7位,取最高位
 72         dat = dat<<1;        // 将最高位遗弃,次高位变为最高位
 73         I2C_Delay10us();
 74          
 75         I2C_SCL = 1;
 76         I2C_Delay10us();
 77         I2C_SCL = 0;
 78         I2C_Delay10us();
 79     }
 80      
 81     // 释放总线
 82     I2C_SDA = 1;
 83     I2C_Delay10us();
 84     I2C_SCL = 1;
 85     I2C_Delay10us();
 86      
 87     while(I2C_SDA)
 88     {
 89         b++;
 90         if(b > 200)    // 判断 ACK(传输失败) 还是 NACK(结束传输)
 91         {
 92             I2C_SCL = 0;
 93             I2C_Delay10us();
 94             return 0;
 95         }
 96     }
 97      
 98     I2C_SCL = 0;
 99     I2C_Delay10us();
100     return 1;
101 }
102  
103  /*****************************************************************
104  * Function        : I2C_ReadByte
105  * Description        : 通过I2C读取一个字节
106  * Parameters        : None
107  * Return Value        : dat(字节数据)
108  *****************************************************************/
109 uchar I2C_ReadByte(void)
110 {
111     uchar i = 0,dat = 0;
112      
113     I2C_SDA = 1;            // START 和 SEND 之后 SCL已复位,释放SDA
114     I2C_Delay10us();
115      
116     for(i=0; i<8; i++)
117     {
118         I2C_SCL = 1;
119         I2C_Delay10us();
120          
121         dat = dat<<1;
122         dat = dat | I2C_SDA;
123         I2C_Delay10us();
124          
125         I2C_SCL = 0;        // 为下一个脉冲周期准备
126         I2C_Delay10us(); 
127     }
128     return dat;
129 }
View Code

 EEPROM 24C02 头文件

 1 #ifndef __E24C02__H_
 2 #define __E24C02__H_
 3 
 4 #include "I2C.h"
 5 
 6 #ifndef uchar
 7 #define uchar unsigned char
 8 #endif
 9 
10 #ifndef uint
11 #define uint unsigned int
12 #endif
13 
14 void E24C02_write(uchar addr, uchar dat);
15 uchar E24C02_read(uchar addr);
16 
17 
18 #endif
View Code

 EEPROM 24C02 源文件

 1 #include "E24C02.h"
 2 
 3  /*****************************************************************
 4  * Function        : E24C02_write
 5  * Description        : 向EEPROM 24C02写入数据
 6  * Parameters        : addr(寄存器地址);dat(数据)
 7  * Return Value        : None
 8  *****************************************************************/
 9  void E24C02_write(uchar addr, uchar dat)
10  {
11      I2C_Start();            // START
12      I2C_SendByte(0xA0);    // 设备地址,写操作
13      I2C_SendByte(addr);            // 要写入的寄存器地址
14      I2C_SendByte(dat);        // 写入的数据
15      I2C_Stop();            // STOP
16  }
17  
18  /*****************************************************************
19  * Function                : 
20  * Description        : 
21  * Parameters            : 
22  * Return Value        : 
23  *****************************************************************/
24  uchar E24C02_read(uchar addr)
25  {
26      uchar tmp;
27      
28      I2C_Start();            // START
29      I2C_SendByte(0xA0);    // 设备地址,写操作
30      I2C_SendByte(addr);            // 要写入的寄存器地址
31      
32      I2C_Start();            // START
33      I2C_SendByte(0xA1);    // 设备地址,读操作
34      tmp = I2C_ReadByte();      // 读取数据,赋值tmp
35      I2C_Stop();            // STOP
36      
37      return tmp;
38  }            
View Code

 Main

 1 #include "I2C.h"
 2 #include "uart.h"
 3 #include "E24C02.h"
 4 
 5  /*****************************************************************
 6  * Function        : delay15ms
 7  * Description        : 延时15ms
 8  * Parameters        : None
 9  * Return Value        : None
10  *****************************************************************/
11 void delay15ms(void)   
12 {
13     unsigned char a,b,c;
14     for(c=1;c>0;c--)
15         for(b=238;b>0;b--)
16             for(a=30;a>0;a--);
17 }
18 
19 
20 void main(void)
21 {
22     unsigned char i = 0, addr = 0;
23     unsigned char src_data[] = "P####OIUYTREWQ@#$";
24     unsigned char buf[8] = "11111111";
25     
26     uart_init();
27     
28     // 写入数据到EEPROM 24C02
29     for(i=0; i<8; i++)
30     {
31         E24C02_write(addr, src_data[i]);
32         delay15ms();
33         addr++;
34     }
35     
36     // 打印buf的内容
37     for(i=0; i<8; i++)
38     {
39         SendOneByte(buf[i]);
40     }
41     
42     // 打印分割线
43     for(i=0; i<30; i++)
44     {
45         SendOneByte('+');
46     }
47     
48     // 读取EEPROM的数据
49     addr = 0;
50     for(i=0; i<8; i++)
51     {
52         buf[i] = E24C02_read(addr);
53         delay15ms();
54         addr++;
55     }
56     
57     // 打印buf的内容
58     for(i=0; i<8; i++)
59     {
60         SendOneByte(buf[i]);
61     }
62     
63     while(1);
64 }
View Code

记录下~

posted on 2023-04-25 23:26  Ivan2023  阅读(80)  评论(0)    收藏  举报