|
本帖最后由 PK250 于 2016-8-9 20:59 編輯
#include<reg52.h>
sfr AUXR = 0x8e;
sfr IAP_DATA = 0xC2; //IAP數(shù)據(jù)寄存器
sfr IAP_ADDRH = 0xC3; //IAP地址寄存器高字節(jié)
sfr IAP_ADDRL = 0xC4; //IAP地址寄存器低字節(jié)
sfr IAP_CMD = 0xC5; //IAP命令寄存器
sfr IAP_TRIG = 0xC6; //IAP命令觸發(fā)寄存器
sfr IAP_CONTR = 0xC7; //IAP控制寄存器
#define CMD_IDLE 0 //空閑模式
#define CMD_READ 1 //IAP字節(jié)讀命令
#define CMD_PROGRAM 2 //IAP字節(jié)編程命令
#define CMD_ERASE 3 //IAP扇區(qū)擦除命令
#define ENABLE_IAP 0x82 //if SYSCLK<20MHz
#define IAP_ADDRESS 0x0000
sbit k1 =P3^4; //按鍵
sbit led1 =P1^0; //燈1
sbit led2 =P1^1; //燈2
sbit led3 =P1^2; //燈3
unsigned char n=0;
unsigned int i;
uchar IapReadByte(unsigned int addr);
void IapProgramByte(unsigned int addr, unsigned char dat);
void IapEraseSector(unsigned int addr);
void InitTimer0(void);
void Delay10ms(unsigned int c); //誤差 0us
void delay(unsigned int t) //延時子程序
{ while(t--); } //延時子程序
void main(void) //主程序
{
InitTimer0();
i = IapReadByte(2);
while(1) //掃描按鍵
{
if(i<9000)//此處設(shè)置到期時間,單位:分鐘
{
if(k1==0) //按鍵按下
{
if(n==0)
{
led1 = 0; //燈1亮
delay(60000); //延時
led2 = 0; //燈2亮
delay(60000); //延時
led1 = 1; //燈1滅
n=1;
}
}
if(k1==1) //按鍵彈起
{
if(n==1)
{
led2 = 1; //燈2滅
led3 = 0; //燈3亮
delay(60000); //延時
led3 = 1; //燈3滅
n=0;
}
}
}
}
}
void InitTimer0(void)//60秒定時
{
TMOD = 0x01;
TH0 = 0x15;
TL0 = 0x0A0;
EA = 1;
ET0 = 1;
TR0 = 1;
}
void Timer0Interrupt(void) interrupt 1
{
TH0 = 0x15;//60秒定時
TL0 = 0x0A0;
i++;
IapEraseSector(2);
IapProgramByte(2,i);
}
/*----------------------------
從ISP/IAP/EEPROM區(qū)域sddr讀取一字節(jié)
----------------------------*/
unsigned char IapReadByte(unsigned int addr)
{
unsigned char dat; //數(shù)據(jù)緩沖區(qū)
IAP_CONTR = ENABLE_IAP; //使能IAP
IAP_CMD = CMD_READ; //設(shè)置IAP命令
IAP_ADDRL = addr; //設(shè)置IAP低地址
IAP_ADDRH = addr >> 8; //設(shè)置IAP高地址
IAP_TRIG = 0x5a; //寫觸發(fā)命令(0x5a)
IAP_TRIG = 0xa5; //寫觸發(fā)命令(0xa5)
_nop_(); //等待ISP/IAP/EEPROM操作完成
dat = IAP_DATA; //讀ISP/IAP/EEPROM數(shù)據(jù)
/* IapIdle(); /*加上這行后EEPROM操作無效*/
return dat; //返回
}
/*----------------------------
寫一字節(jié)數(shù)據(jù)到ISP/IAP/EEPROM區(qū)域
addr:要寫入的地址
dat:要寫入的數(shù)據(jù)
----------------------------*/
void IapProgramByte(unsigned int addr, unsigned char dat)
{
IAP_CONTR = ENABLE_IAP; //使能IAP
IAP_CMD = CMD_PROGRAM; //設(shè)置IAP命令
IAP_ADDRL = addr; //設(shè)置IAP低地址
IAP_ADDRH = addr >> 8; //設(shè)置IAP高地址
IAP_DATA = dat; //寫ISP/IAP/EEPROM數(shù)據(jù)
IAP_TRIG = 0x5a; //寫觸發(fā)命令(0x5a)
IAP_TRIG = 0xa5; //寫觸發(fā)命令(0xa5)
_nop_(); //等待ISP/IAP/EEPROM操作完成
/* IapIdle(); /*加上這行后EEPROM操作無效*/
}
/*----------------------------
扇區(qū)擦除 某一地址addr的數(shù)據(jù)
----------------------------*/
void IapEraseSector(unsigned int addr)
{
IAP_CONTR = ENABLE_IAP; //使能IAP
IAP_CMD = CMD_ERASE; //設(shè)置IAP命令
IAP_ADDRL = addr; //設(shè)置IAP低地址
IAP_ADDRH = addr >> 8; //設(shè)置IAP高地址
IAP_TRIG = 0x5a; //寫觸發(fā)命令(0x5a)
IAP_TRIG = 0xa5; //寫觸發(fā)命令(0xa5)
_nop_(); //等待ISP/IAP/EEPROM操作完成
/* IapIdle(); /*加上這行后EEPROM操作無效*/
}
//這種方法誤差比較大,單片機的定時中斷最多可以定時65535微秒
//如果需要斷電按上次計時處開始計時,那么需要用eeprom,把i值放在eeprom里面,上電的時候再讀取就行了
//已經(jīng)改好了,帶掉電記憶功能
|
|