宁德师范学院计算机系
实验报告
(2014—2015学年 第 2学期)
课程名称 单片机原理
实验名称 独立按键识别
专 业 计算机科学与技术(非师)
年 级 12级
学号 B2012102147 姓名 王 秋
指导教师 杨烈君
实验日期 2015.5.27
实验目的: 1. 掌握查询式按键的原理和编程方法 2. 理解按键防抖技术 | |
实验要求: 1. 在Proteus软件中画好51单片机最小核心电路,包括复位电路和晶振电路 2. 在电路中增加按键、Led灯、八位7段数码管(共阳/共阴自选),将P2口作数据输出口与7段数码管数据引脚相连 ,P3引脚输出位选控制信号。 3. 实现单按键控制Led灯闪烁 4. 实现单按键多功能识别——控制4路Led灯闪烁 5. 实现0-99的计数器效果,按一下数值加一 6. 实现0-99码表 ( 按一次开始计时,第二次停止,第三次清零 ) 7. 扩展要求: 通过3个按键实现时钟的调整 ( KEY1 模式 , KEY2 + ,KEY3 - ) | |
实验设备(环境): 计算机、Proteus ISIS 7 Professional应用程序、Keil应用程序 | |
实验内容: 1. 实现单按键控制Led灯闪烁 2. 实现单按键多功能识别——控制4路Led灯闪烁 3. 实现0-99的计数器效果,按一下数值加一 4. 实现0-99码表 ( 按一次开始计时,第二次停止,第三次清零 ) 5. 扩展要求: 通过3个按键实现时钟的调整 ( KEY1 模式 , KEY2 + ,KEY3 - ) 参考原理图 | |
实验步骤、实验结果及分析: 1、使用Proteus ISIS 7 Professional应用程序,建立一个.DSN文件 2、在“库”下拉菜单中,选中“拾取元件”(快捷键P),分别选择以下元件:AT89C51、CAP、CAP-ELEC、CRYSTAL、RESPACK-8。 3、构建仿真电路 4、创建一个Keil应用程序:新建工程项目文件;为工程选择目标器件(AT89C52);为工程项目创建源程序文件并输入程序代码;保存创建的源程序项目文件;把源程序文件添加到项目中。 5、把程序经过编译后生成的HEX文件添加到仿真电路中的处理器中(编辑元件→文件路径) 程序代码: 1. 实现单按键控制Led灯闪烁 #include"reg51.h" #define uchar unsigned char sbit Led1=P1^0; sbit Key=P3^2; uchar Mode=0; void delay(int x) //定义时间间隔 { while(x--); } void button_Cotrol() //根据按键模式执行相应的代码 { if(Key==0) { delay(1000); if(Key==0) { Mode=(Mode+1)%2; while(Key==0); } } if(Mode==0) Led1=0; if(Mode==1) { Led1=~Led1; delay(1000); } } void main() { while(1) button_Cotrol(); } 图1 单按钮,控制led灯闪烁 2. 实现单按键多功能识别——控制4路Led灯闪烁 #include"reg51.h" #define uchar unsigned char sbit Led1=P1^0;sbit Led2=P1^1; sbit Led3=P1^2;sbit Led4=P1^3; sbit Key=P3^2; uchar Mode=0; void delay(int x) //定义时间间隔 { while(x--); } void button_Cotrol() //根据按键模式执行相应的代码 { if(Key==0) { delay(1000); if(Key==0) { Mode=(Mode+1)%4; while(Key==0); } } if(Mode==0) { Led4=0; Led1=~Led1; delay(3000); } if(Mode==1) { Led1=0; Led2=~Led2; delay(3000); } if(Mode==2) { Led2=0; Led3=~Led3; delay(3000); } if(Mode==3) { Led3=0; Led4=~Led4; delay(3000); } } void main() { Led1=0; Led2=0; Led3=0; Led4=0; while(1) button_Cotrol(); } 图2 单按键多功能识别,控制4路Led灯闪烁 3. 实现0-99的计数器效果,按一下数值加1 #include"reg51.h" #define uchar unsigned char #define disp_null 10 sbit Key=P3^2; uchar code tab[11]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff}; //共阳数码管显示0~9的段码表 uchar DispBuf[8]; uchar sec=0; void delay(int x) //定义时间间隔 { while(x--); } void PutTime() { DispBuf[7]=sec%10; DispBuf[6]=sec/10; DispBuf[5]=disp_null; DispBuf[4]=disp_null; DispBuf[3]=disp_null; DispBuf[2]=disp_null; DispBuf[1]=disp_null; DispBuf[0]=disp_null; } void display() { uchar i; for(i=0;i<8;i++) { P2=0; P2=1< P0=tab[DispBuf[i]]; delay(100); } } void Button_Control() { if(Key==0) { delay(3000); if(Key==0) { sec++; while(Key==0); } } } void main() { while ( 1 ) { display(); PutTime(); Button_Control(); } } 图3 0-99的计数器效果,按一下数值加1 4. 实现0-99码表 ( 按一次开始计时,第二次停止,第三次清零 ) #include"reg51.h" #define uchar unsigned char #define disp_null 10 sbit Key=P3^2; uchar code tab[11]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff}; //共阳数码管显示0~9的段码表 uchar DispBuf[8]; uchar sec=0; uchar temp=30; uchar Mode=2; void delay(int x) //定义时间间隔 { while(x--); } void PutTime() { DispBuf[7]=sec%10; DispBuf[6]=sec/10; DispBuf[5]=disp_null; DispBuf[4]=disp_null; DispBuf[3]=disp_null; DispBuf[2]=disp_null; DispBuf[1]=disp_null; DispBuf[0]=disp_null; } void display() { uchar i; for(i=0;i<8;i++) { P2=0; P2=1< P0=tab[DispBuf[i]]; delay(100); } } void time_Eclipse() { if(Mode==1) { temp--; if(temp==0) { temp=30; sec++; } if(sec>99) sec=0; } } void Button_Control() { if(Key==0) { delay(3000); if(Key==0) { Mode=(Mode+1)%3; while(Key==0); } } if(Mode==0) sec=0; if(Mode==1) time_Eclipse(); if(Mode==2); } void main() { while ( 1 ) { display(); Button_Control(); PutTime(); } } 图4 0-99码表,按一次开始计时,第二次停止 图5 0-99码,按表第三次清零 5. 扩展要求: 通过3个按键实现时钟的调整 #include"reg51.h" #define uchar unsigned char #define disp_null 10 uchar code tab[11]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xbf}; //共阳数码管显示0~9的段码表 uchar dispBuf[8]; uchar hour=13,min=23,sec=25; //分别给时、分、秒赋初值 sbit key1=P3^2; sbit key2=P3^3; sbit key3=P3^4; void delay(int x) //定义时间间隔 { while(x--); } void PutTime() { dispBuf[7]=sec%10; dispBuf[6]=sec/10; dispBuf[5]=disp_null; dispBuf[4]=min%10; dispBuf[3]=min/10; dispBuf[2]=disp_null; dispBuf[1]=hour%10; dispBuf[0]=hour/10; } uchar ScanKey() //识别是否按键 { if(key1==0) return '1'; //如果按键1被按,则返回1 if(key2==0) return '+'; if(key3==0) return '-'; return 0; } uchar ReadKey() { uchar tmp; tmp= ScanKey( ); // 读取按键值 if( tmp== 0 ) return 0; // 没有按键,退出 delay( 1000 ) ; // 延时一小段时间,消抖(10mS左右) if( tmp!= ScanKey( ) ) // 如果现在读回来的和原来的值不一样,放弃 return 0; while( ScanKey( ) ) ; // 如果一旦读回来的值为0,也就是松开按键,那么就可以返回。 return tmp; // 按键返回 } void display() { uchar i; for(i=0;i<8;i++) { P2=0; P2=1< P0=tab[dispBuf[i]]; delay(100); } } void main() { unsigned char mode=0; unsigned char ms; while(1) { PutTime(); display(); switch(ReadKey()) { case'1':mode=(mode+1)%4;break; case'+':if(mode==0) break; else if(mode==1) hour=(hour+1)%24; else if(mode==2) min=(min+1)%60; else if(mode==3) sec=(sec+1)%60;break; case'-':if(mode==0) break; else if(mode==1&&hour) hour=(hour-1)%24; else if(mode==2&&min) min=(min-1)%60; else if(mode==3&&sec) sec=(sec-1)%60; break; } ms++; //控制加1的时延 if(ms>=50) { sec++;ms=0; } if(sec>=60) //表示进位,当秒满六十则向分钟进1,同时秒数清零 { min++;sec=0; } if(min>=60) { hour++;min=0; } if(hour>=24) //当小时数满24小时时,则小时数清零,完成计时 { hour=0; } } } 图6 3按键实现时钟的调整,KEY1选择模式,KEY2 +,KEY3 - 图7 3按键实现时钟的调整,KEY1选择模式,KEY2 +,KEY3 - 图8 3按键实现时钟的调整,KEY1选择模式,KEY2 +,KEY3 - | |
实验总结(包括过程总结、心得体会及实验改进意见等): 过程总结: 1. 在电路中增加按键、Led灯、八位7段数码管(共阳/共阴自选),将P2口作数据输出口与7段数码管数据引脚相连 ,P3引脚输出位选控制信号。掌握查询式按键的原理和编程方法 2. 在Proteus软件中画好51单片机最小核心电路,包括复位电路和晶振电路,理解按键防抖技术,当第一次检测到有建按下时,先延时(10~20ms),而后再确认键电平是否依旧维持闭合状态的电平。若保持闭合状态电平,则确认此间已按下,从而消除抖动影响。 心得体会: 本次的实验是通过对按键的不同控制实现各个功能,在理想的环境下按键的反馈是即时且无误差的,但是在实际的环境中要考虑到按键抖动的现象,所以要写一个判断按键抖动的函数,还有单按键控制多个灯的亮灭,可以设置一个变量来记录按键的情况来实现对不同部件的控制,而多按键的时候只需要判断是哪一个按键被按下,然后执行对应的程序。 | |
指导教师评语: 成绩评定 教师签字 年 月 日 | |
备注: | |
注:1、报告内的项目或设置,可根据实际情况加以补充和调整
2、教师批改学生实验报告应在学生提交实验报告10日内
¥29.8
¥9.9
¥59.8