51单片机 IIC总线 写24C02 问题 看程序 高分悬赏 错误原因。。。。。

#include<reg52.h>#include<INTRINS.H>typedefunsignedcharuint8;typedefunsignedintuint16... #include <reg52.h>
#include <INTRINS.H>
typedef unsigned char uint8;
typedef unsigned int uint16;
typedef unsigned long uint32;
sbit SCL = P1^1;
sbit SDA = P1^2;
sbit WP=P1^0;
uint8 a;
/*****************************************************************************
** 函数名称:Delay
** 功能描述:延时子程序
******************************************************************************/
void Delay(void)
{
_nop_();
_nop_();
_nop_();
_nop_();

}
/*****************************************************************************
** 函数名称:InitI2C
** 功能描述:配置模拟I2C的IO端口
** 可移植性:注意IO口需支持漏开输出
******************************************************************************/
void InitI2C(void)
{
SDA = 1;
SCL = 1;
}
void I2CStart(void)
{
SDA = 1;
Delay(); // 延时子程序
SCL = 1;
Delay();
SDA = 0;
Delay();
SCL = 0;

}
void I2CStop(void)
{
SCL = 0;
Delay();
SDA = 0;
Delay();
SCL = 1;
Delay();
SDA = 1;
Delay();

}
void I2CSend(uint8 byte)
{
uint8 mask;
uint8 i;
uint8 j;

mask = 0x80;
for(i = 0; i < 8; i++)
{
SCL = 0;
Delay();
if((mask & byte) == 0)
{
SDA = 0;
}
else
{
SDA = 1;
}
mask >>= 1;
Delay();
SCL = 1;
Delay();
}

SCL = 0;
SDA = 1;
Delay();
SCL = 1;
j = SDA;
Delay();
SCL = 0;

}

uint8 I2CRead(void)
{
uint8 byte;
uint8 i;

byte = 0;
for(i = 0; i < 8; i++)
{
SCL = 0;
SDA = 1;
Delay();
SCL = 1;
Delay();
byte <<= 1;
if(SDA == 1)
{
byte |= 0x01;
}
Delay();
}
SCL = 0;
SDA = 1;
Delay();
SCL = 1;
Delay();
SCL = 0;
return byte;

}
uint8 I2CReadAck(void)
{
uint8 i;
uint8 byte;

byte = 0;
for(i=0;i<8;i++)
{
SCL = 0;
SDA = 1;
Delay();
SCL = 1;
Delay();
byte <<= 1;
if(SDA==1) {byte |= 0x01;}
Delay();
}
SCL = 0;
Delay();
SDA = 0;
Delay();
SCL = 1;
Delay();
SCL = 0;
return byte;
}
uint8 read_eeprom(uint8 addr)
{
uint8 databyte;
I2CStart();
I2CSend(0xae);
I2CSend(addr);
I2CStart();
I2CSend(0xaf);
databyte = I2CRead();
I2CStop();
return databyte;

}
void write_eeprom(uint8 addr, uint8 databyte)
{
I2CStart();
I2CSend(0xae);
I2CSend(addr);
I2CSend(databyte);
I2CStop();
}
main()
{
WP=0;
InitI2C();
Delay();
write_eeprom(0x10,0x06);
Delay();
Delay();
P2=read_eeprom(0x10);
P0=0xaa;
while(1);
}
展开
 我来答
happyming0809
2011-03-26 · TA获得超过757个赞
知道小有建树答主
回答量:624
采纳率:0%
帮助的人:324万
展开全部
具体我没空看了,我发个程序给你看看

