学习完了AT24C02芯片,所以来总结介绍一下,有写的不对的地方欢迎指正交流。
本次实验主要用到的是AT24C02芯片,下面总结一下:(普中开发板上给我们能操作的就只有EEPROM的SDA和SCL两个引脚)
AT24C02用到的是I2C总线,是一种串行扩展总线
采用串行总线技术可以使:
1.系统的硬件设计大大简化
2.系统的体积减小、可靠性提高
3.系统的更改和扩充极为容易
常用的串行扩展总线有:
1.I2C (Inter IC BUS)总线
2.单总线(1-WIRE BUS)
3.SPI(Serial Peripheral Interface)总线
4.Microwire/PLUS……
串行总线的应用和发展:
越来越多的外围器件集成了同步串行总线,其中I2C总线接口的器件发展较快,大部分微处理器支持该类二线制总线。
I2C总线因使用简单,硬件接线更少,其使用量的增长超过了SPI总线。许多主流微处理器和外围器件同时集成了三线和二线制总线接口
I2C串行总线概述
PHLIPS公司推出的一种串行总线,具备多主机系统所需的包括总线裁决和高低速器件同步功能的高性能串行总线。
只有两根双向信号线:
数据线-----SDA
时钟线-----SCL
I2C总线通过上拉电阻接正电源。
当总线空闲时,两根线均为高电平。
连到总线上的任一器件输出的低电平,都将使总线的信号变低,即各器件的SDA及SCL都是线“与”关系。
由于51单片机没有I2C总线,所以我们要用软件来模拟总线时序
24Cxx这些器件都是支持I2C总线传输协议的,如下图:
总线上发送数据的器件被称作发送器,接收数据的器件被称作接收器。控制信息交换的器件被称作主器件,受主器件控制的器件则被称作从器件。主器件产生串行时钟SCL,控制总线的访问状态、产生 START和STOP条件。
24CXX在I2C总线中作为从器件工作只有当总线处于空闲状态时才可以启动数据传输。每次数据传输均开始于 START条件,结束于STOP条件,二者之间的数据字节数是没有限制的,由总线上的主器件决定。信息以字节(8位)为单位传输,第9位时由接收器产生应答。
所以在代码中要模拟起始信号和停止信号
void start()//开始信号
{
SDA=1;
Delay10us();
SCL=1;
Delay10us();//建立时间是SDA保持时间>4.7us
SDA=0; //SDA一个下降沿启动信号
Delay10us();//保持时间是>4us
SCL=0;
Delay10us();
}
void stop()//停止信号
{
SDA=0;
Delay10us();
SCL=1;
Delay10us();//建立时间大于4.7us
SDA=1; //SDA一个上升沿停止信号
Delay10us();
}
还要有总线初始化,把总线都拉高,释放总线
void init()//总线初始化
{
SCL=1;
Delay10us();
SDA=1;
Delay10us();
}
还要注意的一点是,只有当SCL置为低电平,SDA上的数据才能改变(才能发送或者接受)
总线上的接收器每接收到应答,主器件必须对应的额外的时钟脉冲,见图7。
我们发送数据的时候:首先我们要把SCL置0,这样SDA上的数据才能改变(发送或者接收),这里的传输是从高到低串行传输,每次传输数据的时候,SCL要有一个稳定的高电平,传输完了之后,释放SDA总线把数据传到AT24C02上,等待器件的应答。
uchar I2cSendByte(uchar dat)//模拟IIC发送字节
{
uchar a=0,b=0;//最大255,一个机器周期为1us,最大延时255us。
for(a=0;a<8;a++)//要发送8位,从最高位开始
{
SDA=dat>>7; //起始信号之后SCL=0,所以可以直接改变SDA信号
dat=dat<<1; //用dat一位位传输数据给SDA
Delay10us();
SCL=1;
Delay10us();//建立时间>4.7us
SCL=0;
Delay10us();//时间大于4us
}
SDA=1; //释放SDA
Delay10us();
SCL=1; //应答时钟脉冲,等待应答
while(SDA)//等待应答,也就是等待从设备把SDA拉低
{
b++;
if(b>200) //如果超过2000us没有应答发送失败,或者为非应答,表示接收结束
{
SCL=0;
Delay10us();
return 0;
}
}
SCL=0;
Delay10us();
return 1;
}
如果应答时间太长,我们要手动结束不能一直等待(这里是用b计数等待,超过2000us没应答,我们强制表示结束)
同理,我们的接收数据也是一样,开始都是要SCL置0,SDA为1才能改变数据
uchar I2cReadByte()//模拟IIC接收字节
{
uchar a=0,dat=0;
SDA=1; //起始和发送一个字节之后SCL都是0
Delay10us();
for(a=0;a<8;a++)//接收8个字节
{
SCL=1; //SCL 为高电平才能传输数据
Delay10us();
dat<<=1;
dat|=SDA;//用dat一位位读取SDA的值
Delay10us();
SCL=0;
Delay10us();
}
return dat;
}
然后我们就能写一个写数据函数,和读数据函数了。这两个函数也是根据芯片的时序来写的
这样就大概有了一个操作AT24C02的框架了
本人做的是:利用定时器产生一个0-99秒变化的秒表,并显示在数码管上,将变化的数据写入AT24C02内。关闭电源,重启时读入原来AT24C02里面的数据,并将数据继续变化显示在数码管上。其中用到是就是AT24C02来解决掉电数据保存的问题。
至于完整的实验代码这里就不放上来了,就是基于上面的代码框架来写的。
如果需要的话可以留言,人多的话我再放上来。