第一部分 设计内容和要求1.1设计内容 利用keil、Proteus和C51单片机设计出快棋赛电子计时器 1.2 设计要求 1. 八个数码管分为两组,每组四个数码管动态显示对应方的定时时间,以及倒计过程,包括分钟(2位,00~99)、秒(2位,00~59) 2. 相互控制启停开关(2个) 3. 总暂停开关(用于双方选手同时休息) 4. 各自初始时间设置(选手同意情况下可以设置不同的初始时间),即可以对相应的分钟及秒分别进行初始设置 5. 任何一方的选手如果时间倒计为零,则报警并在其四个数码管上闪烁显示“LOSE” 1.3系统运行流程 程序首先进行初始化,在主程序的循环中,首先调用数据处理函数,将分和秒数值拆开储存在显示缓冲区中(即一个数组中),然后按键扫描函数,判断是否有按键按下;若有,则执行相应程序,若没有;则往下功能指示灯led函数。若功能按键按下,则亮相应的led;若无,则继续往下执警告函数。若有时间快耗完了,则执行相应程序;若无,则继续往下结束函数,若时间耗完了,则执行相应程序;若无,执行循环。这里,我用了定时器0和定时器1,定时器0用来计时间,定时器1用做动态显示。 第二部分 设计方案
程序流程
主程序流程图 按键扫描子程序 检测是否有按键按下,若无返回主程序; 若K1按下,若计时开始且功能按键记录次数为0,则是控制时间作用:红色时间暂停,蓝色时间开始;若计时暂停且功能按键记录次数不为0,则是调节时间作用:根据功能按键次数,增加对应数值 若K2按下,若计时开始且功能按键记录次数为0,则是控制时间作用:蓝色时间暂停,红色时间开始;若计时暂停且功能按键记录次数不为0,则是调节时间作用:根据功能按键次数,减少对应数值 若K3按下,全部时间暂停或者开启;(一开始时,时间都是暂停的,只有当K3按下时,红色方先开始计时) 若K4按下,记录按下次数;(作为功能按键,让K1和K2调整红色分和秒数值以及蓝色分秒数值) (注:当程序开始计时时或比赛结束时,K4按键无效)
功能指示灯程序(附加功能) 共有4个led作为指示灯,根据功能按键按下次数,亮不同的led,作为指示灯,告知使用者,你正在调整的是哪个数值。
警告子程序(附加功能) 若有一方的时间少于十秒了,则代表他的两个led就会闪烁,作为提示。
结束子程序 当一方的时间耗完了,则他的数码管会闪烁“lose”,另一方闪烁显示“win”(附加功能),并且4个led也会一起闪烁(附加功能)。
定时器0 我用做秒计时,每当秒计时到了,根据判断,减少红色时间或减少蓝色时间。
定时器1 我用做数码管的动态显示;这样能消除按键带来的显示影响。 第三部分 Proteus电路图
第四部分 keil编译结果和Proteus仿真结果Keil编译结果 Proteus仿真结果 编译和仿真都能通过没有问题。 第五部分 单片机仿真第六部分 附加功能在第二部分设计方案中,我已用红色字体标注出,这里不再赘述了。
第八部分设计心得及体会
本次课程设计中,特别是在程序编写过程中,遇到了很多的问题。但这是对我的考验一定要充满耐心,遇到问题,就去寻找解决问题的办法。我设计过程中还不断提出自己的疑点以及新的想法,联系实际应用,将课本上学习的东西运用到实际中,这些都令我受益匪浅。最终得以完成这次单片机课程设计,非常感谢老师教导。
第七部分 代码及注释- #include <reg51.h>
- #define uchar unsigned char
- #define uint unsigned int
- uchar DispBuf[8]; //显示缓冲区
- uchar DispTab[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,
- 0x90,0x88,0x83,0xC6,0xA1,0x86,0x8E,0xFF}; //LED字形码
- uchar BitTab[]={0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01 }; //LED位驱动码
- uchar redlose[]={0xC1,0xC1, 0xF9,0xC8,0xC7,0xC0,0x92,0x84};//红色时间到LED字形码
- uchar bluelose[]={0xC7,0xC0,0x92,0x84,0xC1,0xC1,0xF9,0xC8};//蓝色时间到LED字形码
- sbit k1=P1^0;
- sbit k2=P1^1;
- sbit k3=P1^2;
- sbit k4=P1^3;
- sbit L1=P3^0;
- sbit L2=P3^1;
- sbit L3=P3^2;
- sbit L4=P3^3;
- uint num,flag1=1,flag2,flag3=1;,k4num;
- uchar miao1=00,fen1=30,miao2=00,fen2=30;
- void Timer1(void) interrupt 1{
- TH0=(65536-50000)/256;//重装数值
- TL0=(65536-50000)%256;
- num++;
- if(num==20)//如果到了20次,说明一秒时间到
- {
- num=0;//清零,重新计数20次
- if(flag1==1)//红方时间减少
- {
- miao1--;//秒时间减少
- if(miao1==-1){//说明一分钟到了,重新减少一分钟,并且分钟减一
- miao1=59;
- fen1--;
- }
- }
- if(flag1==0)//蓝方时间减少
- {
- miao2--;
- if(miao2==-1){
- miao2=59;
- fen2--;
- }
-
- }
- }
- }
- void Timer2(void) interrupt 3{
- uchar tmp;
- uchar Count;
- TH1=(65536-3000)/256;//重装数值
- TL1=(65536-3000)%256;
-
- P2=BitTab[Count]; //取位值
- tmp=DispBuf[Count]; //取出待显示的数
- tmp=DispTab[tmp]; //取字形码
- P0=tmp;
- Count++;
- if(Count==8)
- Count=0;
-
-
- }
- void delay(uint xms)//延时函数
- {
- uint i,j;
- for(i=xms;i>0;i--)
-
- for(j=110;j>0;j--);
- }
-
- void keyscan(void)//按键函数
- {
- if(k1==0)//按键按下
- {
- delay(5);
- if(k1==0)//确认按键按下
- {
-
- while(!k1);//等待按键释放
- if(k4num==0&&TR0==1)//当计时开始,并且功能键记录次数为零时,作用为控制时间
- {
- if(flag1==1)//红色时间暂停,蓝色时间开始
- flag1=0;
- }
- if(k4num!=0&&TR0==0)//当计时暂停,并且功能键记录次数不为零,作用为调节时间
- {
- switch(k4num)//根据功能键次数,增加相应数值
- {
- case 1: miao1++;
- if(miao1==60)
- miao1=0;
- break;
- case 2: fen1++;
- if(fen1==100)
- fen1=0;
- break;
- case 3: miao2++;
- if(miao2==60)
- miao2=0;
- break;
- case 4: fen2++;
- if(fen2==100)
- fen2=0;
- break;
- }
- }
- }
- }
- if(k2==0){
- delay(5);
- if(k2==0){
-
- while(!k2);
- if(k4num==0&&TR0==1)//
- {
- if(flag1==0)//蓝色时间暂停,红色时间开始
- flag1=1;
- }
- if(k4num!=0&&TR0==0)//根据功能键次数,增加相应数值
- {
- switch(k4num)
- {
- case 1: miao1--;
- if(miao1==-1)
- miao1=59;
- break;
- case 2: fen1--;
- if(fen1==-1)
- fen1=99;
- break;
- case 3: miao2--;
- if(miao2==-1)
- miao2=59;
- break;
- case 4: fen2--;
- if(fen2==-1)
- fen2=99;
- break;
- }
- }
- }
-
- }
- if(k3==0)//总暂停开关
- {
- delay(5);
- if(k3==1){
- while(!k3);
- TR0=~TR0;//控制时间暂停或是开始
- k4num=0;//功能按键记录次数清零
- flag3=0;//清零标志
- }
- }
- if(k4==0)//功能按键
- {
- delay(5);
- if(k4==0){
- if(TR0==0)//当计时暂停时,这个按键才有效
- {
- flag3=1;//做标志,防止在调节时间时,调到零的时候,就进入子程序last()
- k4num++;//记录功能按键按下次数
- }
- if(k4num==5||TR0==1||flag2==1)//当带五次按下或开始计时或某一方时间耗完,清零记录次数
- {
- k4num=0;
-
- }
- while(!k4);
- }
- }
-
-
- }
- void last()//某一方时间耗完,分别显示lose和win
- {
- uint i,j;
- if(miao1==0&&fen1==0&&flag3==0)//红方时间先耗完
- {
- TR0=0;//关闭计时
- TR1=0;//关闭时间显示
- flag2=1;//标志比赛结束
- for(i=80;i>0;i--)//动态显示 lose和win 80次
- {
- for(j=0;j<8;j++){
- P2=BitTab[j];//送入位选
- P0=redlose[j];//送入lose和win的字形码
- delay(2);
- P0=0xFF;
- }
- L1=~L1;//led不断闪烁
- L2=~L2;
- L3=~L3;
- L4=~L4;
- }
- P0=0XFF;//关闭显示300ms
- P2=0X00;
- delay(300);
- }
- if(miao2==0&&fen2==0&&flag3==0)//蓝色方时间耗完
- {
- TR0=0;
- TR1=0;
- flag2=1;
- for(i=70;i>0;i--){
- for(j=0;j<8;j++){
- P2=BitTab[j];
- P0=bluelose[j];
- delay(3);
- P0=0xFF;
- }
- L1=~L1;
- L2=~L2;
- L3=~L3;
- L4=~L4;
- }
- P0=0XFF;
- P2=0X00;
- delay(100);
- }
- }
- void led()//功能按键对应的指示led灯亮或灭
- {
- switch(k4num){
- case 0: P3=0xFF;
- break;
- case 1: P3=0xF7;
- break;
- case 2: P3=0xFB;
- break;
- case 3: P3=0xFD;
- break;
- case 4: P3=0xFE;
- break;
- }
-
-
- }
- void warn(){
- if(fen1==0&&miao1<10&&TR0==1&&flag1==1)//当红色时间少于十秒的时候,闪烁led灯提示
- {
- L3=~L3;
- L4=~L4;
- }
- if(fen2==0&&miao2<10&&TR0==1&&flag1==0)//当红色时间少于十秒的时候,闪烁led灯提示
- {
- L1=~L1;
- L2=~L2;
- }
-
- }
-
- void zixing(){
- DispBuf[0]=fen2/10;
- DispBuf[1]=fen2%10;
- DispBuf[2]=miao2/10;
- DispBuf[3]=miao2%10;
- DispBuf[4]=fen1/10;
- DispBuf[5]=fen1%10;
- DispBuf[6]=miao1/10;
- DispBuf[7]=miao1%10;
-
- }
- void main(){
- TMOD=0X11;//设置T0定时方式一和T1定时方式一
- TH0=(65536-50000)/256;//装入初值,计时一秒
- TL0=(65536-50000)%256;
- TH1=(65536-3000)/256; //装入初值,计时30us
- TL1=(65536-3000)%256;
- EA=1;//打开总中断
- ET0=1;//打开定时器0中断
- ET1=1;//打开定时器1中断
- TR0=0;//暂停定时器0
- TR1=1;//开启定时器1
- while(1){
- zixing();//将分和秒数值拆开,存入显示缓冲区,等待显示
- keyscan();//按键函数
- led();//功能指示led
- warn();//当时间少于十秒时,警告函数
- last();//比赛结束,显示lose和win 函数
- }
- }
复制代码 完整的Word格式文档51黑下载地址:
庞智仁2016160111.doc
(695 KB, 下载次数: 23)
|