#include <STC12C2052AD.h>
#include <intrins.h>
sbit COM1 = P3^0;
sbit COM2 = P3^7;
sbit SCR = P3^4;
sbit Shift = P3^5;
sbit Start = P3^3;
sbit Key = P3^1;
sbit LED = P1^7;
sbit INT = P3^2;
bit run_flag,ws_flag;
unsigned char ds_led;
unsigned char countH,timeH,countL,timeL;
unsigned char keyInt1,keyInt2;
unsigned char FINT0;
unsigned char int_flag,sht,shts;
unsigned char cnt,dtime,runtime,wtime;
unsigned char v,val,remoh,remol;
unsigned char ds1,ds2,atd;
unsigned char code Tab[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
#define DEBUG_DATA 0x55 //存储在 EEPROM 单元的数值(用户可修改测试)
#define DATA_FLASH_START_ADDRESS 0x00 //EEPROM存入地址(用户可修改测试)
#define ENABLE_ISP 0x82 //系统工作时钟<20MHz 时,对IAP_CONTR 寄存器设置此值
union union_temp16
{
unsigned int un_temp16;
unsigned char un_temp8[2];
}my_unTemp16;
/*************************************************************************/
//去抖动延时
/*
void delay(void)
{unsigned char i,j;
for(i = 50;i > 0;i--)
{
for(j = 255;j > 0;j--) _nop_();
}
} */
/*********************************************************************************************/
void ISP_Disable(void)
{
//关闭IAP 功能, 清相关的特殊功能寄存器,使CPU 处于安全状态,
//一次连续的IAP 操作完成之后建议关闭IAP 功能,不需要每次都关
ISP_CONTR = 0; //关闭IAP 功能
ISP_CMD = 0; //清命令寄存器,使命令寄存器无命令,此句可不用
ISP_TRIG = 0; //清命令触发寄存器,使命令触发寄存器无触发,此句可不用
ISP_ADDRH = 0;
ISP_ADDRL = 0;
}
/*********************************************************************************************/
//擦除扇区, 入口:DPTR = 扇区地址
void Sector_Erase(unsigned int add)
{
ISP_CONTR = ENABLE_ISP; //打开IAP 功能, 设置Flash 操作等待时间
ISP_CMD = 0x03; //IAP/ISP/EEPROM 扇区擦除命令
my_unTemp16.un_temp16 = add;
ISP_ADDRH = my_unTemp16.un_temp8[0]; //设置目标单元地址的高8 位地址
ISP_ADDRL = my_unTemp16.un_temp8[1]; //设置目标单元地址的低8 位地址
ISP_TRIG = WD1; //先送 WD1,再送WD2 到ISP/IAP 触发寄存器,每次都需如此
ISP_TRIG = WD2; //送完WD2 后,ISP/IAP 命令立即被触发起动
_nop_();
ISP_Disable(); //关闭IAP 功能, 清相关的特殊功能寄存器,使CPU 处于安全状态,
//一次连续的IAP 操作完成之后建议关闭IAP 功能,不需要每次都关
}
/*********************************************************************************************/
//读一字节,调用前需打开IAP 功能,入口:DPTR = 字节地址,返回:A = 读出字节
unsigned char Byte_Read(unsigned int add)
{
ISP_DATA = 0x00;
ISP_CONTR = ENABLE_ISP; //打开IAP 功能, 设置Flash 操作等待时间
ISP_CMD = 0x01; //IAP/ISP/EEPROM 字节读命令
my_unTemp16.un_temp16 = add;
ISP_ADDRH = my_unTemp16.un_temp8[0]; //设置目标单元地址的高8 位地址
ISP_ADDRL = my_unTemp16.un_temp8[1]; //设置目标单元地址的低8 位地址
ISP_TRIG = WD1; //先送 WD1,再送WD2 到ISP/IAP 触发寄存器,每次都需如此
ISP_TRIG = WD2; //送完WD2 后,ISP/IAP 命令立即被触发起动
_nop_();
ISP_Disable(); //关闭IAP 功能, 清相关的特殊功能寄存器,使CPU 处于安全状态,
//一次连续的IAP 操作完成之后建议关闭IAP 功能,不需要每次都关
return(ISP_DATA);
}
/*********************************************************************************************/
//字节编程,调用前需打开IAP 功能,入口:DPTR = 字节地址, A= 须编程字节的数据
void Byte_Program(unsigned int add, unsigned char ch)
{
ISP_CONTR = ENABLE_ISP; //打开 IAP 功能, 设置Flash 操作等待时间
ISP_CMD = 0x02; //IAP/ISP/EEPROM 字节编程命令
my_unTemp16.un_temp16 = add;
ISP_ADDRH = my_unTemp16.un_temp8[0]; //设置目标单元地址的高8 位地址
ISP_ADDRL = my_unTemp16.un_temp8[1]; //设置目标单元地址的低8 位地址
ISP_DATA = ch; //要编程的数据先送进IAP_DATA 寄存器
ISP_TRIG = WD1; //先送 WD1,再送WD2 到ISP/IAP 触发寄存器,每次都需如此
ISP_TRIG = WD2; //送完WD2 后,ISP/IAP 命令立即被触发起动
_nop_();
ISP_Disable(); //关闭IAP 功能, 清相关的特殊功能寄存器,使CPU 处于安全状态,
//一次连续的IAP 操作完成之后建议关闭IAP 功能,不需要每次都关
}
void time0(void) interrupt 1 using 1 //定时100uS
{
TH0 = 0xff;
TL0 = 0x9b;
if(FINT0 == 1) remoh++;
cnt++;
if(cnt > 199)
{
cnt = 0;
if(sht == 1) shts++;
if(Key)
{
if((wtime < 250)&&(ws_flag == 1)) wtime++;
}
}
}
void LED_display(void)
{
if((int_flag == 0)&&(ds1 == 0))
{
ds2 = 0;
COM1 = 1;
COM2 = 0;
if(ds_led == 0) P1 = Tab[countH];
else P1 = (Tab[timeH] | 0x80);
ds1 = 1;
if((!Shift)&&(sht == 0)) {ds_led = 1 - ds_led;sht = 1;}
if(!Key) {wtime = 0;keyInt1++;}
else keyInt1 = 0;
if(keyInt1 > 6)
{
ws_flag = 1;
if(ds_led == 0)
{
if((countH == 9)&&(countL == 9)) _nop_();
else
{
if(countL == 9) {countL = 0;countH++;}
else countL++;
}
}
else
{
if((timeH == 9)&&(timeL == 9)) _nop_();
else
{
atd = 1;
if(timeL == 9) {timeL = 0;timeH++;}
else timeL++;
}
}
keyInt1 = 0;
}
}
if((int_flag == 1)&&(ds2 == 0))
{
ds1 = 0;
COM1 = 0;
COM2 = 1;
if(ds_led == 0) P1 = Tab[countL];
else P1 = (Tab[timeL] | 0x80);
ds2 = 1;
if(!Key) {wtime = 0;keyInt2++;}
else keyInt2 = 0;
if(keyInt2 > 6)
{
ws_flag = 1;
if(ds_led == 0)
{
if((countH == 0)&&(countL == 0)) _nop_();
else
{
if(countL == 0) {countL = 9;countH--;}
else countL--;
}
}
if((ds_led == 1)&&(atd == 0))
{
if((timeH == 0)&&(timeL == 0)) _nop_();
else
{
if(timeL == 0) {timeL = 9;timeH--;}
else timeL--;
}
}
keyInt2 = 0;
}
}
}
void EX0Int() interrupt 0 using 1
{
remoh = 0;
SCR = 1;
TR0 = 1;
int_flag = 1 - int_flag;
if(run_flag) runtime++;
FINT0 = 1;
}
//按键扫描
/*
void key_scan(void)
{
if(!Shift)
{
delay();
if(!Shift)
{
ds_led = 1 - ds_led;
while(!Shift)
{
if(Shift) break;
}
}
}
} */
//主程序
main(void)
{
TMOD = 0x21;
WDT_CONTR = 0x3C;
TH0 = 0xff;
TL0 = 0x9b; //定时100uS
IT0 = 1;
EX0 = 1;
ET0 = 1;
EA = 1;
SCR = 1;
countH = Byte_Read(0x00)/10;
countL = Byte_Read(0x00)%10;
if(countH > 6) {countH = 0;countL = 0;}
timeH = Byte_Read(0x01)/10;
timeL = Byte_Read(0x01)%10;
if(timeH > 6) {timeH = 0;timeL = 0;}
ds_led = 0;
while(1)
{
// key_scan();
if((shts > 15)&&(Shift)) {sht = 0;shts = 0;}
LED_display();
WDT_CONTR = 0x3C;
if(!Start)
{
val = 100 - (countH * 10 + countL);
if(val > 75) val = 75;
if(remoh == val)
{
if(runtime < timeH *10 + timeL) {SCR = 0;run_flag = 1;}
else {run_flag = 0;SCR = 1;}
}
if(remoh == 90) {SCR = 1;remoh = 0;FINT0 = 0;TR0 = 0;}
}
if((ws_flag == 1)&&(wtime > 50))
{
atd = 0;
ws_flag = 0;
wtime = 0;
Sector_Erase(0x00);
Byte_Program(0x00,countH * 10 + countL);
Byte_Program(0x01,timeH * 10 + timeL);
}
if(Start)
{
SCR = 1;
remoh = 0;
remol = 0;
run_flag = 0;
runtime = 0;
}
}
}