各位同学们大家好~!又到了学习时间了。上一帖中有小可耐回帖,说希望在蓝桥板的代码里多看到一些注释,今天所发的数码管训练题目的帖子,在蓝桥板的代码中必要的地方都重新添加上了注释。让大家能够看得更明白。
今天的题目,主要针对按键进行讲解。有同学觉得按键很简单,但实际上,要想写出一个响应灵敏,并能够灵活触发的各种按键其实并不容易,尤其是当题目中要求我们实现双击、长按等这种不同动作种类的按键时,就更需要大家动一动自己的水灵的小脑袋了。
而且,从历年真题来看,按键和数码管是一样的,也是必考题。题目中通过按键结合数码管,设计的各种逻辑,做起来真的还是蛮有一定的挑战性的。下面咱们就来先针对按键和数码管进行综合练习。本次的练习题目和代码发出来,供大家参考学习。
题1、按下按键S4-S7,数码管分别显示键值1-4
题2、数码管初始显示0,单击S4,显示值加1,单击S5数值减1,长按S6数值连续加1,长按S7数值连续减1
下面依旧给出两个题目的代码,并在文末给出所有代码压缩包的下载链接,欢迎大家下载查看。如有任何问题,请大家在下方回帖告知~不胜感激的同时,还可能有U盘赠送的哦~
-----------------------蓝桥板代码---------------------
蓝桥板题1代码:
/********************************************* 1、按下按键S4-S7,数码管分别显示键值1-4 **********************************************/ #include<stc15f2k60s2.h> #include"intrins.h" #define uchar unsigned char #define uint unsigned int uchar code smgtab[]={0XC0,0XF9,0XA4,0XB0,0X99,0X92,0X82,0XF8,0X80,0X90,0XBF,0XFF}; //共阳数码值 uchar yi,er,san,si,wu,liu,qi,ba; void display1(uchar yi,uchar er); //第1第2两个数码管的显示函数 void display2(uchar san,uchar si); //第3第4两个数码管的显示函数 void display3(uchar wu,uchar liu ); //第5第6两个数码管的显示函数 void display4(uchar qi,uchar ba); //第7第8两个数码管的显示函数 void keyscan(); //按键扫描函数 void delayms(uint z); //毫秒级别延时函数 void init(); //单片机初始化函数 void main() { init(); yi=11;er=11;san=11;si=11;wu=11;liu=11;qi=11;ba=11; while(1) { keyscan(); display1(yi,er); display2(san,si); display3(wu,liu ); display4(qi,ba); } } void delayms(uint z) //延时函数 { uint x,y; for(x=z;x>0;x--) for(y=845;y>0;y--); } void init() { P2=0xa0; P0=0x00; //关闭继电器蜂鸣器 P2=0x80; P0=0xff; //关闭led灯 P2=0xc0; P0=0xff; //选择所有数码管 P2=0xff; P0=0xff; //关闭所有数码管 } void keyscan() //独立按键 { if(P30==0) //s7 { delayms(5); //消抖 if(P30==0) { si=4; //键值4 } while(!P30); } else if(P31==0) //s6 { delayms(5); if(P31==0) { san=3; //键值3 } while(!P31); } else if(P32==0) //s5 { delayms(5); if(P32==0) { er=2; //键值2 } while(!P32); } else if(P33==0) //s4 { delayms(5); if(P33==0) { yi=1; //键值1 } while(!P33); } } void display1(uchar yi,uchar er) { P2=0xc0; P0=0x01; //选择第一个数码管 P2=0xff; P0=smgtab[yi]; //段选 delayms(1); P2=0xc0; P0=0x02; //选择第二个数码管 P2=0xff; P0=smgtab[er]; //段选 delayms(1); } void display2(uchar san,uchar si) { P2=0xc0; P0=0x04; //选择第三个数码管 P2=0xff; P0=smgtab[san]; //段选 delayms(1); P2=0xc0; P0=0x08; //选择第四个数码管 P2=0xff; P0=smgtab[si]; //段选 delayms(1); } void display3(uchar wu,uchar liu ) { P2=0xc0; P0=0x10; //选择第五个数码管 P2=0xff; P0=smgtab[wu]; //段选 delayms(1); P2=0xc0; P0=0x20; //选择第六个数码管 P2=0xff; P0=smgtab[liu]; //段选 delayms(1); } void display4(uchar qi,uchar ba) { P2=0xc0; P0=0x40; //选择第七个数码管 P2=0xff; P0=smgtab[qi]; //段选 delayms(1); P2=0xc0; P0=0x80; //选择第八个数码管 P2=0xff; P0=smgtab[ba]; //段选 delayms(1); }
蓝桥板题2代码:
/************************************************************************************ 2、数码管初始显示0,单击S4,显示值加1,单击S5数值减1,长按S6数值连续加1,长按S7数值连续减1 (评论区有同学觉得长按的设计有点小BUG,已经在代码中重新更正,请大家验证) *************************************************************************************/ #include<stc15f2k60s2.h> #include"intrins.h" #define uchar unsigned char #define uint unsigned int #define TT 5 uchar code smgtab[]={0XC0,0XF9,0XA4,0XB0,0X99,0X92,0X82,0XF8,0X80,0X90,0XBF,0XFF}; uchar s4,s5,num; uint count; uchar One,Two,Three,Four,Five,Six,Seven,Eight; void init();//蓝桥杯板初始化程序 void keyScan();//键盘扫描 void delayms(uint z);//ms级延时函数 void displayOne(uchar One,uchar Two);//第一二个数码管显示函数 void displayTwo(uchar Three,uchar Four);//第三四个数码管显示函数 void displayThree(uchar Five,uchar Six );//第五六个数码管显示函数 void displayFour(uchar Seven,uchar Eight);//第七八个数码管显示函数 /********************主函数****************************/ /*void main() { init(); while(1) { One=11;Two=11;Three=11;Four=11;Five=11;Six=num/100;Seven=num/10%10;Eight=num%10; if(s4==1) //显示值加1 { s4=0; if((num>=0)&&(num<=255)) {num=num+1;} //uchar计数范围为0-255; else if(num>255){num=255;} } else if(s5==1) //显示值减1 { s5=0; if((num>0)&&(num<=255)) {num=num-1;} else if(num==0){num=0;} } else if(P31==0) //s6长按连续加1 { delayms(5); if(P31==0) { count=0; while(P31==0) { delayms(40); count++; } if(count>TT) { if((num>=0)&&(num<255))num=num+1; else if(num==255)num=255; } } } else if(P30==0) //s7长按连续减1 { delayms(5); if(P30==0) { count=0; while(P30==0) { delayms(40); count++; } if(count>TT) { if((num>0)&&(num<=255))num=num-1; else if(num==0)num=0; } } } keyScan(); displayOne(One,Two); displayTwo(Three,Four); displayThree(Five,Six); displayFour(Seven,Eight); } } void delayms(uint z) //延时函数 { uint x,y; for(x=z;x>0;x--) for(y=845;y>0;y--); } void init() { P2=0xa0; P0=0x00; //关闭继电器蜂鸣器 P2=0x80; P0=0xff; //关闭led灯 P2=0xc0; P0=0xff; //选择所有数码管 P2=0xff; P0=0xff; //关闭所有数码管 } void keyscan() { if(P32==0) //s5 { delayms(5); if(P32==0) { s5=1; //按键s5的标志位 } while(!P32); } else if(P33==0) //s4 { delayms(5); if(P33==0) { s4=1; //按键s4的标志位 } while(!P33); } } void displayOne(uchar One,uchar Two) { P2=0xc0; P0=0x01; //选择第一个数码管 P2=0xff; P0=smgtab[One]; //段选 delayms(1); P2=0xc0; P0=0x02; //选择第二个数码管 P2=0xff; P0=smgtab[Two]; //段选 delayms(1); } void displayTwo(uchar Three,uchar Four) { P2=0xc0; P0=0x04; //选择第三个数码管 P2=0xff; P0=smgtab[Three]; //段选 delayms(1); P2=0xc0; P0=0x08; //选择第四个数码管 P2=0xff; P0=smgtab[Four]; //段选 delayms(1); } void displayThree(uchar Five,uchar Six ) { P2=0xc0; P0=0x10; //选择第五个数码管 P2=0xff; P0=smgtab[Five]; //段选 delayms(1); P2=0xc0; P0=0x20; //选择第六个数码管 P2=0xff; P0=smgtab[Six]; //段选 delayms(1); } void displayFour(uchar Seven,uchar Eight) { P2=0xc0; P0=0x40; //选择第七个数码管 P2=0xff; P0=smgtab[Seven]; //段选 delayms(1); P2=0xc0; P0=0x80; //选择第八个数码管 P2=0xff; P0=smgtab[Eight]; //段选 delayms(1); }
-----------------------小红板代码----------------------
小红板题1代码:
/************************************************* 1、按下独立按键s5,s10,s15,s20,数码管分别显示键值1-4 **************************************************/ #include"reg52.h" #define uchar unsigned char #define uint unsigned int sbit P_HC595_SER = P2^7; //pin 14 SER data input sbit P_HC595_RCLK = P2^5; //pin 12 RCLk store (latch) clock sbit P_HC595_SRCLK = P2^6; //pin 11 SRCLK Shift data clock sbit s5=P3^0; sbit s10=P3^1; sbit s15=P3^2; sbit s20=P3^3; uchar code smgtab[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71,0x00}; uchar yi,er,san,si,wu,liu,qi,ba; void display1(uchar yi,uchar er); void display2(uchar san,uchar si); void display3(uchar wu,uchar liu); void display4(uchar qi,uchar ba); void keyscan(); void SMG_Init(); void Send_595(unsigned char dat); void delayms(uint z); void main() { SMG_Init(); yi=16;er=16;san=16;si=16;wu=16;liu=16;qi=16;ba=16; while(1) { keyscan(); display1(yi,er); display2(san,si); display3(wu,liu); display4(qi,ba); } } void delayms(uint z) //ms级别延时函数 { uint x,y; for(x=z;x>0;x--) for(y=110;y>0;y--); } void keyscan() { if(s5==0) //s5 { delayms(5); //延时消抖5-10ms if(s5==0) { yi=1; } while(!s5); // 松手检测 } else if(s10==0) //s10 { delayms(5); if(s10==0) { er=2; } while(!s10); } else if(s15==0) //s15 { delayms(5); if(s15==0) { san=3; } while(!s15); } else if(s20==0) //s20 { delayms(5); if(s20==0) { si=4; } while(!s20); } } void SMG_Init() { Send_595(0x00); //同时选择8个数码管 Send_595(0x00); //让8个数码管同时显示消隐字符 P_HC595_RCLK = 0; P_HC595_RCLK = 1; //使用P2.5制造一个上升沿将这两个字节数据同时送给数码管,完成段选和位选 } void Send_595(unsigned char dat) //发送一个字节 { unsigned char i; for(i=0; i<8; i++) { if(dat & 0x80) //判断dat的最高位是否为1 P_HC595_SER = 1; //最高位如果为1,则令P2.7 = 1 else P_HC595_SER = 0; //最高位如果为0,则令P2.7 = 0 P_HC595_SRCLK = 0; P_HC595_SRCLK = 1; P_HC595_SRCLK = 0; //使用P2.6制造一个上升沿将这一位数据送到74HC595的QA输出端 dat = dat << 1; //将dat左移一位,取次高位 } } void display1(uchar yi,uchar er) { Send_595(0xfe); //选择最右边的一个数码管 Send_595(smgtab[yi]); P_HC595_RCLK = 0; P_HC595_RCLK = 1; //使用P2.5制造一个上升沿将这两个字节数据同时送给数码管,完成段选和位选 delayms(1); Send_595(0xfd); //选择最右边的一个数码管 Send_595(smgtab[er]); P_HC595_RCLK = 0; P_HC595_RCLK = 1; //使用P2.5制造一个上升沿将这两个字节数据同时送给数码管,完成段选和位选 delayms(1); } void display2(uchar san,uchar si) { Send_595(0xfb); //选择最右边的一个数码管 Send_595(smgtab[san]); P_HC595_RCLK = 0; P_HC595_RCLK = 1; //使用P2.5制造一个上升沿将这两个字节数据同时送给数码管,完成段选和位选 delayms(1); Send_595(0xf7); //选择最右边的一个数码管 Send_595(smgtab[si]); P_HC595_RCLK = 0; P_HC595_RCLK = 1; //使用P2.5制造一个上升沿将这两个字节数据同时送给数码管,完成段选和位选 delayms(1); } void display3(uchar wu,uchar liu) { Send_595(0xef); //选择最右边的一个数码管 Send_595(smgtab[wu]); P_HC595_RCLK = 0; P_HC595_RCLK = 1; //使用P2.5制造一个上升沿将这两个字节数据同时送给数码管,完成段选和位选 delayms(1); Send_595(0xdf); //选择最右边的一个数码管 Send_595(smgtab[liu]); P_HC595_RCLK = 0; P_HC595_RCLK = 1; //使用P2.5制造一个上升沿将这两个字节数据同时送给数码管,完成段选和位选 delayms(1); } void display4(uchar qi,uchar ba) { Send_595(0xbf); //选择最右边的一个数码管 Send_595(smgtab[qi]); P_HC595_RCLK = 0; P_HC595_RCLK = 1; //使用P2.5制造一个上升沿将这两个字节数据同时送给数码管,完成段选和位选 delayms(1); Send_595(0x7f); //选择最右边的一个数码管 Send_595(smgtab[ba]); P_HC595_RCLK = 0; P_HC595_RCLK = 1; //使用P2.5制造一个上升沿将这两个字节数据同时送给数码管,完成段选和位选 delayms(1); }
小红板题2代码:
/***************************************************************************************** 2、数码管初始显示0,单击S5,显示值加1,单击S10数值减1,长按S15数值连续加1,长按S20数值连续减1。 ******************************************************************************************/ #include"reg52.h" #define uchar unsigned char #define uint unsigned int #define TT 5 sbit P_HC595_SER = P2^7; //pin 14 SER data input sbit P_HC595_RCLK = P2^5; //pin 12 RCLk store (latch) clock sbit P_HC595_SRCLK = P2^6; //pin 11 SRCLK Shift data clock sbit s5=P3^0; sbit s10=P3^1; sbit s15=P3^2; sbit s20=P3^3; uchar code smgtab[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x40,0x00}; uint count; uchar ss5,ss10,num; uchar One,Two,Three,Four,Five,Six,Seven,Eight; void keyScan(); //键盘扫描 void SMG_Init();//数码管初始化函数 void delayms(uint z);//ms级延时函数 void Send_595(unsigned char dat); void displayOne(uchar One,uchar Two);//第一二个数码管显示函数 void displayTwo(uchar Three,uchar Four);//第三四个数码管显示函数 void displayThree(uchar Five,uchar Six );//第五六个数码管显示函数 void displayFour(uchar Seven,uchar Eight);//第七八个数码管显示函数 /****************************主函数*******************************/ void main() { SMG_Init(); while(1) { One=11;Two=11;Three=11;Four=11;Five=11;Six=num/100;Seven=num/10%10;Eight=num%10; if(ss5==1) { ss5=0; if((num>0)&&(num<=255)){num=num-1;} else if(num==0){num=0;} } else if(ss10==1) { ss10=0; if((num>=0)&&(num<=255)){num=num+1;} else if(num>255){num=255;} } else if(s15==0) //s15长按连续加1 { delayms(5); if(s15==0) { count=0; while(s15==0) { delayms(40); count++; } if(count>TT) { if((num>=0)&&(num<255))num=num+1; else if(num==255)num=255; } } } else if(s20==0) //s20长按连续减1 { delayms(5); if(s20==0) { count=0; while(s20==0) { delayms(40); count++; } if(count>TT) { if((num>0)&&(num<=255))num=num-1; else if(num==0)num=0; } } } keyScan(); displayOne(One,Two); displayTwo(Three,Four); displayThree(Five,Six); displayFour(Seven,Eight); } } void delayms(uint z) { uint x,y; for(x=z;x>0;x--) for(y=110;y>0;y--); } void keyscan() { if(s5==0) //s5 { delayms(5); if(s5==0) { ss5=1; //s5的标志位 } while(!s5); } else if(s10==0) //s10 { delayms(5); if(s10==0) { ss10=1; //s10的标志位 } while(!s10); } } void SMG_Init() { Send_595(0x00); //同时选择8个数码管 Send_595(0x00); //让8个数码管同时显示消隐字符 P_HC595_RCLK = 0; P_HC595_RCLK = 1; //使用P2.5制造一个上升沿将这两个字节数据同时送给数码管,完成段选和位选 } void Send_595(unsigned char dat) //发送一个字节 { unsigned char i; for(i=0; i<8; i++) { if(dat & 0x80) //判断dat的最高位是否为1 P_HC595_SER = 1; //最高位如果为1,则令P2.7 = 1 else P_HC595_SER = 0; //最高位如果为0,则令P2.7 = 0 P_HC595_SRCLK = 0; P_HC595_SRCLK = 1; P_HC595_SRCLK = 0; //使用P2.6制造一个上升沿将这一位数据送到74HC595的QA输出端 dat = dat << 1; //将dat左移一位,取次高位 } } void displayOne(uchar One,uchar Two) { Send_595(0xfe); //选择最右边的一个数码管 Send_595(smgtab[One]); P_HC595_RCLK = 0; P_HC595_RCLK = 1; //使用P2.5制造一个上升沿将这两个字节数据同时送给数码管,完成段选和位选 delayms(1); Send_595(0xfd); //选择最右边的一个数码管 Send_595(smgtab[Two]); P_HC595_RCLK = 0; P_HC595_RCLK = 1; //使用P2.5制造一个上升沿将这两个字节数据同时送给数码管,完成段选和位选 delayms(1); } void displayTwo(uchar Three,uchar Four) { Send_595(0xfb); //选择最右边的一个数码管 Send_595(smgtab[Three]); P_HC595_RCLK = 0; P_HC595_RCLK = 1; //使用P2.5制造一个上升沿将这两个字节数据同时送给数码管,完成段选和位选 delayms(1); Send_595(0xf7); //选择最右边的一个数码管 Send_595(smgtab[Four]); P_HC595_RCLK = 0; P_HC595_RCLK = 1; //使用P2.5制造一个上升沿将这两个字节数据同时送给数码管,完成段选和位选 delayms(1); } void displayThree(uchar Five,uchar Six ) { Send_595(0xef); //选择最右边的一个数码管 Send_595(smgtab[Five]); P_HC595_RCLK = 0; P_HC595_RCLK = 1; //使用P2.5制造一个上升沿将这两个字节数据同时送给数码管,完成段选和位选 delayms(1); Send_595(0xdf); //选择最右边的一个数码管 Send_595(smgtab[Six]); P_HC595_RCLK = 0; P_HC595_RCLK = 1; //使用P2.5制造一个上升沿将这两个字节数据同时送给数码管,完成段选和位选 delayms(1); } void displayFour(uchar Seven,uchar Eight) { Send_595(0xbf); //选择最右边的一个数码管 Send_595(smgtab[Seven]); P_HC595_RCLK = 0; P_HC595_RCLK = 1; //使用P2.5制造一个上升沿将这两个字节数据同时送给数码管,完成段选和位选 delayms(1); Send_595(0x7f); //选择最右边的一个数码管 Send_595(smgtab[Eight]); P_HC595_RCLK = 0; P_HC595_RCLK = 1; //使用P2.5制造一个上升沿将这两个字节数据同时送给数码管,完成段选和位选 delayms(1); }
----------------所有代码打包下载链接------------------
同学们,可以接着往下进行 06. 单片机 外部中断的使用 的题目练习~如对代码有任何问题,欢迎回帖指出来~
欢迎大家对本系列的支持,这是我们的动力!