求大神指点:我想向EEPROM内写入一个数,然后再把他读出来验证写入成功,以此来学习IIC通讯协议的用法。但是读出来的结果是255,不管怎么调试都没用。哪位高手有逻辑分析仪能帮我看看是哪里出错了吗?
单片机源程序如下:
#include<reg52.h>
#include<intrins.h>
#define uint unsigned int
#define uchar unsigned char
#define At24c02ADDR 0xa0 //At24c02EEPROM地址宏定义
#define I2cWrite 0
#define I2cRead 1
sbit SCL=P2^1;
sbit SDA=P2^0;
sbit dula=P2^6;
sbit wela=P2^7;
uchar code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d, //编码表
0x7d,0x07,0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71,0x00 };
bit AcKFlag;
uchar bai,shi,ge;
void delay(uint z) //定义 延时函数
{
uint x,y;
for(x=0;x<100;x++)
for(y=0;y<z;y++);
}
void delay5us() //定义 延时函数
{
_nop_();
}
void I2Cstart() //定义 起始信号函数
{
SDA=1;
SCL=1;
delay5us();
SDA=0;
delay5us();
}
void I2Cstop() //定义 停止信号函数
{
SCL=0;
SDA=0;
SCL=1;
delay5us();
SDA=1;
delay5us();
}
bit ReadAck() //定义 主机读从机应答信号函数
{
SCL=0;
SCL=1;
delay5us();
if(SDA)
{ //非应答
SCL=0; //拉低SCL(据波形图)
return(1);
}
else
{
SCL=0;
return(0);
}
}
void SendAck(bit i) //定义 主机发送应答
{
SCL=0;
if(i)
SDA=1;
else
SDA=0;
SCL=1; //SCL拉高,读取数据
delay5us(); //延时保持数据稳定
SCL=0; //SCL拉低占用总线继续通信
SDA=1; //释放sda ,否则主机会一直占用sda
}
void I2cSendByte(uchar DAT) //定义 写入数据操作逻辑函数
{
uchar i;
for(i=0;i<8;i++)
{
SCL=0;
delay5us();
if(DAT&0x80)
SDA=1;
else
SDA=0;
SCL=1;
delay5us();
DAT<<=1;
}
SCL=0; //拉低时钟总线,继续通信
SDA=1; //释放数据总线,允许其他设备传递数据
}
void At24c02write(uchar ADDR,DAT) //定义 写入函数
{
I2Cstart(); //起始信号
I2cSendByte(At24c02ADDR+I2cWrite); //发送从机地址+写信号
if(ReadAck())
AcKFlag=1; //主机读应答信号:结果为无应答
else
AcKFlag=0; //主机读应答信号:结果为有应答
I2cSendByte(ADDR); //调用写入数据操作逻辑函数:发送想要写入的内存地址
if(ReadAck())
AcKFlag=1;
else
AcKFlag=0;
I2cSendByte(DAT); //调用写入数据操作逻辑函数:发送要写入的数据
if(ReadAck())
AcKFlag=1;
else
AcKFlag=0;
I2Cstop(); //停止信号
}
uchar I2cReadByte() //读取从机内存数据逻辑子函数
{
uchar i,DAT;
for(i=0;i<8;i++)
{
DAT<<=1;
SCL=0; //读数据时SDA由从机控制,主机只要控制scl时序,接收sda上的数据即可
SCL=1;
if(SDA)
DAT|=0x01;
delay5us();
}
return(DAT);
}
uchar At24c02Read(uchar ADDR) //定义 读出函数
{
uchar DAT;
I2Cstart(); //起始信号
I2cSendByte(At24c02ADDR+I2cWrite); //发送从机(EEPROM)地址+写信号(此处发写信号是为了发送想要读取的内存单元的地址)
if(ReadAck())
AcKFlag=1; //主机读应答信号:结果为无应答
else
AcKFlag=0; //主机读应答信号:结果为有应答
I2cSendByte(ADDR); //发送想要读的内存地址
ReadAck(); //主机读应答信号(不管是否应答)
I2Cstart(); //重复起始信号
I2cSendByte(At24c02ADDR+I2cRead); //发送从机地址+读信号
if(ReadAck()) //判断应答信号
AcKFlag=1;
else
AcKFlag=0;
DAT=I2cReadByte(); //调用 读取从机内存数据逻辑子函数 读一个字节
SendAck(1); //主机发送应答信号:非应答(非应答函数内包括,占用总线继续通信与释放数据总线允许其他设备调用的信号,故调用的子函数内部不必写
I2Cstop(); //发送停止信号
return(DAT); //返回函数值
}
void display(uchar num)
{
bai=num/100;
shi=num%100/10;
ge=num%10;
while(1)
{
wela=1;
P0=0xdf;
wela=0;
dula=1;
P0=table[bai];
dula=0;
P0=0xff;
delay(3);
dula=1;
P0=table[shi];
dula=0;
P0=0xff;
wela=1;
P0=0xbf;
wela=0;
delay(3);
dula=1;
P0=table[ge];
dula=0;
P0=0xff;
wela=1;
P0=0x7f;
wela=0;
delay(3);
}
}
void main()
{
At24c02write(0x02,6);
delay5us();
delay5us(); //延时一会,待从机将先前接收的数据处理完毕,否则可能会读取失败
display(At24c02Read(0x02));
while(1);
}
|