51单片机-第九节-AT24C02存储器(I2C总线)
一、AT24C02存储器介绍:
AT24C02是存储器,且掉电不丢失,可存储单片机要永久保存的数据。
通讯接口:I2C总线。
容量:256字节。
二、存储器简化模型:
引脚及应用电路:
三、I2C总线:
1.介绍:
(1)I2C总线 (Inter IC BUS)是由Philips公司开发的一种通用数据总线
(2)两根通信线:SCL(Serial Clock)、SDA(Serial Data)
(3)同步、半双工,带数据应答
(4)通用的I2C总线,可以使各种设备的通信标准统一 。
2. 时序结构:
(1)起始,终止:
(2)发送和接收字节:
下面的SDA的两行是具体数据,可0可1,需要注意SCL拉高期间SDA不能变。
(3)发送和接收应答:
四、利用I2C操作AT24C02:
(1)发送一帧数据:
首先 发送 S 表示开始,即时序结构中的起始部分。
随后 发送地址,由8位构成,最后一位是读写标志位,前7位中的前4位是固定的,51单片机中为1010,后3位是可变地址,即存储器简化模型中的 E0,E1,E2 ,我们用不到,置000即可。
然后每发送一个字节需要接收应答。循环。
最后终止流程。
(2)其他流程见下图,拼接而已。
(3)注意:在每次将数据写入AT24C02后,需 Delay 5ms,因为写入时AT24C02需要操作时间。
五、I2C集成:
//I2C的开始和停止,接受和发送字节,接受和发送应答
sbit I2C_SDA = P2 ^ 0;
sbit I2C_SCL = P2 ^ 1;
void I2C_Start()
{
I2C_SCL = 1;
I2C_SDA = 1;//因为根据时序,Start前需要两个均为高
I2C_SCL = 0;
I2C_SDA = 0;
}
void I2C_Stop()
{
I2C_SDA = 0;
I2C_SCL = 1;
I2C_SDA = 1;
}
void I2C_SendByte(unsigned char Byte)
{
unsigned char i;
for (i = 0; i < 8; i++)
{
I2C_SDA = Byte & (0x80 >> i);
I2C_SCL = 1;
I2C_SCL = 0;
//此处注意:拉高立马拉低,需要考虑单片机执行指令的速度
//不过51本来就很慢,不用考虑,否则每行间需加入Delay
}
}
unsigned char I2C_ReceiveByte()
{
unsigned char Byte = 0x00;
unsigned char i = 0;
I2C_SDA = 1;
for (i = 0; i < 8; i++)
{
I2C_SCL = 1;
if (I2C_SDA) { Byte |= (0x80>>i); }
I2C_SCL = 0;
}
return Byte;
}
void I2C_SendAck(unsigned char AckBit)
{
I2C_SDA = AckBit;
I2C_SCL = 1;
I2C_SCL = 0;
}
unsigned char I2C_ReceiveAck()
{
unsigned char AckBit;
I2C_SDA = 1;
I2C_SCL = 1;
AckBit = I2C_SDA;
I2C_SCL = 0;
return AckBit;
}
六、AT24C02集成:
//AT24C02存储器写入和读取字节,WordAddress=0~256
void AT24C02_WriteByte(unsigned char WordAddress, unsigned char Data)
{
I2C_Start();
I2C_SendByte(0xA0);
I2C_ReceiveAck();
I2C_SendByte(WordAddress);
I2C_ReceiveAck();
I2C_SendByte(Data);
I2C_ReceiveAck();
I2C_Stop();
}
unsigned char AT24C02_ReadByte(unsigned char WordAddress)
{
unsigned char Data;
I2C_Start();
I2C_SendByte(0xA0);
I2C_ReceiveAck();
I2C_SendByte(WordAddress);
I2C_ReceiveAck();
//此处由写改为收,重新start
I2C_Start();
I2C_SendByte(0xA1);
I2C_ReceiveAck();
Data = I2C_ReceiveByte();
I2C_SendAck(1);
I2C_Stop();
return Data;
}
七、实例:独立按键写入读出AT24C02:
按键1:Num加一; 按键2:Num减一;
按键3:Num写入; 按键4:Num读出;
unsigned char KeyNum;
unsigned int Num;
void main()
{
LCD_Init();
LCD_ShowString(1, 1, "Hello");
while (1)
{
KeyNum = Key();
if (KeyNum == 1)
{
Num++;
LCD_ShowNum(1, 1, Num, 5);
}
if (KeyNum == 2)
{
Num--;
LCD_ShowNum(1, 1, Num, 5);
}
if (KeyNum == 3)
{
AT24C02_WriteByte(0, Num % 256);
Delay(5);
AT24C02_WriteByte(1, Num / 256);
Delay(5);
LCD_ShowString(2, 1, "Write OK");
Delay(1000);
LCD_ShowString(2, 1, " ");
}
if (KeyNum == 4)
{
Num = AT24C02_ReadByte(1);
Num = Num << 4;
Num += AT24C02_ReadByte(0);
LCD_ShowNum(1, 1, Num, 5);
}
}
}