|
仿真受PC時鐘影響,不一定準,要用實物驗證。仿真用不了STC89C52的EEPROM保存fixtime變量。給你基本補齊了。
- //適用STC89C52RC單片機
- #include <reg52.h>
- #include <intrins.h>
- #define uint unsigned int
- #define uchar unsigned char
- //定義ISP的操作命令
- #define RdCommand 0x01 //讀命令
- #define PrgCommand 0x02 //寫命令
- #define EraseCommand 0x03 //擦除命令
- #define Error 1
- #define Ok 0
- #define WaitTime 0x01 //定義CPU的等待時間,寫入硬件延時
- //STC89系列EEPROM寄存器聲明
- sfr ISP_DATA=0xe2; //0000,0000 EEPROM數據寄存器
- sfr ISP_ADDRH=0xe3; //0000,0000 EEPROM地址高字節
- sfr ISP_ADDRL=0xe4; //0000,0000 EEPROM地址第字節
- sfr ISP_CMD=0xe5; //xxxx,xx00 EEPROM命令寄存器
- sfr ISP_TRIG=0xe6; //0000,0000 EEPRPM命令觸發寄存器
- sfr ISP_CONTR=0xe7; //0000,x000 EEPROM控制寄存器
- sbit key0=P3^3;
- sbit key1=P3^4;
- sbit key2=P3^5;
- sbit rs=P2^6; //寄存器選擇信號 H:數據寄存器 L:指令寄存器
- sbit rw=P2^5; //寄存器選擇信號 H:數據寄存器 L:指令寄存器
- sbit e =P2^7; //片選信號 下降沿觸發
- uchar sec=0,min=0,hour=12;
- uchar num=0;
- uint usec=0;
- //uint fixtime=10000; //定義修正變量
- uint fixtime; //定義修正變量
- bit sec_flag=0; //秒標志
- // 打開 ISP,IAP 功能
- void ISP_IAP_enable(void)
- {
- EA = 0; /* 關中斷 */
- ISP_CONTR = ISP_CONTR & 0x18; /* 0001,1000 */
- ISP_CONTR = ISP_CONTR | WaitTime; /* 寫入硬件延時 */
- ISP_CONTR = ISP_CONTR | 0x80; /* ISPEN=1 */
- }
- // 關閉 ISP,IAP 功能
- void ISP_IAP_disable(void)
- {
- ISP_CONTR = ISP_CONTR & 0x7f; /* ISPEN = 0 */
- ISP_TRIG = 0x00;
- EA = 1; /* 開中斷 */
- }
- // 公用的觸發代碼
- void ISPgoon(void)
- {
- ISP_IAP_enable(); /* 打開 ISP,IAP 功能 */
- ISP_TRIG = 0x46; /* 觸發ISP_IAP命令字節1 */
- ISP_TRIG = 0xb9; /* 觸發ISP_IAP命令字節2 */
- _nop_();
- }
- // 字節讀
- unsigned char byte_read(unsigned int byte_addr)
- {
- ISP_ADDRH = (unsigned char)(byte_addr >> 8);/* 地址賦值 */
- ISP_ADDRL = (unsigned char)(byte_addr & 0x00ff);
- ISP_CMD = ISP_CMD & 0xf8; /* 清除低3位 */
- ISP_CMD = ISP_CMD | RdCommand; /* 寫入讀命令 */
- ISPgoon(); /* 觸發執行 */
- ISP_IAP_disable(); /* 關閉ISP,IAP功能 */
- return (ISP_DATA); /* 返回讀到的數據 */
- }
- // 扇區擦除
- void SectorErase(unsigned int sector_addr)
- {
- unsigned int iSectorAddr;
- iSectorAddr = (sector_addr & 0xfe00); /* 取扇區地址 */
- ISP_ADDRH = (unsigned char)(iSectorAddr >> 8);
- ISP_ADDRL = 0x00;
- ISP_CMD = ISP_CMD & 0xf8; /* 清空低3位 */
- ISP_CMD = ISP_CMD | EraseCommand; /* 擦除命令3 */
- ISPgoon(); /* 觸發執行 */
- ISP_IAP_disable(); /* 關閉ISP,IAP功能 */
- }
- // 字節寫
- void byte_write(unsigned int byte_addr, unsigned char original_data)
- {
- ISP_ADDRH = (unsigned char)(byte_addr >> 8); /* 取地址 */
- ISP_ADDRL = (unsigned char)(byte_addr & 0x00ff);
- ISP_CMD = ISP_CMD & 0xf8; /* 清低3位 */
- ISP_CMD = ISP_CMD | PrgCommand; /* 寫命令2 */
- ISP_DATA = original_data; /* 寫入數據準備 */
- ISPgoon(); /* 觸發執行 */
- ISP_IAP_disable(); /* 關閉IAP功能 */
- }
- /********************************************************************
- * 名稱 : delay_uint()
- * 功能 : 小延時。
- * 輸入 : 無
- * 輸出 : 無
- ***********************************************************************/
- void delay_uint(uint i)
- {
- while(--i);
- }
- /********************************************************************
- * 名稱 : write_com(uchar com)
- * 功能 : 1602命令函數
- * 輸入 : 輸入的命令值
- * 輸出 : 無
- ***********************************************************************/
- void write_com(uchar com)
- {
- e=0;
- rs=0;
- rw=0;
- P0=com;
- delay_uint(25);
- e=1;
- delay_uint(25);
- e=0;
- }
- /********************************************************************
- * 名稱 : write_data(uchar dat)
- * 功能 : 1602寫數據函數
- * 輸入 : 需要寫入1602的數據
- * 輸出 : 無
- ***********************************************************************/
- void write_data(uchar dat)
- {
- e=0;
- rs=1;
- rw=0;
- P0=dat;
- delay_uint(25);
- e=1;
- delay_uint(25);
- e=0;
- }
- /***********************lcd1602初始化設置************************/
- void init_1602()
- {
- write_com(0x38);
- write_com(0x0c);
- write_com(0x06);
- write_com(0x01);
- }
- void time0_init(void)
- {
- TMOD = 0x02;//自動重裝
- TH0 = 0x9C; //100us
- TL0 = 0x9C;
- EA = 1;
- ET0 = 1;
- TR0 = 1;
- }
- void LCD1602_init(void)
- {
- uchar i;
- uchar a[]=" Digital Clock ";
- write_com(0x80);
- for(i=0;i<16;i++)
- write_data(a[i]);
- }
- void display(void)
- {
- write_com(0xc0+13);
- if(num==0)
- write_data(' ');
- else if(num==1)
- write_data('H');
- else if(num==2)
- write_data('M');
- else if(num==3)
- write_data('S');
- write_com(0x80+0x44);
- if(num==4)
- {
- write_data('F');
- write_data('=');
- write_data('=');
- write_data(fixtime/10000%10+'0');
- write_data(fixtime/1000%10+'0');
- write_data(fixtime/100%10+'0');
- write_data(fixtime/10%10+'0');
- write_data(fixtime%10+'0');
- write_data(' ');
- write_data(' ');
- }
- else
- {
- write_data(hour/10+'0');
- write_data(hour%10+'0');
- write_data(':');
- write_data(min/10+'0');
- write_data(min%10+'0');
- write_data(':');
- write_data(sec/10+'0');
- write_data(sec%10+'0');
- }
- }
- void keyscan()
- {
- static bit key_lock=0; //按鍵自鎖標志
- static uchar count=0; //消抖計數變量
- uchar i=0,a,b;
- if(!key0||!key1||!key2)
- {
- if(++count>=10 && key_lock==0)
- {
- key_lock=1;//自鎖
- if(!key0)
- {
- num++;
- num%=5;
- }
- if(!key1 && num>0)
- {
- switch(num)
- {
- case 1: hour++;if(hour>=24)hour=0; break;
- case 2: min++; if(min>=60) min=0; break;
- case 3: sec++; if(sec>=60) sec=0; break;
- case 4: fixtime++;
- a=fixtime>>8;
- b=fixtime;
- SectorErase(0x2000);//擦除扇區
- byte_write(0x2000,a);//重新寫入數據高8位
- byte_write(0x2001,b);//重新寫入數據低8位
- break;
- default: break;
- }
- }
- if(!key2 && num>0)
- {
- switch(num)
- {
- case 1: hour--;if(hour>=24)hour=23; break;
- case 2: min--; if(min>=60) min=59; break;
- case 3: sec--; if(sec>=60) sec=59; break;
- case 4: fixtime--;
- a=fixtime>>8;
- b=fixtime;
- SectorErase(0x2000);//擦除扇區
- byte_write(0x2000,a);//重新寫入數據高8位
- byte_write(0x2001,b);//重新寫入數據低8位
- break;
- default: break;
- }
- }
- }
- }
- else //松手
- {
- count=0;
- key_lock=0;
- }
- }
- void Timing()//計時程序
- {
- if(sec_flag)
- {
- sec_flag=0;
- sec++;
- if(sec >= 60)
- {
- sec = 0;
- min++;
- if(min >= 60)
- {
- min = 0;
- hour++;
- if(hour >= 24)
- hour=0;
- }
- }
- }
- }
- void main()
- {
- init_1602();
- LCD1602_init();
- fixtime=byte_read(0x2000);//程序開始時讀取EEPROM中數據
- fixtime=fixtime<<8|byte_read(0x2001);//合并為整形數據
- if(fixtime>15000||fixtime<5000) //防止首次上電時讀取出錯
- fixtime=10000;
- time0_init();
- while(1)
- {
- keyscan();
- Timing();
- display();
- }
- }
- void Timer0() interrupt 1
- {
- if(++usec>=fixtime) //1sec
- {
- usec = 0;
- sec_flag=1;
- }
- }
復制代碼
|
-
-
STC99封裝.zip
2020-5-20 20:42 上傳
點擊文件名下載附件
26.37 KB, 下載次數: 7
|