找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

帖子
查看: 4490|回復(fù): 14
打印 上一主題 下一主題
收起左側(cè)

求指點:單片機向EEPROM內(nèi)寫入一個數(shù),然后再把他讀出來驗證寫入成功。但結(jié)果是255

  [復(fù)制鏈接]
回帖獎勵 25 黑幣 回復(fù)本帖可獲得 5 黑幣獎勵! 每人限 1 次
跳轉(zhuǎn)到指定樓層
樓主
ID:702446 發(fā)表于 2020-3-15 14:05 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
求大神指點:我想向EEPROM內(nèi)寫入一個數(shù),然后再把他讀出來驗證寫入成功,以此來學(xué)習(xí)IIC通訊協(xié)議的用法。但是讀出來的結(jié)果是255,不管怎么調(diào)試都沒用。哪位高手有邏輯分析儀能幫我看看是哪里出錯了嗎?

單片機源程序如下:
#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)                   //定義 延時函數(shù)
{
uint x,y;
for(x=0;x<100;x++)
         for(y=0;y<z;y++);
}

void delay5us()                  //定義  延時函數(shù)
{
_nop_();
}

void I2Cstart()                 //定義  起始信號函數(shù)
{
SDA=1;
SCL=1;
delay5us();
SDA=0;
delay5us();
}

void I2Cstop()                 //定義  停止信號函數(shù)
{
SCL=0;
SDA=0;
SCL=1;
delay5us();
SDA=1;
delay5us();
}

bit ReadAck()                //定義  主機讀從機應(yīng)答信號函數(shù)
{
SCL=0;
SCL=1;                           
delay5us();
if(SDA)
{                                         //非應(yīng)答
          SCL=0;                         //拉低SCL(據(jù)波形圖)
        return(1);
}
else
{
  SCL=0;
  return(0);
}


}

void SendAck(bit i)          //定義  主機發(fā)送應(yīng)答
{
SCL=0;
if(i)
         SDA=1;
else
         SDA=0;
SCL=1;                                  //SCL拉高,讀取數(shù)據(jù)
delay5us();                  //延時保持數(shù)據(jù)穩(wěn)定
SCL=0;                                  //SCL拉低占用總線繼續(xù)通信
SDA=1;                                  //釋放sda         ,否則主機會一直占用sda
}

void I2cSendByte(uchar DAT)        //定義 寫入數(shù)據(jù)操作邏輯函數(shù)
{
        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;                                    //拉低時鐘總線,繼續(xù)通信
        SDA=1;                                   //釋放數(shù)據(jù)總線,允許其他設(shè)備傳遞數(shù)據(jù)
}

void At24c02write(uchar ADDR,DAT)        //定義  寫入函數(shù)
{
  I2Cstart();                                  //起始信號
  I2cSendByte(At24c02ADDR+I2cWrite);  //發(fā)送從機地址+寫信號
          if(ReadAck())
           AcKFlag=1;           //主機讀應(yīng)答信號:結(jié)果為無應(yīng)答
          else
           AcKFlag=0;           //主機讀應(yīng)答信號:結(jié)果為有應(yīng)答
  I2cSendByte(ADDR);           //調(diào)用寫入數(shù)據(jù)操作邏輯函數(shù):發(fā)送想要寫入的內(nèi)存地址
          if(ReadAck())
           AcKFlag=1;           
          else
           AcKFlag=0;           
  I2cSendByte(DAT);           //調(diào)用寫入數(shù)據(jù)操作邏輯函數(shù):發(fā)送要寫入的數(shù)據(jù)
             if(ReadAck())
           AcKFlag=1;           
          else
           AcKFlag=0;
  I2Cstop();                      //停止信號
}

uchar I2cReadByte()           //讀取從機內(nèi)存數(shù)據(jù)邏輯子函數(shù)
{
uchar i,DAT;
for(i=0;i<8;i++)
         {
          DAT<<=1;
          SCL=0;                   //讀數(shù)據(jù)時SDA由從機控制,主機只要控制scl時序,接收sda上的數(shù)據(jù)即可
          SCL=1;
          if(SDA)
                  DAT|=0x01;
          delay5us();
        }
return(DAT);
}

