IIC协议——向EEPROM进行读写操作

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;		
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值