|
#include <reg52.h> //用52的头文件 里面加的引脚再定义
#include "intrins.h" //延时
sfr AUXR = 0x8e;
sfr P5 = 0xc8; //p5定义 是加的
sfr P5M0 = 0xc9;
sfr P5M1 = 0XCA;
sfr P3M0 = 0xb2; //p3口设置强推完的定义
sfr P3M1 = 0Xb1;
sfr P1M0 = 0x92; //p0口设置强推完的定义 这样设置数码管就亮
sfr P1M1 = 0X91;
/***********************掉电存储开始********************/
typedef unsigned char BYTE;
typedef unsigned int WORD; //类型定义
unsigned char x = 0;
sfr IAP_DATA = 0xC2; //IAP数据寄存器
sfr IAP_ADDRH = 0xC3; //IAP地址寄存器高字节
sfr IAP_ADDRL = 0xC4; //IAP地址寄存器低字节
sfr IAP_CMD = 0xC5; //IAP命令寄存器
sfr IAP_TRIG = 0xC6; //IAP命令触发寄存器
sfr IAP_CONTR = 0xC7; //IAP控制寄存器
#define CMD_IDLE 0 //空闲模式
#define CMD_READ 1 //IAP字节读命令
#define CMD_PROGRAM 2 //IAP字节编程命令
#define CMD_ERASE 3 //IAP扇区擦除命令
#define ENABLE_IAP 0x82 //if SYSCLK<20MHz
#define IAP_ADDRESS 0x0400 //测试地址
//void Delay(BYTE n);
void IapIdle();
BYTE IapReadByte(WORD addr);
void IapProgramByte(WORD addr, BYTE dat);
void IapEraseSector(WORD addr);
/***********************掉电存储结束****************/
/*****************************数码管开始***********************************/
unsigned int i = 0;//用于扫描数码管
unsigned char bainum1 = 0;//百
unsigned char shinum1 = 0;//十
unsigned char genum1 = 0;//个
sbit pa = P1^0;sbit pb = P3^2;sbit pc = P3^7;sbit pd = P1^3;//数码管段
sbit pe = P1^2;sbit pf = P1^4;sbit pg = P3^3;//数码管段
sbit p1 = P1^1;sbit p2 = P3^6;sbit p3 = P5^5;//数码管位
void s0();void s1();void s2();void s3();void s4();void s5();//数码管部分
void s6();void s7();void s8();void s9();void s10();//数码管部分
void xuaze(unsigned char j);//数码管段显示
void displaynum(unsigned int);//显示函数
//unsigned char code duan [] ={0,1,2,3,4,5,6,7,8,9};
unsigned int bainum11=0,shinum11=0,genum11=0;//用于传到数码管上显示
/*****************************数码管结束***********************************/
unsigned int inum1=0,inum2=0;//触发端子用的计数
unsigned char inum11=0,inum12=0,inum21=0,inum22=0,ss=0;//掉电存储要用到
static unsigned char presstime=0;//时间值按键用到的
unsigned int kf0=1;//按键用的标志位
unsigned int kt0=0;//按键用的标志位
unsigned int if0=1,if0s=1,it0=0;
unsigned int mm=0,ff=0,sss=0;//计数用
bit flag_eeprom1=1;//掉电存储的标志位
unsigned int keynum=0;//数码管的位
sbit key2=P3^0;//按键
sbit key1=P3^1;//按键
sbit out= P5^4;//输出
void timer0_1init();//定时器声明
void keycan();//按键
void keyflag();//按键结束调用
void saveeepro();//掉电存储
extern void displaynums();//将数字传到数码管上显示
void main()
{
timer0_1init();
P3M0 = 0xcc;
P3M1 = 0X00; //p3口设置强推挽
P1M0 = 0x1f;
P1M1 = 0X00;
inum11 = IapReadByte(1);//读取掉电存储里的值
inum12 = IapReadByte(2);
inum21 = IapReadByte(3);
inum22 = IapReadByte(4);
if0 = IapReadByte(5);
if0s = IapReadByte(6);
ss = IapReadByte(7);
inum1=inum11*100+inum12;//组合掉电存储中的值
inum2=inum21*100+inum22;
bainum11=inum1/100;//传到数码管显示
shinum11=inum1/10%10;
genum11=inum1%10;
while(1){
keycan();//按键
}
}
void keycan(){//按键
if(keynum==0){//当按键值等于0的时候调用显示
displaynums();//数码管的显示
if(if0s==0){//当if0s等于0时,继电器输出
out=0;
}
if((flag_eeprom1==1)){//加掉电存储
saveeepro();//掉电存储
flag_eeprom1=0;
}
}
if(key1==0){//当按键1按下
if(kf0){//当标志位kf0=1的时候进行
if(presstime>50){//当时间值大于一百的时候
kf0=0;//标志位kf0=0
kt0=1;//标志位kt0=0
flag_eeprom1=1;if0s=1;out=1;if0=1;
presstime=0;//时间清零,重新进行
keynum++;//数码管的位
if(keynum==4){//当位到4则置位0
keynum=0;
if0=0;
}
if(out==0){
if0=0;
}
}
}
}else{//当按键松开
keyflag();
if((flag_eeprom1==1)){ //加掉电存储,必需加到这,不然有一些小问题
flag_eeprom1=0;
saveeepro();//掉电存储
}
}//按键1结束
if(key2==0){if(kf0){if(presstime>50){kf0=0;kt0=1;presstime=0;flag_eeprom1=1;//掉电存储的标志位改为1,进行存值操作
// if(out==0){
// if0=0;if0s=1;out=1;
// }
switch(keynum){
case 1:
bainum11++;//数码管一加加
if(bainum11>9){//当数码管一加加到9时置为1
bainum11=0;
}
break;
case 2:shinum11++;if(shinum11>9){shinum11=0;}break;
case 3:genum11++;if(genum11>9){genum11=0;}break;
default:break;
}
}}}else{keyflag();displaynums();
if((flag_eeprom1==1))//加掉电存储,必需加到这,不然有一些小问题
{ flag_eeprom1=0;
saveeepro();//掉电存储
}
}//松开按键进行显示
}
void tm0_isr() interrupt 1 using 1
{//500等1s
TL0 = 0x18; //设置定时初值
TH0 = 0xFC; //设置定时初值
presstime++;
i++;
if (if0==0){//当if0==0时开始倒计时
mm++;
if(mm==500){//一秒时间到
mm=0;
ff++;
if(ff>60){//一分钟
ff=0;
sss++;
ss=sss;
flag_eeprom1=1;
if(sss>60){//一小时
sss=0;
inum2--;
flag_eeprom1=1;
if(inum2==0){
if0s=0;//继电器输出
if0=1;//返回设置的时长
flag_eeprom1=1;
}
}
}
}
}
switch (i){
case 1: s10(); xuaze(bainum1); if(keynum==1 || keynum==0){p1 = 0;}p2 = 1;p3 = 1;break;
case 2: s10(); xuaze(shinum1); if(keynum==2 || keynum==0){p2 = 0;}p1 = 1;p3 = 1;break;
case 3: s10(); xuaze(genum1); if(keynum==3 || keynum==0){p3 = 0;}p1 = 1;p2 = 1;break;
default:i=0;s10(); break;
}
}
void timer0_1init(){//定时器声明
TMOD=0x11;//将定时器0,1都设置为模式1
TL0 = 0x18; //设置定时初值
TH0 = 0xFC; //设置定时初值
TR0=1;//开启定时器0
TR1=1;//开启定时器1
EA=1;//开总中断
ET0=1;//开定时器0的中断
}
/**********************数码管显示部分开始**************************/
void displaynums(){//将数字传到数码管上显示
if (if0==0){//当if0==0时num1三个数码管进行显示
genum1=inum2%10;//个位
shinum1=inum2/10%10;//十位
bainum1=inum2/100;//百
}else{
bainum1=bainum11;
shinum1=shinum11;
genum1=genum11;
inum1=bainum11*100+shinum11*10+genum11; //将num1三个数码管的值付给inum
inum2=inum1;
}
}
void s0(){pa = 1;pb = 1;pc = 1;pd = 1;pe = 1;pf = 1;pg = 0;}
void s1(){pb = 1;pc = 1;pa = 0;pg = 0;pd = 0;pe = 0;pf = 0;}
void s2(){pa = 1;pb = 1;pg = 1;pe = 1;pd = 1;pf = 0;pc = 0;}
void s3(){pa = 1;pb = 1;pg = 1;pc = 1;pd = 1;pf = 0;pe = 0;}
void s4(){pb = 1;pg = 1;pc = 1;pf = 1;pa = 0;pd = 0;pe = 0;}
void s5(){pa = 1;pg = 1;pc = 1;pd = 1;pf = 1;pe = 0;pb = 0;}
void s6(){pa = 1;pg = 1;pc = 1;pd = 1;pf = 1;pe = 1;pb = 0;}
void s7(){pa = 1;pb = 1;pc = 1;pf = 0;pe = 0;pd = 0;pg = 0;}
void s8(){pa = 1;pb = 1;pg = 1;pc = 1;pd = 1;pf = 1;pe = 1;}
void s9(){pa = 1;pb = 1;pg = 1;pc = 1;pd = 1;pf = 1;pe = 0;}
void s10(){pa =0;pb = 0;pc = 0;pf = 0;pe = 0;pd = 0;pg = 0;}
void xuaze(unsigned char j){
if(j == 0){s0();}
else if(j == 1){s1();}
else if(j == 2){s2();}
else if(j == 3){s3();}
else if(j == 4){s4();}
else if(j == 5){s5();}
else if(j == 6){s6();}
else if(j == 7){s7();}
else if(j == 8){s8();}
else if(j == 9){s9();}}
/**********************数码管显示部分结束**************************/
/**********************掉电存储部分开始**************************/
//掉电存储
//void Delay(BYTE n){
// WORD x;
// while (n--){x = 0;while (++x);}
//}
//关闭IAP
void IapIdle(){
IAP_CONTR = 0; //关闭IAP功能
IAP_CMD = 0; //清除命令寄存器
IAP_TRIG = 0; //清除触发寄存器
IAP_ADDRH = 0x80; //将地址设置到非IAP区域
IAP_ADDRL = 0;
}
//从ISP/IAP/EEPROM区域读取一字节
BYTE IapReadByte(WORD addr){
BYTE dat; //数据缓冲区
IAP_CONTR = ENABLE_IAP; //使能IAP
IAP_CMD = CMD_READ; //设置IAP命令
IAP_ADDRL = addr; //设置IAP低地址
IAP_ADDRH = addr >> 8; //设置IAP高地址
IAP_TRIG = 0x5a; //写触发命令(0x5a
IAP_TRIG = 0xa5; //写触发命令(0xa5
_nop_(); //等待ISP/IAP/EEPROM操作完
dat = IAP_DATA; //读ISP/IAP/EEPROM数据
IapIdle(); //关闭IAP功能
return dat; //返回
}
//写一字节数据到ISP/IAP/EEPROM区域
void IapProgramByte(WORD addr, BYTE dat){
IAP_CONTR = ENABLE_IAP; //使能IAP
IAP_CMD = CMD_PROGRAM; //设置IAP命令
IAP_ADDRL = addr; //设置IAP低地址
IAP_ADDRH = addr >> 8; //设置IAP高地址
IAP_DATA = dat; //写ISP/IAP/EEPROM数据
IAP_TRIG = 0x5a; //写触发命令(0x5a
IAP_TRIG = 0xa5; //写触发命令(0xa5
_nop_(); //等待ISP/IAP/EEPROM操作完
IapIdle();
}
//扇区擦除
void IapEraseSector(WORD addr){
IAP_CONTR = ENABLE_IAP; //使能IAP
IAP_CMD = CMD_ERASE; //设置IAP命令
IAP_ADDRL = addr; //设置IAP低地址
IAP_ADDRH = addr >> 8; //设置IAP高地址
IAP_TRIG = 0x5a; //写触发命令(0x5a
IAP_TRIG = 0xa5; //写触发命令(0xa5
_nop_(); //等待ISP/IAP/EEPROM操作完
IapIdle();
}
void saveeepro(){//掉电存储
inum11=inum1/100;//把int型的值拆分到char型
inum12=inum1%100;
inum21=inum2/100;
inum22=inum2%100;
IapEraseSector(0);
IapProgramByte(1, inum11);//数值1
IapProgramByte(2, inum12);
IapProgramByte(3, inum21);
IapProgramByte(4, inum22);
IapProgramByte(5, if0);//倒计时的状态
IapProgramByte(6, if0s);//继电器的状态
IapProgramByte(7, ss);//存分
}
/**********************掉电存储部分结束**************************/
void keyflag(){//按键结束调用,按键的建议使用,这样可以减小code,但是触发的不建议
if(kt0){//当标志位kt0=1的时候进行
if(presstime>50){//当时间值大于一百的时候
kf0=1;//标志位kf0=1
kt0=0;//标志位kt0=0
presstime=0;//时间清零,重新进行
}
}
}
|
|