C51: 2块 24C02 的读写
2016-10-14 来源:eefocus
向U2写入12345,向U3写入67890,再分别读出,
在 LCD1602 显示 */
#include
#include
//变量声明
#define uchar unsigned char
#define uint unsigned int
//延时 1ms
void delayms()
{
uchar i;
for(i=0;i<250;i++);
for(i=0;i<80;i++);
}
void delaynms(uint s)
{
uint tem;
for(tem=0;tem
{
delayms();
}
}
//LCD 忙碌查询
sbit LCDbusy=P1^7;
//LCD 操作位 设置
sbit RS=P3^2;
sbit RW=P3^1;
sbit E=P3^0;
sbit BF=P1^7;
//------ LCD 程序 ----
//读LCD 状态
uchar BusyTest()
{
bit result;
//读LCD 状态
RS=0;
RW=1;
E=1;
_nop_();
_nop_();
_nop_();
//指令
result=BF;
_nop_();
_nop_();
_nop_();
E=0;
return result;
}
//写 LCD 指令
void WriteInstruction(uchar instruction)
{
//LCD 忙碌,等待。
while(BusyTest()==1);
//写指令
RS=0;
RW=0;
E=0;
_nop_(); //要求
_nop_();
_nop_();
//指令
P1=instruction;
_nop_();
_nop_();
_nop_();
E=1;
_nop_();
_nop_();
_nop_();
E=0;
}
//初始化 LCD
void InitLCD()
{
delaynms(15);
WriteInstruction(0x38);// 显示模式设置
delaynms(5);
WriteInstruction(0x38);
delaynms(5);
WriteInstruction(0x38);
delaynms(5);
WriteInstruction(0x0d);//显示模式设置: 开显示,不显示光标,闪烁光标
delaynms(5);
WriteInstruction(0x06);//显示模式设置: 光标右移,文字不移动。
delaynms(5);
}
//写LCD 数据
void WriteData(uchar d)
{
//LCD 忙碌,等待。
while(BusyTest()==1);
//写数据
RS=1;
RW=0;
E=0;
_nop_();
_nop_();
_nop_();
//指令
P1=d;
_nop_();
_nop_();
_nop_();
E=1;
_nop_();
_nop_();
_nop_();
E=0;
}
//写地址,属于写指令
void WriteAdd(uchar ad)
{
uchar addr=ad+0x80;
WriteInstruction(addr);
}
//--- 24C02 ---
sbit SDA=P2^0; //数据总线SDA位定义在P2^0引脚
sbit SCL=P2^1; //时钟总线SCL位定义在P2^1引脚
uchar wdeviceadd; //定义写入器件,寻址地址
uchar rdeviceadd; // 定义读出器件,寻址地址
//函数功能:开始数据传送
void start()
{
SDA = 1; //SDA初始化为高电平“1”
SCL = 1; //开始数据传送时,要求SCL为高电平“1”
_nop_(); //等待一个机器周期
_nop_(); //等待一个机器周期
_nop_(); //等待一个机器周期
_nop_(); //等待一个机器周期
SDA = 0; //SDA的下降沿被认为是开始信号
_nop_(); //等待一个机器周期
_nop_(); //等待一个机器周期
_nop_(); //等待一个机器周期
_nop_(); //等待一个机器周期
SCL = 0; //SCL为低电平时,SDA上数据才允许变化(即允许以后的数据传递)
}
//函数功能:结束数据传送
void stop()
{
SDA = 0; //SDA初始化为低电平“0” _n
SCL = 1; //结束数据传送时,要求SCL为高电平“1”
_nop_(); //等待一个机器周期
_nop_(); //等待一个机器周期
_nop_(); //等待一个机器周期
_nop_(); //等待一个机器周期
SDA = 1; //SDA的上升沿被认为是结束信号
_nop_(); //等待一个机器周期
_nop_(); //等待一个机器周期
_nop_(); //等待一个机器周期
_nop_(); //等待一个机器周期
SDA=0;
SCL=0;
}
//应答检查
bit testack()
{
bit ack_bit;
SDA = 1; // 发送设备(主机)应在时钟脉冲的高电平期间(SCL=1)释放SDA线,
//以让SDA线转由接收设备(AT24Cxx)控制
_nop_(); //等待一个机器周期
_nop_(); //等待一个机器周期
SCL = 1; //根据上述规定,SCL应为高电平
_nop_(); //等待一个机器周期
_nop_(); //等待一个机器周期
_nop_(); //等待一个机器周期
_nop_(); //等待一个机器周期
ack_bit = SDA; //接受设备(AT24Cxx)向SDA送低电平,表示已经接收到一个字节
//若送高电平,表示没有接收到,传送异常
SCL = 0; //SCL为低电平时,SDA上数据才允许变化(即允许以后的数据传递)
return ack_bit;
}
//应答
void ack()
{
SDA=0;
_nop_();
_nop_();
SCL = 1;
_nop_();
_nop_();
_nop_();
_nop_();
SCL = 0;
_nop_();
_nop_();
SDA=1;
_nop_();
_nop_();
}
//非应答
void noack()
{
SDA=1;
_nop_();
_nop_();
SCL = 1;
_nop_();
_nop_();
_nop_();
_nop_();
SCL = 0;
_nop_();
_nop_();
}
//函数功能:从AT24Cxx读取一个字节
unsigned char ReadData()
{
uchar i;
uchar x; //储存从AT24Cxx中读出的数据
for(i = 0; i < 8; i++)
{
SCL = 1; //SCL置为高电平
x<<=1; //将x中的各二进位向左移一位
x|=(unsigned char)SDA; //将SDA上的数据通过按位“或“运算存入x中
SCL = 0; //在SCL的下降沿读出数据
}
return(x); //将读取的数据返回
}
//写入一个字节
void WriteCurrent(unsigned char y)
{
unsigned char i;
for(i = 0; i < 8; i++) // 循环移入8个位
{
SDA = (bit)(y&0x80); //通过按位“与”运算将最高位数据送到S
//因为传送时高位在前,低位在后
_nop_(); //等待一个机器周期
SCL = 1; //在SCL的上升沿将数据写入AT24Cxx
_nop_(); //等待一个机器周期
_nop_(); //等待一个机器周期
SCL = 0; //将SCL重新置为低电平,以在SCL线形成传送数据所需的8个脉冲
y <<= 1; //将y中的各二进位向左移一位
}
}
//在器件指定地址 写 n 个字节
//参数(数据地址,器件内存地址 ,写字节数)
void writeI2C(uchar device,uchar *wdata,uchar add,uchar bytes)
{
uchar wdeviceadd=device;
uchar rdeviceadd=device+1;
start(); //开始数据传递
WriteCurrent(wdeviceadd); //选择要操作的AT24Cxx芯片,并告知要对其写入数据
testack();
WriteCurrent(add); //写入指定地址0x36
testack();
//进入循环
for(;bytes!=0;bytes--)
{
WriteCurrent(*wdata); //向当前地址(上面指定的地址)写入数据 0x00
testack(); //应答检查
wdata++;
}
stop(); //停止数据传递
delaynms(4);
}
//在器件指定地址 读出 n 个字节
//参数(接收读出数据缓存地址,读数据器件内存地址 ,读出字节数)
void readI2C(uchar device,uchar *rdata,uchar add,uchar bytes)
{
uchar wdeviceadd=device;
uchar rdeviceadd=device+1;
/*读出数据
流程:
启动-写芯片寻址-应答检查-写数据首址-应答检查- 进入读数据程序段 */
start();
WriteCurrent(wdeviceadd); //选择要操作的AT24Cxx芯片,并告知要对其写入数据
testack();
WriteCurrent(add); //读出数据地址
testack();
/*读数据程序段流程:
启动-写芯片寻址-应答检查- 进入读数据程序段*/
start();
WriteCurrent(rdeviceadd); //选择要操作的AT24Cxx芯片,并告知要读其数据
testack();
/*读数据程序段
条件判断-读数据-应答-指针操作-循环,
最后一个字节退出循环-读最后一个字节-非应答-停止 */
while(bytes!=1)
{
*rdata=ReadData();
ack(); //应答
rdata++;
bytes--;
}
*rdata=ReadData(); //读出最后一个字节
noack(); //最后一个数据 非应答
stop(); //停止数据传递
}
//main 程序
void main()
{
//将此字符串存入24C02,再读出。
uchar str2[5]='12345' ;
uchar str3[5]='67890';
uchar *p;
//读出缓存
uchar readbuf2[10];
uchar readbuf3[10];
//U3 定义器件地址
uchar U3add=0xa0; //写入器件,寻址地址
//U2 定义器件地址
uchar U2add=0xa2; //写入器件,寻址地址
//U2 写入str2
writeI2C(U2add,str2,0x00,5);
//U3 写入str3
writeI2C(U3add,str3,0x00,5);
//
//读出U2
readI2C(U2add,readbuf2,0x00,5);
//初始化LCD
InitLCD();
WriteAdd(0x00);
//写数据
p=readbuf2;
while(*p!='\0')
{
WriteData(*p);
p++;
}
delaynms(1000);
//读出U3
readI2C(U3add,readbuf3,0x00,5);
p=readbuf3;
while(*p!='\0')
{
WriteData(*p);
p++;
}
delaynms(1000);
//
}