#include <reg52.h>//52單片機頭文件 #include <intrins.h>//intrins.h文件 #define uchar unsigned char // 自定義uchar為unsigned char(即無符號字符型數據,數據范圍:0到255。) #define uint unsigned int //自定義uint為unsigned int(即有符號整數型數據,數據范圍:0到65535。) #define ISP_ReadCommand 0x01 //自定義ISP的讀字節操作 #define ISP_WriteCommand 0x02 //自定義ISP的寫字節操作 #define ISP_EraseCommand 0x03 //自定義ISP的擦除扇區操作 #define ERROR 0 #define OK 1 sbit duanxuan=P2^6; sbit weixuan=P2^7; uint count,value;//聲明定時器0中斷次數變量、數值變量 uint ge,shi,bai,qian;//聲明數碼管個位變量、數碼管十位變量、數碼管百位變量、數碼管千位變量 uint valuege,valueshi,valuebai,valueqian;//聲明數值變量個位變量、數值變量十位變量、數值變量百位變量、數值變量千位變量 uchar code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f} ; //共陰數碼管段碼數字0~9字碼表,高電平點亮數碼管段碼數字0~9。 //#define WAIT_TIME 0x00 //mcu clock 小於 40mhz //#define WAIT_TIME 0x01 //mcu clock 小於 20mhz //#define WAIT_TIME 0x02 //mcu clock 小於 10mhz #define WAIT_TIME 0x03 //mcu clock 小於 5mhz sfr ISP_DATA=0xe2; //Flash數據寄存器 sfr ISP_ADDRH=0xe3; //Flash高字節地址寄存器 sfr ISP_ADDRL=0xe4; //Flash低字節地址寄存器 sfr ISP_CMD=0xe5; //Flash命令模式寄存器 sfr ISP_TRIG=0xe6; //Flash命令觸發寄存器 sfr ISP_CONTR=0xe7; //ISP/IAP 控制寄存器 // void Delay100us() //晶振11.0592MHz,100微妙延時。 //{ // unsigned char i, j; // _nop_(); // _nop_(); // i = 2; // j = 15; // do // { // while (--j); // } // while (--i); // } void Delay(uint z)//延時程序 { uint x,y; for(x=z;x>0;x--) for(y=110;y>0;y--); } void OPEN_ISP_IAP()//打開ISP/IAP功能函數 { EA=0;//關中斷 ISP_CONTR=ISP_CONTR&0x18;//0001,1000 ISP_CONTR=ISP_CONTR|WAIT_TIME;//寫入硬件延時 ISP_CONTR=ISP_CONTR|0x80;//ISPEN=1 } void CLOSE_ISP_IAP()//關閉ISP/IAP功能函數 { ISP_CONTR=ISP_CONTR&0x7f;//ISPEN=0 ISP_TRIG=0x00;//關掉與ISP有關的特殊功能寄存器 EA=1;//開中斷 } void ActiveOperate(void)//觸發執行函數 { OPEN_ISP_IAP(); //打開ISP/IAP功能 ISP_TRIG=0x46; //觸發ISP_IAP命令字節1 ISP_TRIG=0xb9; // 觸發ISP_IAP命令字節2 _nop_();//延時 } uchar ReadByte(uint byteaddress)//讀字節函數 { ISP_ADDRH=(uchar)(byteaddress>>8);//高8位字節地址 ISP_ADDRL=(uchar)(byteaddress&0x00ff);//低8位字節地址 ISP_CMD=ISP_CMD&0xf8;//清除低3位 ISP_CMD=ISP_CMD|ISP_ReadCommand;//寫入讀命令 ActiveOperate();//觸發執行 CLOSE_ISP_IAP();//關閉ISP/IAP功能 return (ISP_DATA);//返回讀到的數據 } void SectorErase(uint sectoraddress)//刪除扇區函數 { uint isectoraddress;//聲明扇區地址變量 isectoraddress=(sectoraddress&0xfe00);//扇區地址賦值 ISP_ADDRH=(uchar)(isectoraddress>>8);//高8位字節地址 ISP_ADDRL=0x00;//低8位字節地址復位 ISP_CMD=ISP_CMD&0xf8;//清除低3位 ISP_CMD=ISP_CMD|ISP_EraseCommand;//擦除命令3 ActiveOperate();//觸發執行 CLOSE_ISP_IAP();//關閉ISP/IAP功能 } void WriteByte(uint byteaddress,uchar originaldata)//寫字節函數 { ISP_ADDRH=(uchar)(byteaddress>>8);//高8位字節地址 ISP_ADDRL=(uchar)(byteaddress&0x00ff);//低8位字節地址 ISP_CMD=ISP_CMD&0xf8;//清除低3位 ISP_CMD=ISP_CMD|ISP_WriteCommand;//寫命令2 ISP_DATA=originaldata;//寫入數據准備 ActiveOperate();//觸發執行 CLOSE_ISP_IAP();//關閉ISP/IAP功能 } void ShuMaGuanDisplayValue(uint value)//數碼管顯示數值函數 { qian=value/1000;//數碼管千位變量 bai=value%1000/100;//數碼管百位變量 shi=value%100/10;//數碼管十位變量 ge=value%10;//數碼管個位變量 // // P2=0xfe;//數碼管千位顯示位 // P0=table[qian];//數碼管千位數值顯示 // Delay(5);//延時 // P2=0xfd;//數碼管百位顯示位 // P0=table[bai];//數碼管百位數值顯示 // Delay(5);//延時 // P2=0xfb;//數碼管十位顯示位 // P0=table[shi];//數碼管十位數值顯示 // Delay(5);//延時 // P2=0xf7;//數碼管個位顯示位 // P0=table[ge];//數碼管個位數值顯示 // Delay(5);//延時 weixuan=1; P0=0xfe;//數碼管千位顯示位 weixuan=0; duanxuan=1; P0=table[qian];//數碼管千位數值顯示 duanxuan=0; P0=0xff; Delay(5);//延時 weixuan=1; P0=0xfd;//數碼管百位顯示位 weixuan=0; duanxuan=1; P0=table[bai];//數碼管百位數值顯示 duanxuan=0; P0=0xff; Delay(5);//延時 weixuan=1; P0=0xfb;//數碼管十位顯示位 weixuan=0; duanxuan=1; P0=table[shi];//數碼管十位數值顯示 duanxuan=0; P0=0xff; Delay(5);//延時 weixuan=1; P0=0xf7;//數碼管個位顯示位 weixuan=0; duanxuan=1; P0=table[ge];//數碼管個位數值顯示 duanxuan=0; P0=0xff; Delay(5);//延時 } void Timer0Init()//定時器0初始化 { TMOD=0x01;//設定定時器類型為定時器0,定時器工作模式為模式0。 TH0=(65536-50000)/256;//TH0裝初值 TL0=(65536-50000)%256;//TL0裝初值 EA=1;//開啟定時器總中斷 ET0=1;//開啟定時器0中斷開關 TR0=1;//啟動定時器0 } void Timer0() interrupt 1//定時器0中斷函數 { TH0=(65536-50000)/256;//TH0重新裝值 TL0=(65536-50000)%256;//TL0重新裝值 count++;//定時器0中斷次數變量先賦值再加 } void main()//主函數 { Timer0Init();//定時器0初始化函數 value=ReadByte(0x2004)*1000+ReadByte(0x2003)*100+ReadByte(0x2002)*10+ReadByte(0x2001);//斷電后,讀取EEPROM存儲器掉電保存的數據。 if(value>=3600)//判斷數值變量是否大於等於3600 value=0;//數值變量置0 while(1)//固定循環 { if(count==18)//判斷定時器0中斷次數變量是否為18次 { count=0;//定時器0中斷次數變量歸零 value++;//數值變量先賦值再加 valueqian=value/1000;//數值變量千位變量 valuebai=value%1000/100;//數值變量百位變量 valueshi=value%100/10;//數值變量十位變量 valuege=value%10;//數值變量個位變量 SectorErase(0x2000);//擦除EEPROM第一扇區 WriteByte(0x2004,valueqian);//對EEPROM第一扇區第4個扇區地址(從第0個扇區地址數起)重新寫入數據 WriteByte(0x2003,valuebai);//對EEPROM第一扇區第3個扇區地址(從第0個扇區地址數起)重新寫入數據 WriteByte(0x2002,valueshi);//對EEPROM第一扇區第2個扇區地址(從第0個扇區地址數起)重新寫入數據 WriteByte(0x2001,valuege);//對EEPROM第一扇區第1個扇區地址(從第0個扇區地址數起)重新寫入數據 if(value==3600)//判斷數值變量是否達到3600 { value=0;//數值變量歸零 } } ShuMaGuanDisplayValue(value);//數碼管顯示數值 } }

