標題: 51單片機讀寫內部EEPROM詳解 [打印本頁]
作者: 854100995 時間: 2017-3-29 16:11
標題: 51單片機讀寫內部EEPROM詳解
此文檔共包含三個程序。
第一個程序最簡單易懂,看懂了基本就會讀寫51單片機內部EEPROM了。
第二個程序和第一個讀寫EEPROM原理差不多,包含有LCD1602操作方法,有寫字符串的方法。
第三個程序在原有基礎上增加了外部中斷功能,細心的人會發現,操作內部EEPROM過程會將總中斷關閉,實際上程序要用到中斷時只需在原有的EEPROM操作后加上開總中斷即可。
驗證第二、第三個程序時需按程序內主程序中的操作說明進行燒錄單片機,以驗證是否成功操作單片機內部EEPROM。
程序1:
- /***************************************************************
- 作品:EEPROM實驗,開機還原關電前LED的亮滅狀況
- 單片機:STC89C52RC
- 晶振:12M
- 編譯環境:Keil uVision4 V9.00
- ***************************************************************/
- //#include <STC89C52RC.H>
- #include <reg52.h>
- #include <intrins.h>
- #define uchar unsigned char
- #define uint unsigned int
- /****************特殊功能寄存器聲明****************/
- sfr ISP_DATA = 0xe2;
- sfr ISP_ADDRH = 0xe3;
- sfr ISP_ADDRL = 0xe4;
- sfr ISP_CMD = 0xe5;
- sfr ISP_TRIG = 0xe6;
- sfr ISP_CONTR = 0xe7;
- sbit LED1 = P2^0;
- sbit LED2 = P2^1;
- sbit K1 = P3^2; //按鈕1
- sbit K2 = P3^3; //按鈕2
- void cc(uint addr);
- void xcx(uint addr,uchar dat);
- uchar dcx(uint addr);
- void Q0();
- /*┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈
- 函數:主程序
- ┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈*/
- /*
- void main(void)
- {
- uchar V;
- V = dcx(0x2002); // 開機讀取EEPROM區2002h數據,還原關電前LED的亮滅狀況
- if(V == 2) {LED1=0;LED2=1;}
- else if(V == 6){LED1=0;LED2=0;}
- while(1)
- {
- if(!K1)
- {
- while(!K1);
- LED1=0;LED2=1;
- cc(0x2000); // 擦除第1個扇區(2000h~21FFh)
- xcx(0x2002,2); // 對EEPROM區2002h寫入2
- }
- if(!K2)
- {
- while(!K2);
- LED1=0;LED2=0;
- cc(0x2000); // 擦除第1個扇區(2000h~21FFh)
- xcx(0x2002,6); // 對EEPROM區2002h寫入6
- }
- }
- }
- */
- /*┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈
- 函數:擦除某一扇區(每個扇區512字節)
- 入口:addr = 某一扇區首地址
- ┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈*/
- void cc(uint addr)
- {
- // 打開 IAP 功能(ISP_CONTR.7)=1:允許編程改變Flash, 設置Flash操作等待時間
- // 0x83(晶振<5M) 0x82(晶振<10M) 0x81(晶振<20M) 0x80(晶振<40M)
- ISP_CONTR = 0x81;
- ISP_CMD = 0x03; // 用戶可以對"Data Flash/EEPROM區"進行扇區擦除
- ISP_ADDRL = addr; // ISP/IAP操作時的地址寄存器低八位,
- ISP_ADDRH = addr>>8; // ISP/IAP操作時的地址寄存器高八位。
- EA =0;
- ISP_TRIG = 0x46; // 在ISPEN(ISP_CONTR.7)=1時,對ISP_TRIG先寫入46h,
- ISP_TRIG = 0xB9; // 再寫入B9h,ISP/IAP命令才會生效。
- _nop_();
- Q0(); // 關閉ISP/IAP
- }
- /*┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈
- 函數:寫一字節
- 入口:addr = 扇區單元地址 , dat = 待寫入數據
- ┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈*/
- void xcx(uint addr,uchar dat)
- {
- ISP_CONTR = 0x81;
- ISP_CMD = 0x02; // 用戶可以對"Data Flash/EEPROM區"進行字節編程
- ISP_ADDRL = addr;
- ISP_ADDRH = addr>>8;
- ISP_DATA = dat; // 數據進ISP_DATA
- EA = 0;
- ISP_TRIG = 0x46;
- ISP_TRIG = 0xB9;
- _nop_();
- Q0(); // 關閉ISP/IAP
- }
- /*┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈
- 函數:讀一字節
- 入口:addr = 扇區單元地址
- 出口:dat = 讀出的數據
- ┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈*/
- uchar dcx(uint addr)
- {
- uchar dat;
-
- ISP_CONTR = 0x81;
- ISP_CMD = 0x01; // 用戶可以對"Data Flash/EEPROM區"進行字節讀
- ISP_ADDRL = addr;
- ISP_ADDRH = addr>>8;
- EA = 0;
- ISP_TRIG = 0x46;
- ISP_TRIG = 0xB9;
- _nop_();
- dat = ISP_DATA; // 取出數據
- Q0(); // 關閉ISP/IAP
- return dat;
- }
- /*┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈
- 函數:關閉ISP/IAP操作
- ┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈*/
- void Q0()
- {
- ISP_CONTR = 0; // 關閉IAP功能
- ISP_CMD = 0; // 待機模式,無ISP操作
- ISP_TRIG = 0; // 關閉IAP功能, 清與ISP有關的特殊功能寄存器
- }
- /*
- STC89C52RC內部EEPROM詳細地址表:
- 第一扇區 第二扇區 第三扇區 第四扇區
- 起始地址 結束地址 起始地址 結束地址 起始地址 結束地址 起始地址 結束地址
- 2000h 21FFh 2200h 23FFh 2400h 25FFh 2600h 27FFH
- 第五扇區 第六扇區 第七扇區 第八扇區
- 起始地址 結束地址 起始地址 結束地址 起始地址 結束地址 起始地址 結束地址
- 2800h 29FFh 2A00h 2BFFh 2C00h 2DFFh 2E00h 2FFFh
- */
復制代碼
程序2:
- /***************************************************************
- 作品:EEPROM實驗,開機還原關電前LED的亮滅狀況
- 單片機:STC89C52RC
- 晶振:12M
- 編譯環境:Keil uVision4 V9.00
- ***************************************************************/
- //#include <STC89C52RC.H>
- #include <reg52.h>
- #include <intrins.h>
- #define uchar unsigned char
- #define uint unsigned int
- /****************特殊功能寄存器聲明****************/
- sfr ISP_DATA = 0xe2;
- sfr ISP_ADDRH = 0xe3;
- sfr ISP_ADDRL = 0xe4;
- sfr ISP_CMD = 0xe5;
- sfr ISP_TRIG = 0xe6;
- sfr ISP_CONTR = 0xe7;
- sbit LED1 = P2^0;
- sbit LED2 = P2^1;
- sbit K1 = P3^2; //按鈕1
- sbit K2 = P3^3; //按鈕2
- void cc(uint addr);
- void xcx(uint addr,uchar dat);
- uchar dcx(uint addr);
- void Q0();
- #ifndef uchar
- #define uchar unsigned char
- #endif
- #ifndef uint
- #define uint unsigned int
- #endif
- /**********************************
- PIN口定義
- **********************************/
- #define LCD1602_DATAPINS P0
- sbit LCD1602_E=P2^7;
- sbit LCD1602_RW=P2^5;
- sbit LCD1602_RS=P2^6;
- /**********************************
- 函數聲明
- **********************************/
- /*在51單片機12MHZ時鐘下的延時函數*/
- void Lcd1602_Delay1ms(uint c); //誤差 0us
- /*LCD1602寫入8位命令子函數*/
- void LcdWriteCom(uchar com);
- /*LCD1602寫入8位數據子函數*/
- void LcdWriteData(uchar dat) ;
- /*LCD1602初始化子程序*/
- void LcdInit();
- /*LCD1602寫入字符串*/
- void LCDWrite_String(uchar x, uchar y,uchar z, uchar *s);
- /*設置LCD1602寫入字符串的位置*/
- void LCD_set_xy(uchar x, uchar y, uchar z);
- uchar ON_Hour=0x07; //初始開燈時間 07:00 1
- uchar Warning_TempH=32; //高溫報警溫度 5
- /*┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈
- 函數:主程序
- ┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈*/
- /*
- void main(void)
- {
- uchar V;
- V = dcx(0x2002); // 開機讀取EEPROM區2002h數據,還原關電前LED的亮滅狀況
- if(V == 2) {LED1=0;LED2=1;}
- else if(V == 6){LED1=0;LED2=0;}
- while(1)
- {
- if(!K1)
- {
- while(!K1);
- LED1=0;LED2=1;
- cc(0x2000); // 擦除第1個扇區(2000h~21FFh)
- xcx(0x2002,2); // 對EEPROM區2002h寫入2
- }
- if(!K2)
- {
- while(!K2);
- LED1=0;LED2=0;
- cc(0x2000); // 擦除第1個扇區(2000h~21FFh)
- xcx(0x2002,6); // 對EEPROM區2002h寫入6
- }
- }
- }
- */
- void main(void)
- {
- LcdInit();
- //不注銷下面三句,燒錄一次
- //注銷小面三句,再燒錄一次
- //若兩次燒錄后現象一致,則操作內部EEPROM成功
- /////////////////////////////////////////////////////////////////
- cc(0x2000); // 擦除第1個扇區(2000h~21FFh)
- xcx(0x2000,ON_Hour); // 對EEPROM區2002h寫入2
- xcx(0x2001,Warning_TempH); // 對EEPROM區2002h寫入2
- /////////////////////////////////////////////////////////////////
- ON_Hour = dcx(0x2000);
- Warning_TempH = dcx(0x2001);
- if((ON_Hour==0x07)||(Warning_TempH==32))
- {
- LcdWriteCom(0x80);
- LCDWrite_String(0, 1, 7, "SUCCESS");
- }
- else
- LCDWrite_String(0, 1, 5, "ERROR");
- while(1);
- }
- /*┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈
- 函數:擦除某一扇區(每個扇區512字節)
- 入口:addr = 某一扇區首地址
- ┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈*/
- void cc(uint addr)
- {
- // 打開 IAP 功能(ISP_CONTR.7)=1:允許編程改變Flash, 設置Flash操作等待時間
- // 0x83(晶振<5M) 0x82(晶振<10M) 0x81(晶振<20M) 0x80(晶振<40M)
- ISP_CONTR = 0x81;
- ISP_CMD = 0x03; // 用戶可以對"Data Flash/EEPROM區"進行扇區擦除
- ISP_ADDRL = addr; // ISP/IAP操作時的地址寄存器低八位,
- ISP_ADDRH = addr>>8; // ISP/IAP操作時的地址寄存器高八位。
- EA =0;
- ISP_TRIG = 0x46; // 在ISPEN(ISP_CONTR.7)=1時,對ISP_TRIG先寫入46h,
- ISP_TRIG = 0xB9; // 再寫入B9h,ISP/IAP命令才會生效。
- _nop_();
- Q0(); // 關閉ISP/IAP
- }
- /*┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈
- 函數:寫一字節
- 入口:addr = 扇區單元地址 , dat = 待寫入數據
- ┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈*/
- void xcx(uint addr,uchar dat)
- {
- ISP_CONTR = 0x81;
- ISP_CMD = 0x02; // 用戶可以對"Data Flash/EEPROM區"進行字節編程
- ISP_ADDRL = addr;
- ISP_ADDRH = addr>>8;
- ISP_DATA = dat; // 數據進ISP_DATA
- EA = 0;
- ISP_TRIG = 0x46;
- ISP_TRIG = 0xB9;
- _nop_();
- Q0(); // 關閉ISP/IAP
- }
- /*┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈
- 函數:讀一字節
- 入口:addr = 扇區單元地址
- 出口:dat = 讀出的數據
- ┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈*/
- uchar dcx(uint addr)
- {
- uchar dat;
-
- ISP_CONTR = 0x81;
- ISP_CMD = 0x01; // 用戶可以對"Data Flash/EEPROM區"進行字節讀
- ISP_ADDRL = addr;
- ISP_ADDRH = addr>>8;
- EA = 0;
- ISP_TRIG = 0x46;
- ISP_TRIG = 0xB9;
- _nop_();
- dat = ISP_DATA; // 取出數據
- Q0(); // 關閉ISP/IAP
- return dat;
- }
- /*┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈
- 函數:關閉ISP/IAP操作
- ┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈*/
- void Q0()
- {
- ISP_CONTR = 0; // 關閉IAP功能
- ISP_CMD = 0; // 待機模式,無ISP操作
- ISP_TRIG = 0; // 關閉IAP功能, 清與ISP有關的特殊功能寄存器
- }
- /*
- STC89C52RC內部EEPROM詳細地址表:
- 第一扇區 第二扇區 第三扇區 第四扇區
- 起始地址 結束地址 起始地址 結束地址 起始地址 結束地址 起始地址 結束地址
- 2000h 21FFh 2200h 23FFh 2400h 25FFh 2600h 27FFH
- 第五扇區 第六扇區 第七扇區 第八扇區
- 起始地址 結束地址 起始地址 結束地址 起始地址 結束地址 起始地址 結束地址
- 2800h 29FFh 2A00h 2BFFh 2C00h 2DFFh 2E00h 2FFFh
- */
- /*******************************************************************************
- * 函 數 名 : Lcd1602_Delay1ms
- * 函數功能 : 延時函數,延時1ms
- * 輸 入 : c
- * 輸 出 : 無
- * 說 名 : 該函數是在12MHZ晶振下,12分頻單片機的延時。
- *******************************************************************************/
- void Lcd1602_Delay1ms(uint c) //誤差 0us
- {
- uchar a,b;
- for (; c>0; c--)
- {
- for (b=199;b>0;b--)
- {
- for(a=1;a>0;a--);
- }
- }
- }
- /*******************************************************************************
- * 函 數 名 : void LCDWrite_String(uchar x, uchar y, uchar *s)
- * 函數功能 : 向LCD寫入一個字符串
- * 輸 入 : x,y,*s
- * 輸 出 : 無
- *******************************************************************************/
- void LCDWrite_String(uchar x, uchar y, uchar z, uchar *s) //x 0~15 , y 0,1,2,3
- {
- LCD_set_xy(x,y,z);
- while(*s)
- {
- LcdWriteData(*s);
- s++;
- }
- }
- /*******************************************************************************
- * 函 數 名 : void LCD_set_xy(uchar x, uchar y,uchar z)
- * 函數功能 : 指定向LCD寫入字符串的位置
- * 輸 入 : x,y,z //x:橫坐標 y:縱坐標 z:字符串長度
- * 輸 出 : 無
- *******************************************************************************/
- void LCD_set_xy(uchar x,uchar y,uchar z)
- {
- uchar i;
- if(y==0)
- {
- LcdWriteCom(0x80+x);
- for(i=0;i<z;i++)
- {
- LcdWriteData(' ');
- }
- LcdWriteCom(0x80+x);
- }
- if(y==1)
- {
- LcdWriteCom(0xc0+x);
- for(i=0;i<z;i++)
- {
- LcdWriteData(' ');
- }
- LcdWriteCom(0xc0+x);
- }
- if(y==2)
- {
- LcdWriteCom(0x94+x);
- for(i=0;i<z;i++)
- {
- LcdWriteData(' ');
- }
- LcdWriteCom(0x94+x);
- }
- if(y==3)
- {
- LcdWriteCom(0xd4+x);
- for(i=0;i<z;i++)
- {
- LcdWriteData(' ');
- }
- LcdWriteCom(0xd4+x);
- }
- }
- /*******************************************************************************
- * 函 數 名 : LcdWriteCom
- * 函數功能 : 向LCD寫入一個字節的命令
- * 輸 入 : com
- * 輸 出 : 無
- *******************************************************************************/
- #ifndef LCD1602_4PINS //當沒有定義這個LCD1602_4PINS時
- void LcdWriteCom(uchar com) //寫入命令
- {
- LCD1602_E = 0; //使能
- LCD1602_RS = 0; //選擇發送命令
- LCD1602_RW = 0; //選擇寫入
-
- LCD1602_DATAPINS = com; //放入命令
- Lcd1602_Delay1ms(1); //等待數據穩定
- LCD1602_E = 1; //寫入時序
- Lcd1602_Delay1ms(5); //保持時間
- LCD1602_E = 0;
- }
- #else
- void LcdWriteCom(uchar com) //寫入命令
- {
- LCD1602_E = 0; //使能清零
- LCD1602_RS = 0; //選擇寫入命令
- LCD1602_RW = 0; //選擇寫入
- LCD1602_DATAPINS = com; //由于4位的接線是接到P0口的高四位,所以傳送高四位不用改
- Lcd1602_Delay1ms(1);
- LCD1602_E = 1; //寫入時序
- Lcd1602_Delay1ms(5);
- LCD1602_E = 0;
- // Lcd1602_Delay1ms(1);
- LCD1602_DATAPINS = com << 4; //發送低四位
- Lcd1602_Delay1ms(1);
- LCD1602_E = 1; //寫入時序
- Lcd1602_Delay1ms(5);
- LCD1602_E = 0;
- }
- #endif
- /*******************************************************************************
- * 函 數 名 : LcdWriteData
- * 函數功能 : 向LCD寫入一個字節的數據
- * 輸 入 : dat
- * 輸 出 : 無
- *******************************************************************************/
- #ifndef LCD1602_4PINS
- void LcdWriteData(uchar dat) //寫入數據
- {
- LCD1602_E = 0; //使能清零
- LCD1602_RS = 1; //選擇輸入數據
- LCD1602_RW = 0; //選擇寫入
- LCD1602_DATAPINS = dat; //寫入數據
- Lcd1602_Delay1ms(1);
- LCD1602_E = 1; //寫入時序
- Lcd1602_Delay1ms(5); //保持時間
- LCD1602_E = 0;
- }
- #else
- void LcdWriteData(uchar dat) //寫入數據
- {
- LCD1602_E = 0; //使能清零
- LCD1602_RS = 1; //選擇寫入數據
- LCD1602_RW = 0; //選擇寫入
- LCD1602_DATAPINS = dat; //由于4位的接線是接到P0口的高四位,所以傳送高四位不用改
- Lcd1602_Delay1ms(1);
- LCD1602_E = 1; //寫入時序
- Lcd1602_Delay1ms(5);
- LCD1602_E = 0;
- LCD1602_DATAPINS = dat << 4; //寫入低四位
- Lcd1602_Delay1ms(1);
- LCD1602_E = 1; //寫入時序
- Lcd1602_Delay1ms(5);
- LCD1602_E = 0;
- }
- #endif
- /*******************************************************************************
- * 函 數 名 : LcdInit()
- * 函數功能 : 初始化LCD屏
- * 輸 入 : 無
- * 輸 出 : 無
- *******************************************************************************/
- #ifndef LCD1602_4PINS
- void LcdInit() //LCD初始化子程序
- {
- LcdWriteCom(0x38); //開顯示
- LcdWriteCom(0x0c); //開顯示不顯示光標
- LcdWriteCom(0x06); //寫一個指針加1
- LcdWriteCom(0x01); //清屏
- LcdWriteCom(0x80); //設置數據指針起點
- }
- #else
- void LcdInit() //LCD初始化子程序
- {
- LcdWriteCom(0x32); //將8位總線轉為4位總線
- LcdWriteCom(0x28); //在四位線下的初始化
- LcdWriteCom(0x0c); //開顯示不顯示光標
- LcdWriteCom(0x06); //寫一個指針加1
- LcdWriteCom(0x01); //清屏
- LcdWriteCom(0x80); //設置數據指針起點
- }
- #endif
復制代碼
程序3:
- /***************************************************************
- 作品:EEPROM實驗,開機還原關電前LED的亮滅狀況
- 單片機:STC89C52RC
- 晶振:12M
- 編譯環境:Keil uVision4 V9.00
- ***************************************************************/
- //#include <STC89C52RC.H>
- #include <reg52.h>
- #include <intrins.h>
- #define uchar unsigned char
- #define uint unsigned int
- /****************特殊功能寄存器聲明****************/
- sfr ISP_DATA = 0xe2;
- sfr ISP_ADDRH = 0xe3;
- sfr ISP_ADDRL = 0xe4;
- sfr ISP_CMD = 0xe5;
- sfr ISP_TRIG = 0xe6;
- sfr ISP_CONTR = 0xe7;
- sbit LED1 = P2^0;
- sbit LED2 = P2^1;
- sbit K1 = P3^2; //按鈕1
- sbit K2 = P3^3; //按鈕2
- void cc(uint addr);
- void xcx(uint addr,uchar dat);
- uchar dcx(uint addr);
- void Q0();
- #ifndef uchar
- #define uchar unsigned char
- #endif
- #ifndef uint
- #define uint unsigned int
- #endif
- /**********************************
- PIN口定義
- **********************************/
- #define LCD1602_DATAPINS P0
- sbit LCD1602_E=P2^7;
- sbit LCD1602_RW=P2^5;
- sbit LCD1602_RS=P2^6;
- /**********************************
- 函數聲明
- **********************************/
- /*在51單片機12MHZ時鐘下的延時函數*/
- void Lcd1602_Delay1ms(uint c); //誤差 0us
- /*LCD1602寫入8位命令子函數*/
- void LcdWriteCom(uchar com);
- /*LCD1602寫入8位數據子函數*/
- void LcdWriteData(uchar dat) ;
- /*LCD1602初始化子程序*/
- void LcdInit();
- /*LCD1602寫入字符串*/
- void LCDWrite_String(uchar x, uchar y,uchar z, uchar *s);
- /*設置LCD1602寫入字符串的位置*/
- void LCD_set_xy(uchar x, uchar y, uchar z);
- void IntConfiguration();
- /*
- uchar ON_Hour=0x07; //初始開燈時間 07:00 1
- uchar Warning_TempH=32; //高溫報警溫度 5
- */
- uchar ON_Hour; //初始開燈時間 07:00 1
- uchar Warning_TempH; //高溫報警溫度
- /*┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈
- 函數:主程序
- ┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈*/
- void main(void)
- {
- LcdInit();
- IntConfiguration();
- /////////////////////////////////////////////////////////////////
- /*
- cc(0x2000); // 擦除第1個扇區(2000h~21FFh)
- xcx(0x2000,ON_Hour); // 對EEPROM區2002h寫入2
- xcx(0x2001,Warning_TempH); // 對EEPROM區2002h寫入2
- */
- /////////////////////////////////////////////////////////////////
- while(1)
- {
- ON_Hour = dcx(0x2000);
- Warning_TempH = dcx(0x2001);
- if((ON_Hour==0x07)||(Warning_TempH==32))
- {
- LcdWriteCom(0x80);
- LCDWrite_String(0, 1, 7, "SUCCESS");
- }
- else
- LcdWriteCom(0x80);
- LCDWrite_String(0, 1, 5, "ERROR");
- }
- /*
- uchar V;
- V = dcx(0x2002); // 開機讀取EEPROM區2002h數據,還原關電前LED的亮滅狀況
- if(V == 2) {LED1=0;LED2=1;}
- else if(V == 6){LED1=0;LED2=0;}
- while(1)
- {
- if(!K1)
- {
- while(!K1);
- LED1=0;LED2=1;
- cc(0x2000); // 擦除第1個扇區(2000h~21FFh)
- xcx(0x2002,2); // 對EEPROM區2002h寫入2
- }
- if(!K2)
- {
- while(!K2);
- LED1=0;LED2=0;
- cc(0x2000); // 擦除第1個扇區(2000h~21FFh)
- xcx(0x2002,6); // 對EEPROM區2002h寫入6
- }
- }
- */
- }
- /*┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈
- 函數:擦除某一扇區(每個扇區512字節)
- 入口:addr = 某一扇區首地址
- ┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈*/
- void cc(uint addr)
- {
- // 打開 IAP 功能(ISP_CONTR.7)=1:允許編程改變Flash, 設置Flash操作等待時間
- // 0x83(晶振<5M) 0x82(晶振<10M) 0x81(晶振<20M) 0x80(晶振<40M)
- ISP_CONTR = 0x81;
- ISP_CMD = 0x03; // 用戶可以對"Data Flash/EEPROM區"進行扇區擦除
- ISP_ADDRL = addr; // ISP/IAP操作時的地址寄存器低八位,
- ISP_ADDRH = addr>>8; // ISP/IAP操作時的地址寄存器高八位。
- EA =0;
- ISP_TRIG = 0x46; // 在ISPEN(ISP_CONTR.7)=1時,對ISP_TRIG先寫入46h,
- ISP_TRIG = 0xB9; // 再寫入B9h,ISP/IAP命令才會生效。
- _nop_();
- Q0(); // 關閉ISP/IAP
- }
- /*┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈
- 函數:寫一字節
- 入口:addr = 扇區單元地址 , dat = 待寫入數據
- ┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈*/
- void xcx(uint addr,uchar dat)
- {
- ISP_CONTR = 0x81;
- ISP_CMD = 0x02; // 用戶可以對"Data Flash/EEPROM區"進行字節編程
- ISP_ADDRL = addr;
- ISP_ADDRH = addr>>8;
- ISP_DATA = dat; // 數據進ISP_DATA
- EA = 0;
- ISP_TRIG = 0x46;
- ISP_TRIG = 0xB9;
- _nop_();
- Q0(); // 關閉ISP/IAP
- }
- /*┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈
- 函數:讀一字節
- 入口:addr = 扇區單元地址
- 出口:dat = 讀出的數據
- ┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈*/
- uchar dcx(uint addr)
- {
- uchar dat;
-
- ISP_CONTR = 0x81;
- ISP_CMD = 0x01; // 用戶可以對"Data Flash/EEPROM區"進行字節讀
- ISP_ADDRL = addr;
- ISP_ADDRH = addr>>8;
- EA = 0;
- ISP_TRIG = 0x46;
- ISP_TRIG = 0xB9;
- _nop_();
- dat = ISP_DATA; // 取出數據
- Q0(); // 關閉ISP/IAP
- return dat;
- }
- /*┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈
- 函數:關閉ISP/IAP操作
- ┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈*/
- void Q0()
- {
- ISP_CONTR = 0; // 關閉IAP功能
- ISP_CMD = 0; // 待機模式,無ISP操作
- ISP_TRIG = 0; // 關閉IAP功能, 清與ISP有關的特殊功能寄存器
- EA=1;
- }
- /*
- STC89C52RC內部EEPROM詳細地址表:
- 第一扇區 第二扇區 第三扇區 第四扇區
- 起始地址 結束地址 起始地址 結束地址 起始地址 結束地址 起始地址 結束地址
- 2000h 21FFh 2200h 23FFh 2400h 25FFh 2600h 27FFH
- 第五扇區 第六扇區 第七扇區 第八扇區
- 起始地址 結束地址 起始地址 結束地址 起始地址 結束地址 起始地址 結束地址
- 2800h 29FFh 2A00h 2BFFh 2C00h 2DFFh 2E00h 2FFFh
- */
- /*******************************************************************************
- * 函 數 名 : Lcd1602_Delay1ms
- * 函數功能 : 延時函數,延時1ms
- * 輸 入 : c
- * 輸 出 : 無
- * 說 名 : 該函數是在12MHZ晶振下,12分頻單片機的延時。
- *******************************************************************************/
- void Lcd1602_Delay1ms(uint c) //誤差 0us
- {
- uchar a,b;
- for (; c>0; c--)
- {
- for (b=199;b>0;b--)
- {
- for(a=1;a>0;a--);
- }
- }
- }
- /*******************************************************************************
- * 函 數 名 : void LCDWrite_String(uchar x, uchar y, uchar *s)
- * 函數功能 : 向LCD寫入一個字符串
- * 輸 入 : x,y,*s
- * 輸 出 : 無
- *******************************************************************************/
- void LCDWrite_String(uchar x, uchar y, uchar z, uchar *s) //x 0~15 , y 0,1,2,3
- {
- LCD_set_xy(x,y,z);
- while(*s)
- {
- LcdWriteData(*s);
- s++;
- }
- }
- /*******************************************************************************
- * 函 數 名 : void LCD_set_xy(uchar x, uchar y,uchar z)
- * 函數功能 : 指定向LCD寫入字符串的位置
- * 輸 入 : x,y,z //x:橫坐標 y:縱坐標 z:字符串長度
- * 輸 出 : 無
- *******************************************************************************/
- void LCD_set_xy(uchar x,uchar y,uchar z)
- {
- uchar i;
- if(y==0)
- {
- LcdWriteCom(0x80+x);
- for(i=0;i<z;i++)
- {
- LcdWriteData(' ');
- }
- LcdWriteCom(0x80+x);
- }
- if(y==1)
- {
- LcdWriteCom(0xc0+x);
- for(i=0;i<z;i++)
- {
- LcdWriteData(' ');
- }
- LcdWriteCom(0xc0+x);
- }
- if(y==2)
- {
- LcdWriteCom(0x94+x);
- for(i=0;i<z;i++)
- {
- LcdWriteData(' ');
- }
- LcdWriteCom(0x94+x);
- }
- if(y==3)
- {
- LcdWriteCom(0xd4+x);
- for(i=0;i<z;i++)
- {
- LcdWriteData(' ');
- }
- LcdWriteCom(0xd4+x);
- }
- }
- /*******************************************************************************
- * 函 數 名 : LcdWriteCom
- * 函數功能 : 向LCD寫入一個字節的命令
- * 輸 入 : com
- * 輸 出 : 無
- *******************************************************************************/
- #ifndef LCD1602_4PINS //當沒有定義這個LCD1602_4PINS時
- void LcdWriteCom(uchar com) //寫入命令
- {
- LCD1602_E = 0; //使能
- LCD1602_RS = 0; //選擇發送命令
- LCD1602_RW = 0; //選擇寫入
-
- LCD1602_DATAPINS = com; //放入命令
- Lcd1602_Delay1ms(1); //等待數據穩定
- LCD1602_E = 1; //寫入時序
- Lcd1602_Delay1ms(5); //保持時間
- LCD1602_E = 0;
- }
- #else
- void LcdWriteCom(uchar com) //寫入命令
- {
- LCD1602_E = 0; //使能清零
- LCD1602_RS = 0; //選擇寫入命令
- LCD1602_RW = 0; //選擇寫入
- LCD1602_DATAPINS = com; //由于4位的接線是接到P0口的高四位,所以傳送高四位不用改
- Lcd1602_Delay1ms(1);
- LCD1602_E = 1; //寫入時序
- Lcd1602_Delay1ms(5);
- LCD1602_E = 0;
- // Lcd1602_Delay1ms(1);
- LCD1602_DATAPINS = com << 4; //發送低四位
- Lcd1602_Delay1ms(1);
- LCD1602_E = 1; //寫入時序
- Lcd1602_Delay1ms(5);
- LCD1602_E = 0;
- }
- #endif
- /*******************************************************************************
- * 函 數 名 : LcdWriteData
- * 函數功能 : 向LCD寫入一個字節的數據
- * 輸 入 : dat
- * 輸 出 : 無
- *******************************************************************************/
- #ifndef LCD1602_4PINS
- void LcdWriteData(uchar dat) //寫入數據
- {
- LCD1602_E = 0; //使能清零
- LCD1602_RS = 1; //選擇輸入數據
- LCD1602_RW = 0; //選擇寫入
- LCD1602_DATAPINS = dat; //寫入數據
- Lcd1602_Delay1ms(1);
- LCD1602_E = 1; //寫入時序
- Lcd1602_Delay1ms(5); //保持時間
- LCD1602_E = 0;
- }
- #else
- void LcdWriteData(uchar dat) //寫入數據
- {
- LCD1602_E = 0; //使能清零
- LCD1602_RS = 1; //選擇寫入數據
- LCD1602_RW = 0; //選擇寫入
- LCD1602_DATAPINS = dat; //由于4位的接線是接到P0口的高四位,所以傳送高四位不用改
- Lcd1602_Delay1ms(1);
- LCD1602_E = 1; //寫入時序
- Lcd1602_Delay1ms(5);
- LCD1602_E = 0;
- LCD1602_DATAPINS = dat << 4; //寫入低四位
- Lcd1602_Delay1ms(1);
- LCD1602_E = 1; //寫入時序
- Lcd1602_Delay1ms(5);
- LCD1602_E = 0;
- }
- #endif
- /*******************************************************************************
- * 函 數 名 : LcdInit()
- * 函數功能 : 初始化LCD屏
- * 輸 入 : 無
- * 輸 出 : 無
- *******************************************************************************/
- #ifndef LCD1602_4PINS
- void LcdInit() //LCD初始化子程序
- {
- LcdWriteCom(0x38); //開顯示
- LcdWriteCom(0x0c); //開顯示不顯示光標
- LcdWriteCom(0x06); //寫一個指針加1
- LcdWriteCom(0x01); //清屏
- LcdWriteCom(0x80); //設置數據指針起點
- }
- #else
- void LcdInit() //LCD初始化子程序
- {
- LcdWriteCom(0x32); //將8位總線轉為4位總線
- LcdWriteCom(0x28); //在四位線下的初始化
- LcdWriteCom(0x0c); //開顯示不顯示光標
- LcdWriteCom(0x06); //寫一個指針加1
- LcdWriteCom(0x01); //清屏
- LcdWriteCom(0x80); //設置數據指針起點
- }
- #endif
- void IntConfiguration()
- {
- //設置INT0
- IT0=1;//跳變沿出發方式(下降沿)
- EX0=1;//打開INT0的中斷允許。
- //設置INT1
- IT1=1;//跳變沿出發方式(下降沿)
- EX1=1;//打開INT0的中斷允許。
- EA=1;//打開總中斷
- }
- void Int0() interrupt 1
- {
- cc(0x2000); // 擦除第1個扇區(2000h~21FFh)
- xcx(0x2000,0x07); // 對EEPROM區2002h寫入2
- xcx(0x2001,32);
- LcdInit();
- }
- void Int1() interrupt 2
- {
- cc(0x2000); // 擦除第1個扇區(2000h~21FFh)
- xcx(0x2000,0x08); // 對EEPROM區2002h寫入2
- xcx(0x2001,33);
- LcdInit();
- }
復制代碼
163702u7rzlq1j88ibczbl.png (6.87 KB, 下載次數: 156)
下載附件
2017-8-12 02:35 上傳
全部資料下載地址:
51單片機讀寫內部EEPROM詳解.rar
(101.88 KB, 下載次數: 364)
2017-8-12 02:36 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
作者: liujueshen 時間: 2017-3-31 09:42
好好學習,天天向上
作者: xzf586 時間: 2017-7-22 07:57
樓主好樣的,多謝,學習一下
作者: 文龍 時間: 2017-7-29 15:25
剛剛學到這里,學習了.
作者: 周鵬 時間: 2017-11-21 15:12
結合我看的資料,你的程序易懂!!!
作者: 飛躍吧 時間: 2018-4-19 22:08
感謝樓主
作者: eeadad 時間: 2018-8-15 14:09
謝謝了!,學習一下
作者: zzzzzkevin 時間: 2019-3-20 23:40
好好學習
作者: jwl595 時間: 2019-3-21 08:31
代碼很好,內容十分詳細,已經借鑒
作者: 有心插花花木蘭 時間: 2019-3-22 19:06
有點復雜,51芯片手冊上面有
作者: univers 時間: 2019-4-9 10:59
謝謝,我還是看看手冊,剛學寫EEPROM。頭好暈啊。
作者: 白歌 時間: 2019-4-28 11:09
學習學習
作者: 13534702358 時間: 2019-4-28 15:20
正需要呢 ,謝謝 !
作者: aiwenxue999 時間: 2019-5-16 14:59
好東西。謝謝分享。
作者: 13798559800 時間: 2019-5-20 23:15
好東西,收藏了
作者: ben0147 時間: 2019-5-21 17:06
很給力!!!!!
作者: LIUSUSHUAI 時間: 2019-6-5 14:42
謝謝樓主,學習了
作者: 宗遙 時間: 2019-6-27 19:32
感謝樓主發布 學習了
作者: wspytu 時間: 2019-6-28 15:06
謝謝分享,好資料
作者: 時之沙丶流年 時間: 2019-8-24 14:34
可以可以
作者: zhouxianen 時間: 2019-11-1 11:27
資料不錯,謝謝!
作者: rsurb0371 時間: 2019-11-13 22:51
我必須對你提出表揚和感謝,程序簡單易懂,注釋詳細!
謝謝你的無私奉獻!
作者: 風暴之靈1022 時間: 2019-11-18 11:55
學習了~
作者: 好學007 時間: 2020-3-16 17:37
給力!
作者: coffeepod 時間: 2020-4-16 17:21
墻都不服,就服你
作者: zbfdyw 時間: 2020-4-19 22:26
這個程序比較符合初學者,注解很仔細,很細心,真的很不錯,感謝你。
作者: liangsheng0212 時間: 2020-4-21 13:04
謝謝樓主,真心不錯
作者: 15857778517 時間: 2022-12-12 10:13
51單片機讀寫內部EEPROM詳解
http://www.zg4o1577.cn/bbs/dpj-80082-1.html
(出處: http://www.zg4o1577.cn/bbs/)
作者: kz0018 時間: 2023-5-18 00:01
點贊一個,三個例子說的詳細,學習了。
作者: Q__Q 時間: 2023-5-22 11:56
收藏了 謝謝樓主 寫的很詳細 感覺自己能看懂 很給力!
作者: 美琴的備胎 時間: 2023-6-25 14:25
謝謝好兄弟,問題解決了
歡迎光臨 (http://www.zg4o1577.cn/bbs/) |
Powered by Discuz! X3.1 |
主站蜘蛛池模板:
午夜精品久久久久久久久久久久久
|
二区视频|
国产精品国产三级国产aⅴ浪潮
|
一级毛片免费视频观看
|
天堂精品视频
|
国产精品久久精品
|
欧美日韩1区
|
国产精品美女久久久av超清
|
午夜小视频在线播放
|
在线精品观看
|
亚州午夜精品
|
国产福利资源在线
|
欧美精品一区二区在线观看
|
成人蜜桃av|
成人在线欧美
|
天堂综合网
|
米奇7777狠狠狠狠视频
|
国产黄色大片在线免费观看
|
国产日韩一区二区
|
免费国产一区
|
亚洲精品一区二区三区蜜桃久
|
国产成人免费一区二区60岁
|
蜜桃在线视频
|
国产视频在线一区二区
|
国产精品久久久久免费
|
国产精品a一区二区三区网址
|
日本精品视频一区二区三区四区
|
中文字幕一二三区
|
亚洲一区在线日韩在线深爱
|
日朝毛片
|
日韩中文字幕一区二区
|
久久综合香蕉
|
在线播放国产一区二区三区
|
一区二区免费在线观看
|
热re99久久精品国产99热
|
青青久久av北条麻妃海外网
|
999久久久
|
国产日韩欧美精品一区二区
|
在线观看免费av网
|
国产亚洲人成a在线v网站
|
天天噜天天干
|