51单片机 Keil编译器
普中科技开发板HC6800-ES V2.0
我按照文档的时序很快写了代码,但是结果一直出不来,最后发现是延时设置的不够,这个延时虽然官方说EEPROM(24C02)的延时都是纳秒和微秒级别的。但是实际上更大一点。
详细的步骤就代码里注释说明吧
#include <reg51.h>
#include <intrins.h>
sbit scl=P2^1;
sbit sda=P2^0;
void start();
void init();
void write(unsigned char);
void respons();
void end();
unsigned char read();
void delay(){
unsigned char i,j;
for(i=10;i>0;i--)
for(j=2000;j>0;j--);
}
void main(){
//向EEPROM写数据
//1.初始化
//将SCL时钟线和SDA数据线都设置为1,为了发出起始信号做准备
//同样,每次信号发送结束后终止信号也将SCL和SDA置1
//为下次发送/接收数据做准备
init();
//2.起始信号
//条件:SCL=1时,SDA有一个由1->0的变化后 判断为起始信号
//在这之前init()已经初始化SCL,SDA为1
start();
//3.写入器件地址
//目的:寻找需要的器件
//在SDA和SCL线上并联挂载了好几个器件,EEPROM有固定的前四位地址1010
//后三位地址是根据A0,A1,A2物理接线决定的
//写完地址后要向器件发送是写/读的命令 发送0/1
//因为我们还要写后续内容所以写0
//所以一共是八位数据 1010 000 0
write(0xa0);
//4.写字节地址
//告诉EEPROM要向字节地址0x01写数据
//24C02有256个字节,这里选择第一个字节
//如果要连续写入多个字节 要对地址翻页 这里不详讲
write(1);
//5.写入数据
//10101010
write(0x55);
//6.结束信号
//条件:SCL=1时,SDA有一个由0->1的变化后 判断为结束信号
//结束信号之前,SCL由上个操作已经置0
//只需要在SCL=1前,令SDA=0 在SCL=1后,SDA=1 就完成了结束信号
end();
//至此,写操作完成了
//两个信号开始之前 必须有足够的延时,官方至少4微秒 实际可能更高
delay();
//从EEPROM读数据
//1.起始信号
start();
//2.写入器件地址
write(0xa0);
//3.告诉EEPROM要从字节地址0x01读取数据
write(1);
//4.起始信号
//注:从写操作->读操作 要重新发起始信号
start();
//EEPROM固定前四位地址1010
//后三位地址是根据A0,A1,A2物理接线决定的
//向器件发送是写/读的命令 发送0/1
//
write(0xa1);
//6.把读出来的值赋给需要的变量
P2=read();
//7.结束信号
end();
while(1);
}
void end(){
sda=0;
delay();
scl=1;
delay();
sda=1;
delay();
}
void start(){
sda=1;
delay();
scl=1;
delay();
sda=0;
delay();
scl=0;
delay();
}
void init(){
sda=1;
scl=1;
}
void write(unsigned char cha){
unsigned char i;
for(i=0;i<8;i++){
scl=0;
delay();
cha=cha<<1;
sda=CY;//左移一位后,高位的cha进入了寄存器的CY
delay();
scl=1;
delay();
}
scl=0;
delay();
//应答信号
sda=1;
delay();
scl=1;
delay();
i=0;
while((sda==1)&&(i<250)){i++;}
scl=0;
delay();
}
unsigned char read(){
unsigned char a=0,dat=0;
sda=1;//先把上个操作后的SDA重新置1打开
delay();
for(a=0;a<8;a++)
{
scl=1;
delay();
dat<<=1;//左移一位低位置0
dat|=sda;//或运算 相当于把SDA上的数据赋值给dat的低位
Delay10us();
scl=0;
delay();
}
return dat;
}