uchar At24c02Read(uchar ADDR)  //定義  讀出函數(shù)
{
  uchar DAT;
  I2Cstart();                                  //起始信號
  I2cSendByte(At24c02ADDR+I2cWrite);  //發(fā)送從機(EEPROM)地址+寫信號(此處發(fā)寫信號是為了發(fā)送想要讀取的內(nèi)存單元的地址)
          if(ReadAck())
           AcKFlag=1;           //主機讀應(yīng)答信號:結(jié)果為無應(yīng)答
          else
           AcKFlag=0;           //主機讀應(yīng)答信號:結(jié)果為有應(yīng)答
  I2cSendByte(ADDR);           //發(fā)送想要讀的內(nèi)存地址
  ReadAck();                             //主機讀應(yīng)答信號(不管是否應(yīng)答)
  I2Cstart();                   //重復(fù)起始信號
  I2cSendByte(At24c02ADDR+I2cRead);  //發(fā)送從機地址+讀信號
  if(ReadAck())                   //判斷應(yīng)答信號
           AcKFlag=1;           
          else
           AcKFlag=0;
  DAT=I2cReadByte();   //調(diào)用 讀取從機內(nèi)存數(shù)據(jù)邏輯子函數(shù) 讀一個字節(jié)
  SendAck(1);                   //主機發(fā)送應(yīng)答信號:非應(yīng)答(非應(yīng)答函數(shù)內(nèi)包括,占用總線繼續(xù)通信與釋放數(shù)據(jù)總線允許其他設(shè)備調(diào)用的信號,故調(diào)用的子函數(shù)內(nèi)部不必寫
  I2Cstop();                   //發(fā)送停止信號
  return(DAT);                   //返回函數(shù)值
}

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();                           //延時一會,待從機將先前接收的數(shù)據(jù)處理完畢,否則可能會讀取失敗
display(At24c02Read(0x02));
while(1);

}

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏 分享淘帖 頂 踩
回復(fù)

使用道具 舉報

沙發(fā)
ID:235200 發(fā)表于 2020-3-15 17:39 | 只看該作者
讀出是255,證明是數(shù)據(jù)未寫進去,重點檢查寫入程序
回復(fù)

使用道具 舉報

板凳
ID:699855 發(fā)表于 2020-3-16 08:31 | 只看該作者
用示波器看i2c時序?qū)崿F(xiàn)對不對
回復(fù)

使用道具 舉報

地板
ID:709464 發(fā)表于 2020-3-16 17:23 | 只看該作者
可能是讀寫時序沒處理好吧,建議換匯編語言來處理這部分程序,可能更精準些。
回復(fù)

使用道具 舉報

5#
ID:691449 發(fā)表于 2020-3-19 12:52 | 只看該作者
可能是應(yīng)答出了問題
回復(fù)

使用道具 舉報

6#
ID:645890 發(fā)表于 2020-3-19 14:01 | 只看該作者
數(shù)據(jù)超過了?
回復(fù)

使用道具 舉報

7#
ID:466599 發(fā)表于 2020-3-20 09:49 | 只看該作者
這個是時序不對,利用示波器/邏輯分析儀檢查波形,根據(jù)手冊說明調(diào)整時序即可
回復(fù)

使用道具 舉報

8#
ID:743654 發(fā)表于 2020-9-17 13:58 | 只看該作者
有可能是時序有問題,時序必須嚴格對照數(shù)據(jù)手冊
回復(fù)

使用道具 舉報

9#
ID:637608 發(fā)表于 2021-8-13 14:40 | 只看該作者
時序問題,可采用示波器復(fù)現(xiàn)修正
回復(fù)

使用道具 舉報

10#
ID:386001 發(fā)表于 2021-8-14 09:30 | 只看該作者
這個讀寫函數(shù),我自己寫過,你按著時序?qū)懥�,然后用示波器看一下,感覺不是很難的
回復(fù)

使用道具 舉報

11#
ID:805317 發(fā)表于 2021-9-2 09:37 來自觸屏版 | 只看該作者
你把時間多延遲一會,就是寫入數(shù)據(jù)后,延遲時間稍微長一點,再讀取數(shù)據(jù)
回復(fù)

使用道具 舉報

12#
ID:624769 發(fā)表于 2021-9-2 14:54 | 只看該作者
首先IIC必須用上拉電阻,其次,Eeprom的寫保護,要確保關(guān)閉。最后,確認一下設(shè)備地址,是否正確?
回復(fù)

使用道具 舉報

13#
ID:81196 發(fā)表于 2021-9-13 11:48 | 只看該作者
肯定是時序的問題了,
回復(fù)

使用道具 舉報

14#
ID:207030 發(fā)表于 2021-9-13 14:27 | 只看該作者
1、檢查IO口置高置低是否正常,萬用表量一下。
2、檢查IO口的讀是否正常,是否能讀到0   1  電平。
3、單片機如果不是準雙向,需要在讀之前設(shè)置為輸入,讀之后立刻設(shè)置為輸出。
4、還是不行  那就是時序不對  或者延時不對。
回復(fù)

使用道具 舉報

15#
ID:624769 發(fā)表于 2021-9-13 14:36 | 只看該作者
sgd985437 發(fā)表于 2021-9-13 14:27
1、檢查IO口置高置低是否正常,萬用表量一下。
2、檢查IO口的讀是否正常,是否能讀到0   1  電平。
3、單 ...

此帖 樓主 于2020年 3 月 發(fā)的帖子,至今1年半,只有63黑幣。這種僵尸貼,就沒有必要翻出來回復(fù)了吧?而且也不是結(jié)論性的答復(fù),也不會對其他壇友有任何參考價值。
回復(fù)

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機教程網(wǎng)

快速回復(fù) 返回頂部 返回列表