標(biāo)題: 求指點(diǎn):單片機(jī)向EEPROM內(nèi)寫入一個(gè)數(shù),然后再把他讀出來驗(yàn)證寫入成功。但結(jié)果是255 [打印本頁]

作者: Amlee    時(shí)間: 2020-3-15 14:05
標(biāo)題: 求指點(diǎn):單片機(jī)向EEPROM內(nèi)寫入一個(gè)數(shù),然后再把他讀出來驗(yàn)證寫入成功。但結(jié)果是255
求大神指點(diǎn):我想向EEPROM內(nèi)寫入一個(gè)數(shù),然后再把他讀出來驗(yàn)證寫入成功,以此來學(xué)習(xí)IIC通訊協(xié)議的用法。但是讀出來的結(jié)果是255,不管怎么調(diào)試都沒用。哪位高手有邏輯分析儀能幫我看看是哪里出錯(cuò)了嗎?

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

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

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

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

bit ReadAck()                //定義  主機(jī)讀從機(jī)應(yīng)答信號(hào)函數(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)          //定義  主機(jī)發(fā)送應(yīng)答
{
SCL=0;
if(i)
         SDA=1;
else
         SDA=0;
SCL=1;                                  //SCL拉高,讀取數(shù)據(jù)
delay5us();                  //延時(shí)保持?jǐn)?shù)據(jù)穩(wěn)定
SCL=0;                                  //SCL拉低占用總線繼續(xù)通信
SDA=1;                                  //釋放sda         ,否則主機(jī)會(huì)一直占用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;                                    //拉低時(shí)鐘總線,繼續(xù)通信
        SDA=1;                                   //釋放數(shù)據(jù)總線,允許其他設(shè)備傳遞數(shù)據(jù)
}

void At24c02write(uchar ADDR,DAT)        //定義  寫入函數(shù)
{
  I2Cstart();                                  //起始信號(hào)
  I2cSendByte(At24c02ADDR+I2cWrite);  //發(fā)送從機(jī)地址+寫信號(hào)
          if(ReadAck())
           AcKFlag=1;           //主機(jī)讀應(yīng)答信號(hào):結(jié)果為無應(yīng)答
          else
           AcKFlag=0;           //主機(jī)讀應(yīng)答信號(hào):結(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();                      //停止信號(hào)
}

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

uchar At24c02Read(uchar ADDR)  //定義  讀出函數(shù)
{
  uchar DAT;
  I2Cstart();                                  //起始信號(hào)
  I2cSendByte(At24c02ADDR+I2cWrite);  //發(fā)送從機(jī)(EEPROM)地址+寫信號(hào)(此處發(fā)寫信號(hào)是為了發(fā)送想要讀取的內(nèi)存單元的地址)
          if(ReadAck())
           AcKFlag=1;           //主機(jī)讀應(yīng)答信號(hào):結(jié)果為無應(yīng)答
          else
           AcKFlag=0;           //主機(jī)讀應(yīng)答信號(hào):結(jié)果為有應(yīng)答
  I2cSendByte(ADDR);           //發(fā)送想要讀的內(nèi)存地址
  ReadAck();                             //主機(jī)讀應(yīng)答信號(hào)(不管是否應(yīng)答)
  I2Cstart();                   //重復(fù)起始信號(hào)
  I2cSendByte(At24c02ADDR+I2cRead);  //發(fā)送從機(jī)地址+讀信號(hào)
  if(ReadAck())                   //判斷應(yīng)答信號(hào)
           AcKFlag=1;           
          else
           AcKFlag=0;
  DAT=I2cReadByte();   //調(diào)用 讀取從機(jī)內(nèi)存數(shù)據(jù)邏輯子函數(shù) 讀一個(gè)字節(jié)
  SendAck(1);                   //主機(jī)發(fā)送應(yīng)答信號(hào):非應(yīng)答(非應(yīng)答函數(shù)內(nèi)包括,占用總線繼續(xù)通信與釋放數(shù)據(jù)總線允許其他設(shè)備調(diào)用的信號(hào),故調(diào)用的子函數(shù)內(nèi)部不必寫
  I2Cstop();                   //發(fā)送停止信號(hào)
  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í)一會(huì),待從機(jī)將先前接收的數(shù)據(jù)處理完畢,否則可能會(huì)讀取失敗
display(At24c02Read(0x02));
while(1);

}


作者: csmyldl    時(shí)間: 2020-3-15 17:39
讀出是255,證明是數(shù)據(jù)未寫進(jìn)去,重點(diǎn)檢查寫入程序
作者: eastjack    時(shí)間: 2020-3-16 08:31
用示波器看i2c時(shí)序?qū)崿F(xiàn)對(duì)不對(duì)
作者: 3ABC    時(shí)間: 2020-3-16 17:23
可能是讀寫時(shí)序沒處理好吧,建議換匯編語言來處理這部分程序,可能更精準(zhǔn)些。
作者: xianming    時(shí)間: 2020-3-19 12:52
可能是應(yīng)答出了問題
作者: hi毀人不倦    時(shí)間: 2020-3-19 14:01
數(shù)據(jù)超過了?
作者: Kingsely    時(shí)間: 2020-3-20 09:49
這個(gè)是時(shí)序不對(duì),利用示波器/邏輯分析儀檢查波形,根據(jù)手冊(cè)說明調(diào)整時(shí)序即可
作者: cheney03    時(shí)間: 2020-9-17 13:58
有可能是時(shí)序有問題,時(shí)序必須嚴(yán)格對(duì)照數(shù)據(jù)手冊(cè)
作者: 飛天芭蕾    時(shí)間: 2021-8-13 14:40
時(shí)序問題,可采用示波器復(fù)現(xiàn)修正
作者: sustlixin    時(shí)間: 2021-8-14 09:30
這個(gè)讀寫函數(shù),我自己寫過,你按著時(shí)序?qū)懥,然后用示波器看一下,感覺不是很難的
作者: 貴庚子    時(shí)間: 2021-9-2 09:37
你把時(shí)間多延遲一會(huì),就是寫入數(shù)據(jù)后,延遲時(shí)間稍微長一點(diǎn),再讀取數(shù)據(jù)
作者: 188610329    時(shí)間: 2021-9-2 14:54
首先IIC必須用上拉電阻,其次,Eeprom的寫保護(hù),要確保關(guān)閉。最后,確認(rèn)一下設(shè)備地址,是否正確?
作者: shumivan    時(shí)間: 2021-9-13 11:48
肯定是時(shí)序的問題了,
作者: sgd985437    時(shí)間: 2021-9-13 14:27
1、檢查IO口置高置低是否正常,萬用表量一下。
2、檢查IO口的讀是否正常,是否能讀到0   1  電平。
3、單片機(jī)如果不是準(zhǔn)雙向,需要在讀之前設(shè)置為輸入,讀之后立刻設(shè)置為輸出。
4、還是不行  那就是時(shí)序不對(duì)  或者延時(shí)不對(duì)。
作者: 188610329    時(shí)間: 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ù),也不會(huì)對(duì)其他壇友有任何參考價(jià)值。




歡迎光臨 (http://www.torrancerestoration.com/bbs/) Powered by Discuz! X3.1