MCU:AT89S52
EEPROM:AT24C02
IIC
IIC物理层
IIC协议是PHILIPS公司在1980年代开发的串行通信协议,半双工通信,多主从结构(任意时刻只有一主机),低速传输,支持多种传输速率(标准:100Kbit/s、快速:400Kbit/s、高速:3.4Mbit/s),传输距离短,主要用于MCU与外设的通信。IIC一共由两根总线组成:用于数据传输的SDA
和用于时序控制的SCL
。
IIC协议层
主机&从机:控制SCL
电平变换的器件即为主机。
IIC协议没有固定的波特率,但有时序的要求。
IIC空闲状态
SCL
和SDA
均保持高电平。
IIC起始信号
SCL
保持高电平,SDA
由高电平跳变到低电平,产生一个下降沿,表示起始信号。
IIC停止信号
SCL
保持高电平,SDA
由低电平跳变到高电平,产生一个上升沿,表示停止信号。
IIC响应信号
外设每接收到一字节的数据后,在第9个时钟脉冲到来前,(从机)将SDA
稳定置低电平表示应答
,(从机)将SDA
稳定置高电平表示非应答
。
IIC数据传输
一字节数据由高位到低位依次传输,在数据传输过程中,主机必须保持SCL
为低电平(因为当SCL
为高电平时,SDA
的任何电平变化都将被视为起始/停止信号)。
IIC寻址信号
主机发送一个起始信号后,接着发送一字节的寻址信号,该寻址信号的前7位表示器件地址(其中前4位固定为1010
,后3位由从器件的对应的3个引脚的电平决定),第8位则为数据方向位(0
表示主机写入数据,1
表示主机读取数据),若从器件存在,则响应应答
信号。
IIC时序

起始/停止时序

写周期时序

应答时序

EEPROM读写
开发板上的EEPROM使用IIC协议来读写数据。
数据写入
⑴发送IIC起始信号
⑵发送IIC寻址信号(从器件EEPROM的地址+写
操作方向)
⑶发送将要存储数据的EEPROM的存储地址
⑷发送将要写入EEPROM的数据
数据读出
⑴发送IIC起始信号
⑵发送IIC寻址信号(从器件EEPROM的地址+写
操作方向)
⑶发送将要读出数据的EEPROM的存储地址
⑷发送IIC起始信号
⑸发送IIC寻址信号(从器件EEPROM的地址+读
操作方向)
⑹主机读取从器件返回的数据
举个栗子
一个00~99的计数器,每秒计数一次,具有断电记忆功能(开机后,从关机前的最新数值继续计数),软件模拟IIC协议。



#include<reg52.h> #include<intrins.h>
bit x=0; sbit SCL=P2^1; sbit SDA=P2^0; sbit X=P2^4; sbit DU=P2^6; sbit WE=P2^7;
unsigned char num=0; unsigned char i=0;
unsigned char LEDS[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
void LEDS_IO() { WE=1; P0=1; WE=0; DU=1; P0=0; DU=0; }
void Delay5ms() { unsigned char i,j; i=9; j=244; do { while(--j); } while(--i); }
void IIC_Delay() { _nop_(); _nop_(); }
void IIC_INIT() { X=0; SDA=1; IIC_Delay(); SCL=1; IIC_Delay(); }
void IIC_Start() { SDA=1; IIC_Delay(); SCL=1; IIC_Delay(); SDA=0; IIC_Delay(); }
void IIC_Stop() { SDA=0; IIC_Delay(); SCL=1; IIC_Delay(); SDA=1; IIC_Delay(); }
void IIC_ACK() { unsigned char i; SCL=1; IIC_Delay(); while((SDA==1)&&(i<256)) { i++; } SCL=0; IIC_Delay(); }
void IIC_Write(unsigned char DATA) { unsigned char i; unsigned char temp; temp=DATA; for(i=0;i<8;i++) { temp=temp<<1; SCL=0; IIC_Delay(); SDA=CY; IIC_Delay(); SCL=1; IIC_Delay(); } SCL=0; IIC_Delay(); SDA=1; IIC_Delay(); }
unsigned char IIC_Read() { unsigned char i; unsigned char DATA; SCL=0; IIC_Delay(); SDA=1; IIC_Delay(); for(i=0;i<8;i++) { SCL=1; IIC_Delay(); DATA=(DATA<<1)|SDA; SCL=0; IIC_Delay(); } return DATA; }
void EEPROM_Write(unsigned char ADDRESS,unsigned char DATA) { IIC_Start(); IIC_Write(0xa0); IIC_ACK(); IIC_Write(ADDRESS); IIC_ACK(); IIC_Write(DATA); IIC_ACK(); IIC_Stop(); }
unsigned char EEPROM_Read(unsigned char ADDRESS) { unsigned char DATA; IIC_Start(); IIC_Write(0xa0); IIC_ACK(); IIC_Write(ADDRESS); IIC_ACK(); IIC_Start(); IIC_Write(0xa1); IIC_ACK(); DATA=IIC_Read(); IIC_Stop(); return DATA; }
void LEDS_OUTPUT(unsigned char m,unsigned char n) { DU=0; P0=LEDS[m]; DU=1; DU=0; WE=0; P0=0x3e; WE=1; WE=0; Delay5ms(); DU=0; P0=LEDS[n]; DU=1; DU=0; WE=0; P0=0x3d; WE=1; WE=0; Delay5ms(); }
void main() { IIC_INIT(); LEDS_IO(); num=EEPROM_Read(0x00); TMOD=0x01; TH0=0x4c00; TL0=0x4c00; TR0=1; ET0=1; EA=1; while(1) { LEDS_OUTPUT(num/10,num%10); if(x==1) { x=0; EEPROM_Write(0x00,num); } } }
void T() interrupt 1 { TH0=0x4c00; TL0=0x4c00; i++; if(i==20) { i=0; num++; x=1; if(num==100) { num=0; } } }
|
参考资料:
第14章 I2C总线与EEPROM
IIC协议超详细解释(适合小白入门)
IIC详解,包括原理、过程,最后一步步教你实现IIC
IIC原理超详细讲解—值得一看