为了方便查看博客,特意申请了一个公众号,附上二维码,有兴趣的朋友可以关注,和我一起讨论学习,一起享受技术,一起成长。
AT24C02是一个2K位串行CMOS E2PROM, 内部含有256个8位字节,CATALYST公司的先进CMOS技术实质上减少了器件的功耗。AT24C02有一个8字节页写缓冲器。该器件通过IIC总线接口进行操作,有一个专门的写保护功能。在单片机上的应用广泛, 可以实现掉电数据不丢失功能。
通过IIC几种信号的组合,可以向AT24C02指定单元地址写一字节的数据。
可以看出,写顺序为:起始,写器件地址,应答,写单元地址,应答,写数据,应答,终止。
从AT24C02任意单元地址读取数据,可以看出读写顺序为:起始,写器件地址(下一个字节为写),应答,写单元地址,应答,起始,写器件地址(下一个字节为读取),读取数据,终止。
delay.h:
#ifndef _DELAY_H
#define _DELAY_H
#include "stc51.h"
void delay_us(uchar t);
void delay_ms(uint t);
#endif
#include "delay.h"
#include "stc51.h"
//Function:延时1us
//Input:延时的微秒数
//Output:无
//Return:无
//Others:无
void delay_us(uchar t)
{
while(t--);
}
//Function:延时1us
//Input:延时的毫秒数
//Output:无
//Return:无
//Others:无
void delay_ms(uint t)
{
uint x,y;
for(x=t;x>0;x--)
for(y=110;y>0;y--);
}
iic.h:
#ifndef _IIC_H
#define _IIC_H
#include "stc51.h"
/*IIC管脚定义*/
sbit IIC_SDA = P3^0;
sbit IIC_SCL = P3^1;
void IO_Init();
void IIC_Start();
void IIC_Stop();
void IIC_Ack();
void IIC_NAck();
void IIC_Write_Byte(uchar txd);
uchar IIC_Read_Byte();
#endif
iic.c:
#include "delay.h"
#include "iic.h"
#include "stc51.h"
//Function:初始化IO口
//Description:GPIO初始化为高,通知器件总线空闲
//Input:无
//Output:无
//Return:无
//Others:无
void IO_Init()
{
IIC_SCL = 1;
delay_us(5);
IIC_SDA = 1;
delay_us(5);
}
//Function:启动IIC传输
//Description:IIC_SCL为高时,IIC_SDA由高到低
//Input:无
//Output:无
//Return:无
//Others:无
void IIC_Start()
{
IIC_SDA = 1;
IIC_SCL = 1;
delay_us(5);
IIC_SDA = 0;
delay_us(5);
IIC_SCL = 0;
}
//Function:停止IIC传输
//Description:IIC_SCL为高时,IIC_SDA由低到高
//Input:无
//Output:无
//Return:无
//Others:无
void IIC_Stop()
{
IIC_SCL = 0;
IIC_SDA = 0;
delay_us(5);
IIC_SCL = 1;
IIC_SDA = 1;
delay_us(5);
}
//Function:产生应答信号
//Description:IIC_SCL为高时,IIC_SDA被拉低并保持一定时间的低电平
//Input:无
//Output:无
//Return:无
//Others:无
void IIC_Ack()
{
uchar i;
IIC_SCL = 1;//在scl为高电平期间等待应答
delay_ms(2);
while((IIC_SDA == 1) && i < 250)//若为应答0即退出,从机向主机发送应答信号
i++;//通过i自增等待一段时间
IIC_SCL = 0;//得到应答,拉低时钟
delay_ms(2);
}
//Function:产生非应答信号
//Description:IIC_SCL为高时,IIC_SDA为高
//Input:无
//Output:无
//Return:无
//Others:无
void IIC_NAck()
{
IIC_SCL = 1;
delay_ms(2);
IIC_SDA = 1;
IIC_SCL = 0;
delay_ms(2);
}
//Function:I2C写一个字节数据,返回ACK或者NACK
//Description:从高位开始依次传输
//Input:写的字节
//Output:无
//Return:无
//Others:无
void IIC_Write_Byte(uchar txd)
{
uchar len;
for (len=0;len<8;len++)
{
IIC_SCL = 0;//只有在IIC_SCL为低电平时,才允许IIC_SDA上的数据变化
delay_us(5);
if(txd & 0x80)
IIC_SDA = 1;
else
IIC_SDA = 0;
delay_us(5);
IIC_SCL = 1;//在IIC_SCL为高电平时,不允许IIC_SDA上的数据变化,使数据稳定
txd <<= 1;
delay_us(10);
IIC_SCL = 0;
delay_us(5);
}
IIC_SDA = 1;//释放总线
IIC_SCL = 1;
delay_us(5);
}
//Function:I2C读一个字节数据,返回ACK或者NACK
//Description:从高到低,依次接收
//Input:是否应答
//Output:无
//Return:接收的数据
//Others:无
uchar IIC_Read_Byte(/*uchar ack*/)
{
uchar len,dat = 0;
IIC_SDA = 1;//准备读取数据
for(len=0;len<8;len++)
{
IIC_SCL = 0;
delay_us(5);
IIC_SCL = 1;//不允许IIC_SDA变化
delay_us(5);
dat <<= 1;
dat |= IIC_SDA; //读数据
delay_us(5);
IIC_SCL = 0;//允许IIC_SDA变化等待下一位数据的到来
delay_us(5);
}
return dat;
}
(3)AT24C02实现:
at24c02.h:
#ifndef _AT24C02_H
#define _AT24C02_H
#include "stc51.h"
#define IIC_WADDR 0XA0
#define IIC_RADDR 0XA1
void AT24C02_Init(void);
void At24c02_Write_Byte(uchar addr,uchar dat);
uchar At24c02_Read_Byte(uchar addr);
void At24c02_Serial_Write(uchar Writeaddr,uchar *Str,uchar Len);
void At24c02_Serial_Read(uchar Readaddr,uchar *Str,uchar Len);
#endif
at24c02.c:
#include "iic.h"
#include "delay.h"
#include "at24c02.h"
#include "stc51.h"
//Function:初始化AT24C02
//Description:IO口属于空闲,准备开始通信
//Input:无
//Output:无
//Return:无
//Others:无
void AT24C02_Init(void)
{
IO_Init();
}
//Function:写一个字节
//Description:向AT24C02的任意地址写入一个字节数据
//Input:写入的地址和数据
//Output:无
//Return:无
//Others:无
void At24c02_Write_Byte(uchar addr,uchar dat)
{
IIC_Start(); //启动
IIC_Write_Byte(IIC_WADDR); //发送从设备地址
IIC_Ack(); //等待从设备的响应
IIC_Write_Byte(addr); //发出芯片内地址
IIC_Ack(); //等待从设备的响应
IIC_Write_Byte(dat); //发送数据
IIC_Ack(); //等待从设备的响应
IIC_Stop(); //停止
delay_ms(10); // 写入周期
}
//Function:指定地址读一个字节
//Description:向AT24C02的指定地址读出一个字节数据
//Input:读地址
//Output:无
//Return:读到的数据
//Others:无
uchar At24c02_Read_Byte(uchar addr)
{
uchar dat;
IIC_Start();
IIC_Write_Byte(IIC_WADDR);//发送发送从设备地址 写操作
IIC_Ack();
IIC_Write_Byte(addr);//发送芯片内地址
IIC_Ack();
IIC_Start();
IIC_Write_Byte(IIC_RADDR);//发送发送从设备地址 读操作
IIC_Ack();
dat = IIC_Read_Byte();//获取数据
IIC_Stop();
return dat;
}
//Function:任意地址写入一串数据
//Description:向AT24C02写入一串数据
//Input:写地址,写数据,数据长度
//Output:无
//Return:无
//Others:无
void At24c02_Serial_Write(uchar Writeaddr,uchar *Str,uchar Len)
{
while(Len--)
{
At24c02_Write_Byte(Writeaddr,*Str);
Writeaddr++;
Str++;
}
}
//Function:指定地址读出一串数据
//Description:向AT24C02读出一串数据
//Input:读地址,读数据,数据长度
//Output:无
//Return:无
//Others:无
void At24c02_Serial_Read(uchar Readaddr,uchar *Str,uchar Len)
{
while(Len)
{
*Str++ = At24c02_Read_Byte(Readaddr++);
Len--;
}
}
stc51.h:
#ifndef _STC51_H
#define _STC51_H
#include
typedef unsigned char uchar;
typedef unsigned int uint;
#endif
主函数main.c:
#include "iic.h"
#include "at24c02.h"
#include "stc51.h"
#include "Lcd_4line.h"
#include "key.h"
#include "delay.h"
//要写入到24c02的字符串数组
const uchar TEXT_Buffer[]={"STC51"};
uchar TEXT_Buffer1[]={"00000"};//数组一定初始化
#define SIZE sizeof(TEXT_Buffer)
void main()
{
uchar dat = 8;
uchar Text = 6 + '0';
uchar val;
Lcd_1602_init();
AT24C02_Init();
while(1)
{
lcd_onestring(0,0,Text);
At24c02_Write_Byte(10,dat);
val = At24c02_Read_Byte(10);
val = val + '0';
lcd_onestring(1,0,val);
lcd_string(0,7,5,TEXT_Buffer);
At24c02_Serial_Write(10,TEXT_Buffer,5);
At24c02_Serial_Read(10,TEXT_Buffer1,5);
lcd_string(1,7,5,TEXT_Buffer1);
}
}
通过LCD1602显示写入和读出的数据,分别测试单字节和字符串。