AT24C02的使用说明和完整代码-51单片机
简述:at24c02为存储器芯片,可以使用单片机将数据存入其中,同时也可以任意读取。
at24c02的原理及使用方法在其说明资料中已有充分的讲述,本篇仅对其使用的关键步骤进行罗列,以及说明一下具体的使用代码。
at24c02使用iic驱动,需要对其进行启动、停止、等待响应、写字节、读字节的操作
- iic启动和停止:启动/关闭总线
void IIC_Start(void)
{
SDA = 1;
SCL = 1;
somenop;
SDA = 0;
somenop;
SCL = 0;
}
void IIC_Stop(void)
{
SDA = 0;
SCL = 1;
somenop;
SDA = 1;
}
2.等待相应,在每次对at24c02操作后,at24c02会对单片机发出相应信号,以代表at24c02接收到了主机发来的信号,单片机需要等待接收响应。
bit IIC_WaitAck(void)
{
SDA = 1;
somenop;
SCL = 1;
somenop;
if(SDA)
{
SCL = 0;
IIC_Stop();
return 0;
}
else
{
SCL = 0;
return 1;
}
}
3.发送一个字节的数据:向at24c02发送一个字节的数据
void IIC_SendByte(unsigned char byt)
{
unsigned char i;
for(i=0;i<8;i++)
{
if(byt&0x80)
{
SDA = 1;
}
else
{
SDA = 0;
}
somenop;
SCL = 1;
byt <<= 1;
somenop;
SCL = 0;
}
}
4.接收一个字节的数据:读取总线上的一个字节的数据
unsigned char IIC_RecByte(void)
{
unsigned char da;
unsigned char i;
for(i=0;i<8;i++)
{
SCL = 1;
somenop;
da <<= 1;
if(SDA)
da |= 0x01;
SCL = 0;
somenop;
}
return da;
}
至此,我们有了基本的总线驱动,开始封装功能函数
1.单片机向at24c02的某地址写入一个字节的数据:启动总线,第一次发送(发送8位一个字节),发送硬件地址(at24c0的a0,a1,a2的电平即为此三位的硬件地址,通常为000)和读写类型(最后一位,RW低RD高),等待响应,第二次发送,发送要写入的地址,等待响应,第三次发送,发送要写入的数据,等待响应,关闭总线,略作延时。
void rom_write(char add,da)
{
IIC_Start();
IIC_SendByte(0xa0);
IIC_WaitAck();
IIC_SendByte(add);
IIC_WaitAck();
IIC_SendByte(da);
IIC_WaitAck();
IIC_Stop();
delay(30);
}
2单片机从at24c02的某个地址读取一个字节的数据:先向at24c02写地址,再重新启动总线,发送读当前地址指令,等待响应后读取总线数据。
char rom_read(char add)
{
char t;
IIC_Start();
IIC_SendByte(0xa0);
IIC_WaitAck();
IIC_SendByte(add);
IIC_WaitAck();
IIC_Start();
IIC_SendByte(0xa1);
IIC_WaitAck();
t=IIC_RecByte();
return t;
delay(30);
}
至此,单片机控制at24c02的功能函数封装完毕,以下是完整的参考程序,程序为向eeprom的0x00地址写入0x01,并且再读取,具体验证方式读者可使用数码管显示来验证。
/*
作者:FarryNiu
https://blog.csdn.net/qq_43474959/article/details/88373714
*/
#include <reg52.h>
#include "intrins.h"
#define somenop {_nop_();_nop_();_nop_();_nop_();_nop_();}
sbit SDA = P2^1; /* 数据线 */
sbit SCL = P2^0; /* 控制线 */
char a; //a为读取出的数据
void delay(int z)
{
int x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
//启动
void IIC_Start(void)
{
SDA = 1;
SCL = 1;
somenop;
SDA = 0;
somenop;
SCL = 0;
}
//停止
void IIC_Stop(void)
{
SDA = 0;
SCL = 1;
somenop;
SDA = 1;
}
//等待响应
bit IIC_WaitAck(void)
{
SDA = 1;
somenop;
SCL = 1;
somenop;
if(SDA)
{
SCL = 0;
IIC_Stop();
return 0;
}
else
{
SCL = 0;
return 1;
}
}
//发送一个字节
void IIC_SendByte(unsigned char byt)
{
unsigned char i;
for(i=0;i<8;i++)
{
if(byt&0x80)
{
SDA = 1;
}
else
{
SDA = 0;
}
somenop;
SCL = 1;
byt <<= 1;
somenop;
SCL = 0;
}
}
//接收一个字节
unsigned char IIC_RecByte(void)
{
unsigned char da;
unsigned char i;
for(i=0;i<8;i++)
{
SCL = 1;
somenop;
da <<= 1;
if(SDA)
da |= 0x01;
SCL = 0;
somenop;
}
return da;
}
void rom_write(char add,da)
{
IIC_Start();
IIC_SendByte(0xa0);
IIC_WaitAck();
IIC_SendByte(add);
IIC_WaitAck();
IIC_SendByte(da);
IIC_WaitAck();
IIC_Stop();
delay(30);
}
char rom_read(char add)
{
char t;
IIC_Start();
IIC_SendByte(0xa0);
IIC_WaitAck();
IIC_SendByte(add);
IIC_WaitAck();
IIC_Start();
IIC_SendByte(0xa1);
IIC_WaitAck();
t=IIC_RecByte();
return t;
delay(30);
}
void main()
{
rom_write(0x00,0x01); //向AT24C02的地址0x00处写入0x01
a=rom_read(0x00); //从AT24C02的地址0x00处读取数据,赋值给a
while(1)
{
/*自行验证:在第一次向AT24C02写入数据后,将代码中的rom_write(0x00,0x01)删除后烧写进入单片机,仅保留读取函数,如果还能读到,则验证成功*/
}
}