找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 4574|回复: 14
打印 上一主题 下一主题
收起左侧

求指点:单片机向EEPROM内写入一个数,然后再把他读出来验证写入成功。但结果是255

  [复制链接]
回帖奖励 25 黑币 回复本帖可获得 5 黑币奖励! 每人限 1 次
跳转到指定楼层
楼主
ID:702446 发表于 2020-3-15 14:05 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
求大神指点:我想向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);

}

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:235200 发表于 2020-3-15 17:39 | 只看该作者
读出是255,证明是数据未写进去,重点检查写入程序
回复

使用道具 举报

板凳
ID:699855 发表于 2020-3-16 08:31 | 只看该作者
用示波器看i2c时序实现对不对
回复

使用道具 举报

地板
ID:709464 发表于 2020-3-16 17:23 | 只看该作者
可能是读写时序没处理好吧,建议换汇编语言来处理这部分程序,可能更精准些。
回复

使用道具 举报

5#
ID:691449 发表于 2020-3-19 12:52 | 只看该作者
可能是应答出了问题
回复

使用道具 举报

6#
ID:645890 发表于 2020-3-19 14:01 | 只看该作者
数据超过了?
回复

使用道具 举报

7#
ID:466599 发表于 2020-3-20 09:49 | 只看该作者
这个是时序不对,利用示波器/逻辑分析仪检查波形,根据手册说明调整时序即可
回复

使用道具 举报

8#
ID:743654 发表于 2020-9-17 13:58 | 只看该作者
有可能是时序有问题,时序必须严格对照数据手册
回复

使用道具 举报

9#
ID:637608 发表于 2021-8-13 14:40 | 只看该作者
时序问题,可采用示波器复现修正
回复

使用道具 举报

10#
ID:386001 发表于 2021-8-14 09:30 | 只看该作者
这个读写函数,我自己写过,你按着时序写了,然后用示波器看一下,感觉不是很难的
回复

使用道具 举报

11#
ID:805317 发表于 2021-9-2 09:37 来自触屏版 | 只看该作者
你把时间多延迟一会,就是写入数据后,延迟时间稍微长一点,再读取数据
回复

使用道具 举报

12#
ID:624769 发表于 2021-9-2 14:54 | 只看该作者
首先IIC必须用上拉电阻,其次,Eeprom的写保护,要确保关闭。最后,确认一下设备地址,是否正确?
回复

使用道具 举报

13#
ID:81196 发表于 2021-9-13 11:48 | 只看该作者
肯定是时序的问题了,
回复

使用道具 举报

14#
ID:207030 发表于 2021-9-13 14:27 | 只看该作者
1、检查IO口置高置低是否正常,万用表量一下。
2、检查IO口的读是否正常,是否能读到0   1  电平。
3、单片机如果不是准双向,需要在读之前设置为输入,读之后立刻设置为输出。
4、还是不行  那就是时序不对  或者延时不对。
回复

使用道具 举报

15#
ID:624769 发表于 2021-9-13 14:36 | 只看该作者
sgd985437 发表于 2021-9-13 14:27
1、检查IO口置高置低是否正常,万用表量一下。
2、检查IO口的读是否正常,是否能读到0   1  电平。
3、单 ...

此帖 楼主 于2020年 3 月 发的帖子,至今1年半,只有63黑币。这种僵尸贴,就没有必要翻出来回复了吧?而且也不是结论性的答复,也不会对其他坛友有任何参考价值。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表