void _24c02menu(void) //处理I2C数据时用的函数
{
unsigned char tmp,tmp2;
P2=0; //数码管显示清0
l_key=0xfe; //进入存储器处理程序先读取0地址的数据
while (1){
if(l_key==0x0c){ //如果按下*号键退出循环,即退出回到主函数
l_key=0xff;
break;
}
switch(l_key){ //扫描键盘做相应处理
case 0x0a: //按下0X0A键,我们可将它理解为上翻键
l_key=0xff;
if(l_address>0){
l_address--; //将地址减1
l_key=0xfe; //读取数据
}
break;
case 0x0b: //按下0X0A键,我们可将它理解为下翻键
l_key=0xff;
if(l_address<255){
l_address++; //将地址加1
l_key=0xfe; ////读取数据
}
break;
case 0x0e: //如果按下#号键,调用写存储器函数
l_key=0xff;
_24c02wdate(tmp);
l_key=0xfe;
break;
case 0xfe: //此按值是在键盘是没有的,我们有内部给他增加做为读数据处理
l_key=0xff;
I2C_start(); //I2C读数据的开始,到下面的结束是读一地址的整个过程,
I2C_write(W24C02); //向I2C总线发出读取24C02的地址
I2C_ACK(0); //下面就得你们自己结合I2C串口协议进行,先看看24C02数据手册是怎么讲I2C协议的
I2C_write(l_address);//先写入地址,
I2C_ACK(1);
I2C_stop();

I2C_start(); //再开始读取数据
I2C_write(R24C02);
I2C_ACK(0);
tmp=I2C_read();
I2C_ACK(1);
I2C_stop(); //读取一个地址的数据结束
l_tmpdate[0]=l_address/16; //数码管前两位显示地址(以16进制显示)
l_tmpdate[1]=l_address%16; //将地址变量分开用两位数据
l_tmpdate[3]=tmp/100; //后面用10进制数显示数据,中间用"-"隔开,数组l_tmpdate[2]
tmp2=tmp%100; //8位二进制最大十进制为255,所以我们也将它分开三位显示
l_tmpdate[4]=tmp2/10;
l_tmpdate[5]=tmp2%10;
break;
}
display(l_tmpdate,6);
}
}
void _24c02wdate(unsigned char tmp)//对24C02的写数据处理函数
{
unsigned char tmp2=0;
while(1){
if (l_key==0x0c){ //如果按下*号键退出循环,即退出回到上一极函数
l_key=0xff;
break;
}
if(l_key==0x0e){ //如果按下#号键,将更改的数据写入24C02存储器
l_key=0xff;
I2C_start(); //下面是写一地址数据的过程
I2C_write(W24C02); //先向总线发出写24C02的地址
I2C_ACK(0);
I2C_write(l_address); //写入地址
I2C_ACK(0);
I2C_write(tmp); //然后写入数据
I2C_ACK(1);
I2C_stop();
break;
}
switch(l_key){ //下面是对数据的处理
case 0x01: //如果按下1键,数据百位加1
l_key=0xff;
if(tmp<155)
tmp+=100;
break;
case 0x02: //如果按下2键,数据十位加1
l_key=0xff;
if(tmp<245)
tmp+=10;
break;
case 0x03: //如果按下3键,数据个位加1
l_key=0xff;
if(tmp<255)
tmp++;
break;
case 0x04: //如果按下4键,数据百位减1
l_key=0xff;
if(tmp>=100)
tmp-=100;
break;
case 0x05: //如果按下5键,数据十位减1
l_key=0xff;
if(tmp>=10)
tmp-=10;
break;
case 0x06: //如果按下6键,数据个位减1
l_key=0xff;
if(tmp>0)
tmp--;
break;
}
l_tmpdate[3]=tmp/100; //地址不变我们不用修改,更改数据显示即可
tmp2=tmp%100;
l_tmpdate[4]=tmp2/10;
l_tmpdate[5]=tmp2%10;
display(l_tmpdate,6);
}
}
void I2C_write(unsigned char tmp)//I2C写入一个8位二进制数,高位在前低位在后
{
unsigned char i;
for(i=0;i<8;i++){
SCL=0;
_nop_();
_nop_();
_nop_();
SDA=(bit)(tmp&0x80);
tmp<<=1;
_nop_();_nop_();_nop_();_nop_();_nop_();
SCL=1;
_nop_();_nop_();_nop_();_nop_();_nop_();
}
SCL=0;
}
unsigned char I2C_read(void)////I2C读取一个8位二进制数,也是高位在前低位在后
{
unsigned char i,tmp;
tmp=0;
for(i=0;i<8;i++){
SCL=0;
_nop_();
_nop_();
_nop_(); //加入空指令增加稳定性,这关系到频率问题
SDA=1;
_nop_();_nop_();_nop_();_nop_();_nop_();
SCL=1;
_nop_();_nop_();_nop_();_nop_();_nop_();
tmp<<=1;
if(SDA==1)
tmp++;
}
SCL=0;
return tmp;

}
void I2C_ACK(bit tmp) //根据tmp的1、0来决定应答信号
{
SDA=tmp;
_nop_();_nop_();_nop_();_nop_();_nop_();
SCL=1;
_nop_();_nop_();_nop_();_nop_();_nop_();
SCL=0;
}
void I2C_start(void) //看看I2C开始的波形,再对应SDA、SCL的输出
{
SDA=1;
_nop_();
SCL=1;
_nop_();
SDA=0;
_nop_();
SCL=0;
_nop_();
}

/*********/
void I2C_stop(void) //I2C结束
{
SDA=0;
_nop_();
SCL=1;
_nop_();
SDA=1;
_nop_();
SCL=0;
_nop_();
}
mscyhll
2011-03-26 · TA获得超过643个赞
知道小有建树答主
回答量:494
采纳率:0%
帮助的人:497万
展开全部
你的程序编译是通过的,看你的原理图,指出两点:
1.你的地址端接的是高电平,读写时是不是和0xae,0xaf地址码对应,请请查看使用说明解决。
2.SCL、SDA需要接上上电阻的,不然高电平上不去。
希望对你有帮助!
本回答被提问者采纳
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
推荐律师服务: 若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询

为你推荐:

下载百度知道APP,抢鲜体验
使用百度知道APP,立即抢鲜体验。你的手机镜头里或许有别人想知道的答案。
扫描二维码下载
×

类别

我们会通过消息、邮箱等方式尽快将举报结果通知您。

说明

0/200

提交
取消

辅 助

模 式