1. 單片機的外接eeprom是不是靠E0 E1 和 E2 上所加的電壓確定地址的
呵呵,EEPROM的選中確實是靠E2、E1、E0所加電壓來確定其片選信號的。應該沒有問題了吧。
2. 51單片接的外接存儲器EEPROM的地址究竟怎麼用
E0,E1,E2是EEPROM的片選地址(這個3個管腳都有效的話,非NC)。當E0接Vcc時,其他兩個接地,那麼發信號start+1010_001_0/1就可以訪問該EEPROM(1010:為EEPROM的通用器件地址;001:為E2、E1、E0的狀態;0:對應寫命令,1:對應讀命令);若都接Vcc,發start+1010_111_0/1;以此類推。
EEPROM的數據地址是接著寫命令後發。
希望對你有所幫助!
3. 51單片機I2C匯流排的問題。為什麼寫不進到外部eeprom啊
ead_byte()中第一個SCL=0:表示讓對方輸入數據;( I2C匯流排是SCL=0時從設備輸出數據,SCL=1時主設備接收數據。)
第一個SDA=1:表示釋放數據線,這樣對方發數據到匯流排上,因為在SDA=0時,會線與,所以對方發不了數據。
write_byte中的「SCL = 0; delay(1); SDA = 1; delay(1); 」和read_byte()中一個意思。只是這里write_byte之後要接收應答信號。
可參考下面的資料
I2C匯流排信號時序分析
鐵電存儲器 FM24C16G(I2C介面) 數據手冊
時鍾晶元 DS3231(I2C介面) 數據手冊
4. 51單片機都有eeprom嗎
51單片機內部程序存儲器五花八門:
1、內部沒有程序存儲器如:8031
2、內部有EPROM(可擦除ROM)如:8751
3、內部有EEPROM(電可擦除ROM)如:AT89C51
4、內部有FLASHROM(可以在線編程ISP)如:STC、AT89S51等等。
5. 51單片機通過I2C匯流排操作EEPROM
把Display();用大括弧括住試一試
另外要確定從EEPROM讀取的數值dat是否在0-16范圍內,因表格內只有17個代碼,超過此范圍是顯示不出來的
還有LSD=LEDDATA[DisplayData[i]];//發送段碼
你獲得的數據只有DisplayData[0],那麼DisplayData[i]其它數據從何而來,是0嗎?也許只是想先試一試能否點亮一個數碼管
6. 51單片機內部EEPROM使用求教
不知道你用的是哪款單片機,你可以看單片機的數據手冊,應該會有詳細到操作時序的介紹
針對STC15F4K系列單片機EEPROM使用實例如下:
單位元組操作,串口發送
#include"reg51.h"
#include"intrins.h"
typedefunsignedcharBYTE;
typedefunsignedintWORD;
//-----------------------------------------------
sfrP1M1=0x91;//PxM1.n,PxM0.n=00--->Standard,01--->push-pull
sfrP1M0=0x92;//=10--->pureinput,11--->opendrain
sfrP0M1=0x93;
sfrP0M0=0x94;
sfrP2M1=0x95;
sfrP2M0=0x96;
sfrP3M1=0xB1;
sfrP3M0=0xB2;
sfrP4M1=0xB3;
sfrP4M0=0xB4;
sfrP5M1=0xC9;
sfrP5M0=0xCA;
sfrP6M1=0xCB;
sfrP6M0=0xCC;
sfrP7M1=0xE1;
sfrP7M0=0xE2;
sfrIAP_DATA=0xC2;//IAP數據寄存器
sfrIAP_ADDRH=0xC3;//IAP地址寄存器高位元組
sfrIAP_ADDRL=0xC4;//IAP地址寄存器低位元組
sfrIAP_CMD=0xC5;//IAP命令寄存器
sfrIAP_TRIG=0xC6;//IAP命令觸發寄存器
sfrIAP_CONTR=0xC7;//IAP控制寄存器
#defineCMD_IDLE0//空閑模式
#defineCMD_READ1//IAP位元組讀命令
#defineCMD_PROGRAM2//IAP位元組編程命令
#defineCMD_ERASE3//IAP扇區擦除命令
#defineURMD0//0:使用定時器2作為波特率發生器
//1:使用定時器1的模式0(16位自動重載模式)作為波特率發生器
//2:使用定時器1的模式2(8位自動重載模式)作為波特率發生器
sfrT2H=0xd6;//定時器2高8位
sfrT2L=0xd7;//定時器2低8位
sfrAUXR=0x8e;//輔助寄存器
//#defineENABLE_IAP0x80//ifSYSCLK<30MHz
//#defineENABLE_IAP0x81//ifSYSCLK<24MHz
#defineENABLE_IAP0x82//ifSYSCLK<20MHz
//#defineENABLE_IAP0x83//ifSYSCLK<12MHz
//#defineENABLE_IAP0x84//ifSYSCLK<6MHz
//#defineENABLE_IAP0x85//ifSYSCLK<3MHz
//#defineENABLE_IAP0x86//ifSYSCLK<2MHz
//#defineENABLE_IAP0x87//ifSYSCLK<1MHz
//測試地址
#defineIAP_ADDRESS0x0400
voidDelay(BYTEn);
voidIapIdle();
BYTEIapReadByte(WORDaddr);
voidIapProgramByte(WORDaddr,BYTEdat);
voidIapEraseSector(WORDaddr);
voidInitUart();
BYTESendData(BYTEdat);
voidmain()
{
WORDi;
P0M0=0x00;
P0M1=0x00;
P1M0=0x00;
P1M1=0x00;
P2M0=0x00;
P2M1=0x00;
P3M0=0x00;
P3M1=0x00;
P4M0=0x00;
P4M1=0x00;
P5M0=0x00;
P5M1=0x00;
P6M0=0x00;
P6M1=0x00;
P7M0=0x00;
P7M1=0x00;
P1=0xfe;//1111,1110系統OK
InitUart();//初始化串口
Delay(10);//延時
IapEraseSector(IAP_ADDRESS);//扇區擦除
for(i=0;i<512;i++)//檢測是否擦除成功(全FF檢測)
{
if(SendData(IapReadByte(IAP_ADDRESS+i))!=0xff)
gotoError;//如果出錯,則退出
}
P1=0xfc;//1111,1100擦除成功
Delay(10);//延時
for(i=0;i<512;i++)//編程512位元組
{
IapProgramByte(IAP_ADDRESS+i,(BYTE)i);
}
P1=0xf8;//1111,1000編程完成
Delay(10);//延時
for(i=0;i<512;i++)//校驗512位元組
{
if(SendData(IapReadByte(IAP_ADDRESS+i))!=(BYTE)i)
gotoError;//如果校驗錯誤,則退出
}
P1=0xf0;//1111,0000測試完成
while(1);
Error:
P1&=0x7f;//0xxx,xxxxIAP操作失敗
while(1);
}
/*----------------------------
軟體延時
----------------------------*/
voidDelay(BYTEn)
{
WORDx;
while(n--)
{
x=0;
while(++x);
}
}
/*----------------------------
關閉IAP
----------------------------*/
voidIapIdle()
{
IAP_CONTR=0;//關閉IAP功能
IAP_CMD=0;//清除命令寄存器
IAP_TRIG=0;//清除觸發寄存器
IAP_ADDRH=0x80;//將地址設置到非IAP區域
IAP_ADDRL=0;
}
/*----------------------------
從ISP/IAP/EEPROM區域讀取一位元組
----------------------------*/
BYTEIapReadByte(WORDaddr)
{
BYTEdat;//數據緩沖區
IAP_CONTR=ENABLE_IAP;//使能IAP
IAP_CMD=CMD_READ;//設置IAP命令
IAP_ADDRL=addr;//設置IAP低地址
IAP_ADDRH=addr>>8;//設置IAP高地址
IAP_TRIG=0x5a;//寫觸發命令(0x5a)
IAP_TRIG=0xa5;//寫觸發命令(0xa5)
_nop_();//等待ISP/IAP/EEPROM操作完成
dat=IAP_DATA;//讀ISP/IAP/EEPROM數據
IapIdle();//關閉IAP功能
returndat;//返回
}
/*----------------------------
寫一位元組數據到ISP/IAP/EEPROM區域
----------------------------*/
voidIapProgramByte(WORDaddr,BYTEdat)
{
IAP_CONTR=ENABLE_IAP;//使能IAP
IAP_CMD=CMD_PROGRAM;//設置IAP命令
IAP_ADDRL=addr;//設置IAP低地址
IAP_ADDRH=addr>>8;//設置IAP高地址
IAP_DATA=dat;//寫ISP/IAP/EEPROM數據
IAP_TRIG=0x5a;//寫觸發命令(0x5a)
IAP_TRIG=0xa5;//寫觸發命令(0xa5)
_nop_();//等待ISP/IAP/EEPROM操作完成
IapIdle();
}
/*----------------------------
扇區擦除
----------------------------*/
voidIapEraseSector(WORDaddr)
{
IAP_CONTR=ENABLE_IAP;//使能IAP
IAP_CMD=CMD_ERASE;//設置IAP命令
IAP_ADDRL=addr;//設置IAP低地址
IAP_ADDRH=addr>>8;//設置IAP高地址
IAP_TRIG=0x5a;//寫觸發命令(0x5a)
IAP_TRIG=0xa5;//寫觸發命令(0xa5)
_nop_();//等待ISP/IAP/EEPROM操作完成
IapIdle();
}
/*----------------------------
初始化串口
----------------------------*/
voidInitUart()
{
SCON=0x5a;//設置串口為8位可變波特率
#ifURMD==0
T2L=0xd8;//設置波特率重裝值
T2H=0xff;//115200bps(65536-18432000/4/115200)
AUXR=0x14;//T2為1T模式,並啟動定時器2
AUXR|=0x01;//選擇定時器2為串口1的波特率發生器
#elifURMD==1
AUXR=0x40;//定時器1為1T模式
TMOD=0x00;//定時器1為模式0(16位自動重載)
TL1=0xd8;//設置波特率重裝值
TH1=0xff;//115200bps(65536-18432000/4/115200)
TR1=1;//定時器1開始啟動
#else
TMOD=0x20;//設置定時器1為8位自動重裝載模式
AUXR=0x40;//定時器1為1T模式
TH1=TL1=0xfb;//115200bps(256-18432000/32/115200)
TR1=1;
#endif
}
/*----------------------------
發送串口數據
----------------------------*/
BYTESendData(BYTEdat)
{
while(!TI);//等待前一個數據發送完成
TI=0;//清除發送標志
SBUF=dat;//發送當前數據
returndat;
}
7. 關於單片機EEPROM存儲器使用問題
埠 自己改一下
接法..隨便找兩個io口.
上拉5-10k電阻就好了.
24c01總共就只有128位元組
而且寫入的時候都知道忘那裡寫
你自己自然清楚什麼時候..24c01滿了.
這個東西都是固定地址.
又不是硬碟這種..還要什麼時候滿
SDA EQU P2.0
SCL EQU P2.1
Address EQU 08H
I2CData EQU 09H
ORG 0040H
LJMP START;轉入主程序.
START:
MOV SP,#60H
MOV Address,#00H
MOV I2CData,#55H
MOV P0,I2CDATA
CALL DELAY
CALL I2C_WRITE ;寫入數據.
MOV I2CDATA,#0AAH
MOV P0,I2CDATA
CALL DELAY
MOV Address,#00H
CALL I2C_READ
MOV I2CData,A ;讀出數據.
MOV P0,I2CDATA
CALL DELAY
NOP
NOP
LJMP START
//*******************************************
/*------------------------------------------------------
讀一個位元組 Address地址 Data讀出的數據
------------------------------------------------------*/
I2C_READ:
I2C_READ_A:
LCALL I2C_START
MOV A,#10100000B //從器件地址位是000,並且對從器件進行寫操作。
//不要有所疑問為什麼這么操作。因為這是一個選擇性讀的操作,主器件發送從器件地址和它想讀取的位元組數據的地址執行一個偽寫操作。
LCALL I2C_SEND8BIT
LCALL I2C_ACK
JC I2C_READ_A ;=1,表示無確認,再次發送 C為1轉移。
MOV A,Address
LCALL I2C_SEND8BIT
LCALL I2C_ACK
I2C_READ_B:
LCALL I2C_START
MOV A,#10100001B //從器件地址位是000,並且對從器件進行讀操作。
LCALL I2C_SEND8BIT
LCALL I2C_ACK
JC I2C_READ_B //C=1轉移,表示無確認,再次發送。
LCALL I2C_RECEIVE8BIT
MOV I2CData,A
LCALL I2C_ACK
LCALL I2C_STOP
RET
//*******************************************************
//*******************************************************
;接收八位數據
//主器件接收從器件指定地址的8位數據。
I2C_RECEIVE8BIT:
MOV B,#08H
CLR A
SETB SDA
I2C_RECEIVE8IT_A:
SETB SCL
NOP
NOP
MOV C,SDA
RLC A
CLR SCL
DJNZ B,I2C_RECEIVE8IT_A
RET
//*******************************************************
//*******************************************************
/*------------------------------------------------------
寫一個位元組 Address地址 I2CDatata寫入的數據
------------------------------------------------------*/
I2C_WRITE:
I2C_WRITE_A:
LCALL I2C_START //調用I2C匯流排的起始信號的程序。
MOV A,#10100000B //從器件地址位是000,並且對從器件進行寫操作。
LCALL I2C_SEND8BIT
LCALL I2C_ACK
JC I2C_WRITE_A //=1,表示無確認,再次發送。 C為1轉移。
MOV A,Address
LCALL I2C_SEND8BIT
LCALL I2C_ACK
MOV A,I2CData
LCALL I2C_SEND8BIT
LCALL I2C_ACK
LCALL I2C_STOP
RET
//***************************************
//**********************************
;發送開始信號
//I2C匯流排的起始信號的程序。
I2C_START:
SETB SCL
SETB SDA
NOP
NOP
CLR SDA
NOP
NOP
CLR SCL
RET
//***********************************
//***********************************
;送八位數據
//主器件送從器件8位數據。
I2C_SEND8BIT:
MOV B,#08H
I2C_SEND8BIT_A:
RLC A
MOV SDA,C
SETB SCL
NOP
NOP
CLR SCL
DJNZ B,I2C_SEND8BIT_A
RET
//************************************
//*************************************
;發送接收確認信號
I2C_ACk:
SETB SDA
SETB SCL
NOP
NOP
JB SDA,I2C_ACK0 //SDA為1跳轉。
CLR C
SJMP I2C_ACK_END
I2C_ACK0:
SETB C
I2C_ACK_END:
CLR SCL
RET
//**************************************
//**************************************
;發送結束信號
I2C_STOP:
CLR SDA
NOP
NOP
SETB SCL
NOP
NOP
SETB SDA
RET
//***************************************
//***************************************
delay:
MOV R7,#0FFH
DEL1:
MOV R6,#0FFH
DEL2:
MOV R5,#10
DEL3:
DJNZ R5,DEL3
DJNZ R6,DEL2
DJNZ R7,DEL1
RET
//***************************************
8. 如何用51單片機來檢測一個外接EEPROM的好壞
EEPROM存儲器,有並行的,如28系列的,IIC的,如24系列的。
24系列的,比較好接電路,只需要2個腳與單片機相連,重點是寫IIC通信程序。逐個單元寫入一個特定的數,如AAH,55H等,然後再讀出來,看是否相同,如有一個單元的數據讀/寫不同,就說明晶元有問題。
並行的,如28系列的,要與單片機連接,就有點麻煩,需要用到地址匯流排,數據匯流排,讀/寫控制線,擴展成外部數據存儲器電路。檢測好壞的方法與上面的相同。
9. 用51單片機和EEPROM如何寫掉電存儲c程序
直接存儲是不行的,單片機本身的RAM是掉電就沒有的。一般使用EEPROM,常用的有24c01等,採用I2C協議進行讀寫數據,怎麼使用這類晶元的程序網上搜一下能搜出幾噸來。可以自己搜索一下,由於你使用的51單片機,可以直接用IO口來模擬I2C協議,很簡單的。
需要注意的一點就是,要注意E2P晶元的壽命(一般是讀寫100萬次,足夠了)。
存儲數據的時候,可以對操作數和存儲的數據進行比較,不相等則存儲,比如:
if
(ReadI2c()!=data)
這樣可以增加使用壽命,比有些每隔1秒鍾進行存儲的會好多了。
碰到要存儲的是時間的時候,並且是每秒鍾存的話,由於壽命的原因,則要另外想辦法,常用的有:
1.在掉電瞬間的時候去存儲數據,這種方法要硬體上給予檢測電路來告知現在掉電了,然後程序就對時間進行存儲,這種方法的弊端是「必須要有檢測電路」。
2.考慮到上述的問題,可以開辟多塊空間來存儲「時間」,每次上電依次使用不同的空間,但是為了要有「使用哪一塊的判斷條件」,所以必須再多一個空間存儲「判斷」:每次程序開始,將「判斷++」,然後根據其來決定使用哪一塊的「時間空間」。
/*************************************************************/
希望能有幫助,上述是對掉電記憶來講比較不錯的的方法了。
10. 用51單片機和EEPROM如何寫掉電存儲匯編程序
(1)51單片機只能往外部的eeprom寫,要用movc指令;
(2)51單片機訪問外部存儲器的地址線為16位,最多64kB的地址空間。假如你選了一個2kB的EEPROM,那麼只需要11跟地址線,你把51的低11位地址與EEPROM相連,將第12位地址線連到EEPROM的選通線。在這個例子里,2048~4096的地址空間即對應你的EEPROM,隨便你往哪裡寫。