标签:驱动 技术 推荐 com 版权 break class 逻辑 外部中断
功能需求概述
源代码:
#include <reg51.h> #define uint unsigned int #define uchar unsigned char uchar code seg[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90}; //共阳极数码管编码表0-9显示 sbit key1 = P1^0; sbit key2 = P1^1; sbit key3 = P1^2; sbit key4 = P1^3; sbit begin = P2^1; sbit clear = P2^2; sbit addtime = P3^2; //按键定义 sbit P2_4 = P2^4; sbit P2_5 = P2^5; sbit P2_6 = P2^6; sbit P2_7 = P2^7; //数码管显示控制 sbit sounder = P3^7; //喇叭控制 bit key1_flag = 0; bit key2_flag = 0; bit key3_flag = 0; bit key4_flag = 0; bit begin_flag = 0; bit clear_flag = 0; //按键标志位 bit a = 0; uchar second = 0; uchar b=0; uchar c=0; uchar i=0; uchar j=1; uchar k=0; uchar number=0; uchar number_display=0; void delay(uint m) { uchar n; while(m--) { for(n=0;n<120;n++); } } void display(uchar number,uchar second) // 数码管显示驱动函数 { uchar second_first,second_second; second_first=second/10; second_second=second%10; //将秒数分成两位 P2_7=0; P2_4=1; //选通第一个数码管 P0=0xc0 ; //显示0 delay(2); P2_4=0; P2_5=1; //选通第二个 P0 = seg[number]; //显示编码数字 delay(2); P2_5=0; P2_6=1; //选通第三个 P0=seg[second_first]; //显示一位秒数 delay(2); P2_6=0; P2_7=1; //选通第四个 P0=seg[second_second]; //显示另一位秒数 delay(2); } void display2() //显示00功能 { P2_7=0; P2_6=1; //选通一位秒表数码管 P0 =seg[0]; //显示0 delay(2); P2_6=0; P2_7=1; //选通另一位秒表数码管 P0=seg[0]; //显示0 delay(2); } uchar key_scan4() //四位抢答键扫描函数 { if(key1==0) //如果按键1按下 { delay(10); //防抖动延时 if((key1==0)&&(!key1_flag)) //如果仍旧按下 { key1_flag=1; number=1; //数字变量赋值1 number_display=number; } } else { key1_flag = 0; number = 0; } if(key2==0) { delay(10); if((key2==0)&&(!key2_flag)) { key2_flag=1; number=2; number_display=number; } } else { key2_flag=0; number=0; } if(key3==0) { delay(10); if((key3==0)&&(!key3_flag)) { key3_flag=1; number=3; number_display=number; } } else { key3_flag=0; number=0; } if(key4==0) { delay(10); if((key4==0)&&(!key4_flag)) { key4_flag=1; number=4; number_display=number; } } else { key4_flag=0; number=0; } if(number_display!= 0) { return 1; } else { return 0; //返回值控制是否有键按下 } } void begin_keyscan() //开始键扫描函数 { if(begin==0) //启动按下 { delay(10); //防抖动延时 if((begin==0)&&(!begin_flag)) //如果还是按下,同时标志位为0 { begin_flag=1; //标志位置1 sounder=0; //喇叭响 j=1; b=0; //辅助循环变量 a=1; if(second!=0) //秒数不为0 { TR0=1; //打开定时器0 } } } else { begin_flag=0; } } void reset_keyscan() //复位键扫描函数 { if(clear==0) { delay(10); //防抖动 if((clear == 0)&&(!clear_flag))//如果仍旧按下 { clear_flag=1; number_display=0; sounder=1; //关闭喇叭 j=0; b=1; //循环控制变量赋值,可跳出主程序的某个死循环 } } else { clear_flag=0; } } void main() { TMOD=0x01; TH0=0x3c; TL0=0xb0; //定时0.05s EA=1; EX0=1; ET0=1; IT0=1; TR0=0; while(1) { begin_keyscan(); //判断是否按了开始 reset_keyscan(); //判断是否复位 second=c; //每次将按键加的秒数实时显示 while(a) //当开始按下 { while(!key_scan4()) //当无人抢答 { display(number_display,second); //显示号码和秒数,一秒后时间减一显示 while((second==0)&&(j==1)) //减到0同时j=1 { display2(); //显示00 sounder=0; //报警 reset_keyscan(); //按下复位j=0,跳出循环 } if(second==0) //如果秒数减到0,跳出抢答循环 { break; } } TR0=0; //关闭定时器 k=0; //复位0 while(b==0) { display(number_display,second); //显示当前数据 reset_keyscan(); } a=0; break; } display(number_display,second); } } void timer0() interrupt 1 { TH0=0x3c; TL0=0xb0; k++; if(k==10) //0.5s控制关闭喇叭 { sounder=1; } if(k==20) //1s控制秒数倒计时 { k=0; second--; if(second==0) { TR0=0; number_display=0; a=0; } } } void int0() interrupt 0 //外部中断,当加时按钮按下一次加时间1S { if(addtime==0) { if(i<=29) //变量控制增加秒数直到30 { i++; c=c+1; } else { i=0; c=0; } } }
代码写的逻辑很清楚,注释和很明确。推荐自动化的同学细细研读。
最后小剧场:
事情起因:卢思毅同学邀请本人代画此程序设计流程图,当时是一口答应了;后来才发现画这个程序流程图是有多难。后来到了交图时间,只能草草收场,十分尴尬;没能给学霸菇凉画出来,还耽误人时间,十分抱歉。
源代码版权声明归卢思毅所有,在此有本人只进行总结和归纳,弥补自己对单片机领域的不足。
研究汇编语言,最好看是多看看单片机这块儿。
标签:驱动 技术 推荐 com 版权 break class 逻辑 外部中断
原文地址:http://www.cnblogs.com/licongzhuo/p/7560354.html