在学习蓝桥杯的时候,经常会用的EEPROM来保存调用数据。我在写程序的过程中,会出现读取失败或者是写入数据不准确的情况。在这里我总结了一种可以很稳定读写EEPROM的方法
蓝桥杯开发板上使用的存储芯片为24C02,可以把它简单理解为一个专门用来保存数据用的芯片,里面有256个字节的空间(00-FF)。它通过IIC协议与单片机进行通信(收发数据),且保存在里面的数据掉电也不会丢失。想要向它写入或者读取数据,我们需要简单了解一下IIC通信协议,想要写好与各种通信协议有关的程序,必须严格按照时序要求
。
IIC协议是一种双向、两线串行通讯接口,分别是串行数据线SDA和串行时钟线SCL.两根线都必须通过一个上拉电阻接到电源
总线上发送数据的器件被称作发送器,接收数据的器件被称作接收器。控制信息交换的器件被称作主器件,受主器件控制的器件则被称作从器件。主器件产生串行时钟SCL,控制总线的访问状态、产生START和STOP条件。24C02在IIC总线中作为从器件工作。只有当总线处于空闲状态时才可以启动数据传输。每次数据传输均开始于START条件,结束于STOP条件,二者之间的数据字节数是没有限制的,由总线上的主器件决定。信息以字节(8位)为单位传输,第9位时由接收器产生应答。
IIC是一种通信协议,由主器件(单片机)控制两条线:时钟线SCL,数据线SDA进行数据的收发,24C02作为从器件接收
我们要使用IIC协议来进行数据的收发,我们只需要记住读写的时序即可。
写时序
字节写
字节写是常用的写操作。我简单概括一下,有关字节写具体的描述见手册
1.发送起始命令
2.发送器件地址和写命令0xa0*
高四位为器件地址固定,A2-A0接地,最后一位为读写控制,写是0读是1,所以是0xa0;
3.等待应答信号 (即拉低SDA)
4.发送字节地址(你数据想要保存的位置0x00-0xff)
5.等待应答信号
6.发送保存的数据
7.等待应答信号
8.发送停止信号
以上每个步骤都对应一个函数,这些函数在比赛会提供的数据包里的驱动文件里(IIC.c,IIC.h)
代码示例
//按照上面步骤写一个往EEPROM写数据的函数
void Write_eep(uchar addr,uchar dat) //定义两个形参,一个代表想要写入的位置,一个代表想要写入的数据。引入形参,我们可以再调用此函数时设定任意的地址和数据,如果我想把我测的温度数据保存在0x00位置上,那么就可以*Write_eep(0x00,temp)*
{
IIC_Start(); //起始信号
IIC_SendByte(0xa0); //发送器件地址和写命令
IIC_WaitAck(); //等待应答信号
IIC_SendByte(addr); //发送你想要保存的位置
IIC_WaitAck();
IIC_SendByte(value); //发送要保存的数据
IIC_WaitAck();
IIC_Stop(); //发送停止信号
}
读时序
随机读
随机读就是读取指定位置的数据,需要提供地址,是比较常用的读操作。我还是简单概括一下,感兴趣的伙伴可以查看24C02的读操作。
由上图可以看出,前半段就是写一个地址(你要读取的数据的位置),和写操作完全一样,后半段是读操作。
1.发送起始命令
2.发送器件地址和写指令(0xa0)
3.等待应答
4.发送想要读取的数据所在地址
5.等待应答
6.发送起始命令
7发送器件地址和读操作(0xa1)
8.等待应答
9.调用读取函数,读出数据
10.发送一个非应答信号(即拉高SDA,NO ACK)
11.发送停止信号
代码示例
//接上一个示例,把保存的温度数据给读出来
uchar Read_eep(uchar adde) //此函数有返回值,返回value
{
unsigned char value; //定义一个变量,用来保存读取的数据,并返回出去
IIC_Start(); //起始信号
IIC_SendByte(0xa0); //发送器件地址和写命令
IIC_WaitAck(); //等待应答信号
IIC_SendByte(addr); //发送你想要读取的位置
IIC_WaitAck();
IIC_Start();
IIC_SendByte(0xa1); //发送器件地址和读命令
IIC_WaitAck();
value=IIC_RecByte(); //调用函数读取数据
IIC_SendAck(1); //发送一个非应答信号
IIC_Stop();