标题:
求指点:单片机向EEPROM内写入一个数,然后再把他读出来验证写入成功。但结果是255
[打印本页]
作者:
Amlee
时间:
2020-3-15 14:05
标题:
求指点:单片机向EEPROM内写入一个数,然后再把他读出来验证写入成功。但结果是255
求大神指点:我想向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);
}
作者:
csmyldl
时间:
2020-3-15 17:39
读出是255,证明是数据未写进去,重点检查写入程序
作者:
eastjack
时间:
2020-3-16 08:31
用示波器看i2c时序实现对不对
作者:
3ABC
时间:
2020-3-16 17:23
可能是读写时序没处理好吧,建议换汇编语言来处理这部分程序,可能更精准些。
作者:
xianming
时间:
2020-3-19 12:52
可能是应答出了问题
作者:
hi毁人不倦
时间:
2020-3-19 14:01
数据超过了?
作者:
Kingsely
时间:
2020-3-20 09:49
这个是时序不对,利用示波器/逻辑分析仪检查波形,根据手册说明调整时序即可
作者:
cheney03
时间:
2020-9-17 13:58
有可能是时序有问题,时序必须严格对照数据手册
作者:
飞天芭蕾
时间:
2021-8-13 14:40
时序问题,可采用示波器复现修正
作者:
sustlixin
时间:
2021-8-14 09:30
这个读写函数,我自己写过,你按着时序写了,然后用示波器看一下,感觉不是很难的
作者:
贵庚子
时间:
2021-9-2 09:37
你把时间多延迟一会,就是写入数据后,延迟时间稍微长一点,再读取数据
作者:
188610329
时间:
2021-9-2 14:54
首先IIC必须用上拉电阻,其次,Eeprom的写保护,要确保关闭。最后,确认一下设备地址,是否正确?
作者:
shumivan
时间:
2021-9-13 11:48
肯定是时序的问题了,
作者:
sgd985437
时间:
2021-9-13 14:27
1、检查IO口置高置低是否正常,万用表量一下。
2、检查IO口的读是否正常,是否能读到0 1 电平。
3、单片机如果不是准双向,需要在读之前设置为输入,读之后立刻设置为输出。
4、还是不行 那就是时序不对 或者延时不对。
作者:
188610329
时间:
2021-9-13 14:36
sgd985437 发表于 2021-9-13 14:27
1、检查IO口置高置低是否正常,万用表量一下。
2、检查IO口的读是否正常,是否能读到0 1 电平。
3、单 ...
此帖 楼主 于2020年 3 月 发的帖子,至今1年半,只有63黑币。这种僵尸贴,就没有必要翻出来回复了吧?而且也不是结论性的答复,也不会对其他坛友有任何参考价值。
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1