📄 ex8_1.c
字号:
//程序:ex8_1.c
//功能:EEPROM读写程序,从AT24C01的4个连续存储单元中读出4个字节的数据,然后将4
// 个新的数值写入AT24C01的对应4个存储单元中,再重新读出。
#include <reg51.h>
#include <intrins.h> //_nop_()函数所在的头文件
/******************************位定义及预定义*******************************/
#define AddWr 0xa0 //器件地址选择及写数据地址0xa0
#define AddRd 0xa1 //器件地址选择及读数据地址0xa1
sbit SDA= P3^4; //串行数据输入/输出位定义
sbit SCL= P3^3; //串行时钟位定义
bit ack_bit; //应答标志
/******************************函数声明************************************/
void mDelay(unsigned char ms); //延时函数声明
void Start(void); //开始函数
void Stop(void); //停止函数
void Ack(void); //应答函数
void NoAck(void); //反向应答函数
void Shout(unsigned char Data); //串行输出数据函数
unsigned char Shin(void); //串行输入数据函数
void WrByte(unsigned char Data[],unsigned char Address,unsigned char Num); //写字节函数
void RdRadom(unsigned char Data[],unsigned char Address,unsigned char Num); //随机地址读函数
/******************************主函数************************************/
void main()
{
unsigned char R1data[4]= {0,0,0,0}; //初始化读数据数组1为全0
unsigned char R2data[4]= {0,0,0,0}; //初始化读数据数组2为全0
unsigned char Wdata[4]={1,2,3,4}; //初始化写数据数组
RdRadom(R1data,4,4); //读AT24C01中的4个字节数据到读数据数组1
WrByte(Wdata,4,4); //将初始化后的数值写入AT24C01
mDelay(20);
RdRadom(R2data,4,4); //重新读出写入的数据到读数据数组2
}
/******************************写字节************************************/
//函数名:WrByte
//函数功能:向AT24C**器件的指定地址按字节连续写入数据
//形式参数:待写入的数据Data[],起始地址Address,待写入的字节数Num
//返回值:返回为0表示操作成功,否则操作有误
void WrByte(unsigned char Data[],unsigned char Address,unsigned char Num)
{
unsigned char i;
unsigned char *PData;
PData=Data;
for(i=0;i<Num;i++) //连续写入Num个字节数据
{
Start(); //发送启动信号
Shout(AddWr); //发送写操作器件地址AddWr,0xa0
Ack(); //接收ACK应答
Shout(Address+i); //发送地址
Ack(); //接收ACK应答
Shout(*(PData+i)); //发送待写入的数据
Ack(); //接收ACK应答
Stop(); //发送停止信号
mDelay(20); //等待内定时写入周期结束
}
}
/*****************************随机地址读***********************************/
//函数名:RdRadom
//函数功能:从AT24C**器件的指定地址按字节读入数据
//形式参数:起始地址Address,待读入的字节数Num
//返回值:读出的字节放入data[],如果操作成功返回为0,否则操作有误
void RdRadom(unsigned char Data[],unsigned char Address,unsigned char Num)
{
unsigned char i;
unsigned char *PData;
PData=Data;
for(i=0;i<Num;i++)
{
Start(); //开始
Shout(AddWr); //发送写操作器件地址AddWr
Ack();
shout(Address+i); //发送字节地址
Ack();
Start(); //开始
shout(AddRd); //发送读操作器件地址AddRd
Ack();
*(PData+i)=shin(); //调用读数据函数
SCL=0;
NoAck(); //反向应答
Stop(); //停止
}
}
/*****************************开始函数***********************************/
//函数名: Start
//函数功能:发送START状态,定义为当SCL为高时SDA从高到低
//形式参数:无
//返回值:返回时SCL,SDA为低
void Start(void)
{
SDA=1; //升高SDA
SCL=1; //升高SCL
_nop_();_nop_();_nop_();_nop_(); //保持数据建立延迟及周期延迟
SDA=0; //降低SDA
_nop_();_nop_();_nop_();_nop_(); //保持SDA为低,保持时间hold delay
SCL=0; //降低SCL
}
/********************************停止函数*********************************/
//函数名:Stop
//函数功能:发送STOP状态,定义为当SCL为高时SDA从低变高
//形式参数:无
//返回值:返回时SCL,SDA为高
void Stop(void)
{
SDA=0;
_nop_();_nop_(); //保持SCL为低及数据稳定
SCL=1;
_nop_();_nop_();_nop_();_nop_(); //保持建立延迟
SDA=1;
_nop_();_nop_();_nop_();_nop_();
}
/*******************************串行输出数据*****************************/
//函数名:Shout
//函数功能:串行发送一个字节(包括地址和数据)给AT24C**器件,高位在前
//形式参数:待发送的字节Data,调用前SCL,SDA为低,返回时SCL为低。
//返回值:无
void Shout(unsigned char Data)
{
unsigned char BitCounter=8; //设置位计数器
unsigned char temp; //中间变量控制
do
{
temp=Data;
SCL=0; //时钟为低电平
_nop_();_nop_();_nop_();_nop_(); //保持SCL为低
if((temp&0x80)==0x80) SDA=1; //输出一位,如果最高位是1,则输出1到SDA
else SDA=0; //如果最高位是0,则输出0到SDA
SCL=1; //时钟为高电平
temp=Data<<1; //左移一位(高位在前)
Data=temp;
BitCounter--;
} while(BitCounter); //传送下一位
SCL=0;
}
/*******************************串行输入数据******************************/
//函数名:Shin
//函数功能:从AT24C**串行读入一个字节数据,高位在前
//形式参数:调用前SCL为低
//返回值:返回读入的字节,返回时SCL为低
unsigned char Shin(void)
{
unsigned char temp=0;
unsigned char temp1=0;
unsigned char BitCounter=8; //设置位计数器
SDA=1; //使SDA为高,准备读
do {
SCL=0; //降低时钟
_nop_();_nop_();_nop_();_nop_(); //保持SCL为低且使数据稳定
SCL=1; //升高时钟
_nop_();_nop_();_nop_();_nop_(); //保持SCL为高
if(SDA) temp=temp|0x01; //输入一位,如果SDA=1则temp的最低位置1
else temp=temp&0xfe; //否则temp的最低位清0
if(BitCounter-1)
{
temp1=temp<<1; //左移一位(高位在前)
temp=temp1;
}
BitCounter--;
} while(BitCounter); //传送下一位
return(temp); //返回读入的数据
}
//********************************应答**************************************/
//函数名:Ack
//函数功能:检测来自AT24C**器件的ACK应答
//形式参数:无
//返回值:返回ack_bit,为0表示操作成功,否则操作有误
bit Ack(void)
{
bit ack_bit;
SDA=1; //置SDA为高,准备接收ACK应答
_nop_();_nop_();_nop_();_nop_();
SCL=1; //第9个时钟脉冲
_nop_();_nop_();_nop_();_nop_();
ack_bit = SDA; //读入应答
SCL=0;
return(ack_bit); //返回应答标志ack_bit
}
/*******************************反向应答*************************************/
//函数名:NoAck
//函数功能:向AT24C**器件发送NAK反向应答,随时钟输出一个高电平的负应答位,调用前
// SCL为低,返回时SCL为低,SDA为高
//形式参数: 无
//返回值: 无
void NoAck(void)
{
SDA=1;
_nop_();_nop_();_nop_();_nop_();
SCL=1;
_nop_();_nop_();_nop_();_nop_();
SCL=0;
}
/**********************************延时************************************/
//函数名:mDelay
//函数功能:延时函数
//函数形式参数:ms用来控制循环次数,从而控制延时时间长短
//函数返回值: 无
void mDelay(unsigned char ms)
{
unsigned int i;
while(ms--)
{
for(i=0;i<125;i++);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -