希望能给大家提供经验,51单片机做的状态机应用程序的电子表
- #include <REGX51.H>
- #include <intrins.h>
- typedef unsigned char uint8;
- #define NT 29
- const uint8 THH=(65536-2000+NT)/256;
- const uint8 TLL=(65536-2000+NT)%256;
- uint8 code SEG7CC[]={0x3F,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x0};
- uint8 volatile LED[]={2,3,5,9,5,0};
- volatile uint8 hour=23;
- volatile uint8 minute=59;
- volatile uint8 sec=50;
- volatile uint8 mode=0;
- volatile uint8 isAddPush=0;
- void timeDly(unsigned int n);
- void tickProc();
- void main()
- {
- //char i,temp;
- EA=1; //总中断开关
- ET0=1; //分中断开关
- TMOD = 1; //设置为 16 位定时器模式。
- TR0=1; //启动定时器 T0
- ET1=1;
- TR1=1;
- TMOD |= 0x10; //不更改原先的代码
- PT0 =1;//时间的刷新比按键更重要
- PT1 =1;// 时间的刷新比按键更重要
- EX0=1;
- EX1=1;
- IT0=1;
- IT1=1;
- while(1)
- {
- tickProc();
-
- }
- } void tickProc()
- { static uint8 N=0;//记录调用次数,实现闪烁
- switch(mode)
- {
- case 0://正常运行模式下,N 不变,秒定时器运行
- TR1 =1;
- break;
- case 1://模式 1 下,小时闪
- TR1 =0;
- N++;
- if(isAddPush)//如果有加键按下,小时加
- { if(++hour>23) hour=0;
- isAddPush=0;
- }
- if(N%2==0) //N 为偶数,小时数字灭
- {
- LED[0]=10;
- LED[1]=10;
- }
- else //N 为奇数,小时恢复正常数字,实现闪烁
- {
- LED[0]=hour/10;
- LED[1]=hour%10;
- }
- timeDly(500);
- break;
- case 2:
- TR1 =0;
- N++;
- if(isAddPush)
- { if(++minute>59) minute=0; isAddPush=0; }
- if(N%2==0)
- { LED[2]=10; LED[3]=10; }
- else
- { LED[2]=minute/10; LED[3]=minute%10; }
- timeDly(500);
- break;
- case 3:
- TR1 =0;
- N++;
- if(isAddPush)
- { if(++sec>59) sec=0; isAddPush=0; }
- if(N%2==0)
- { LED[4]=10; LED[5]=10; }
- else
- {
- LED[4]=sec/10; LED[5]=sec%10;
- }
- timeDly(500);
- break;
- default: mode=0;//增强抗干扰能力
- }
- }
- void int0ISR()interrupt 0
- { timeDly(10);//消除抖动
- IE0 =0;//二次进入同类中断,中断标志位会保留,防止处理 2 次。
- if(P3_2) return;//松开按键,后边沿,不处理
- if(++mode>3) mode=0;
- LED[0]=hour/10; //模式变后,闪的位置也会变,要重置正常显示情况
- LED[1]=hour%10;
- LED[2]= minute/10;
- LED[3]= minute%10;
- LED[4] = sec/10;
- LED[5] = sec%10; }
- void int1ISR() interrupt 2
- { timeDly(10);
- IE1 =0;
- if(P3_3) return;
- isAddPush=1;//有按键则置位标志位,这个处理较为复杂,在主循环中处理。
- }
-
- void timeDly(unsigned int n)
- {
- unsigned int i;
- for(; n>0; n--)
- for(i=123; i>0; i--);
- }
- void t1ISR() interrupt 3
- {
- static uint8 N=0;//记录中断次数
- TH1 = (65536-62500)/256;
- TL1 = (65536-62500)%256;
-
- if(++N>=16)
- {
- N=0;
- ET0 =0;//时分秒比显示定时刷新重要,暂时先关刷新中断
- if(++sec>59)
- {
- sec=0;
- if(++minute>59)
- {
- minute =0;
- if(++hour>23)
- hour=0;
- }
- }
- LED[0]=hour/10;//时分秒有改变,重置显示缓冲区
- LED[1]=hour%10;
- LED[2]= minute/10;
- LED[3]= minute%10;
- LED[4] = sec/10;
- LED[5] = sec%10;
-
- ET0 =1;
- }
- }
- void t0ISR() interrupt 1
- {
- static uint8 N=0;
-
- switch(N)
- {
- case 0:
- P2 = (1<<5);
- P1 = SEG7CC[ LED[5]];
- break;
- case 1:
- P2 = (1<<4);
- if(LED[4]!=0)
- P1 = SEG7CC[ LED[4]];
- else
- P1 = SEG7CC[10];//秒高位为 0,则不显示
- break;
- case 2:
- P2 = (1<<3);
- P1 = SEG7CC[ LED[3]];
- if(mode==0) //如果是正常显示,则将这个位置的小数点点亮
- P1 = SEG7CC[ LED[3]] | 0x80;
- break;
- case 3:
- P2 = (1<<2);
- if(LED[2]!=0)
- P1 = SEG7CC[ LED[2]];
- else
- P1 = SEG7CC[10];//分钟高位为 0,则不显示
- break;
- case 4:
- P2 = (1<<1);
- P1 = SEG7CC[ LED[1]];
- if(mode==0) //如果是正常显示,则将这个位置的小数点点亮
- P1 = SEG7CC[ LED[1]] | 0x80;
- break;
- case 5:
- P2 = 1;
- if(LED[0]!=0)
- P1 = SEG7CC[LED[0]];
- else
- P1 = SEG7CC[10];//小时高位为 0,则不显示
- break;
- default:
- N=0;//出错,令 N 归零。
- }
- if(++N>5) N=0;
- TH0 = THH;
- TL0 = TLL;
-
- }
复制代码
所有资料打包下载:
新建文件夹.rar
(51.65 KB, 下载次数: 14)
|