按键处理程序分析与设计
- 格式:doc
- 大小:25.00 KB
- 文档页数:6
按键处理程序C语言单片机分享一种按键处理程序(用C)//头文件定义:Ustruct KEY{Uchar Val;#define Key_Model_C 0 //按键1值#define Key_AddVal_C 1 //按键2值Uint ScanOnTime;Uchar LongKeyState;Uchar LongKeyRestState;Uchar SetInRn;Uchar Model; //按键状态(模式)#define Off_C 0 //之前未按下#define On_C 1 //现按下#define Delay_C 2 //按键处理后标志}Key;//----------------定义两个IO输入口为按键入口--------------------//#define KeyMo_Bin (GPIOB->IDR.Bit.B5)#define KeyAdd_Bin (GPIOB->IDR.Bit.B6)/*===================================== ==========================*/GPIO_Init(GPIO_Pin_5|GPIO_Pin_6,GPIO_Mode_In_PU_No_IT); //初始化为上拉输入无中断/*===================================== ==========================*///主程序大循环中每1毫秒扫描1次void KeyScan(void){if(Key.LongKeyRestState == 1) //长按键标志(复位处理长按键){if((KeyMo_Bin == 1) && (KeyAdd_Bin == 1)) //当两按键均抬起{if(++Key.ScanOnTime >= 130) //延时后复位{Key.LongKeyRestState=0;Key.Model=Delay_C;}}elseKey.ScanOnTime=0;return;}if(Key.Model == Off_C) //如果当前按键状态为未按下“Off_C”{if((KeyMo_Bin == 0) || (KeyAdd_Bin == 0))//按键1或按键2已按下(低有效){if(++Key.ScanOnTime >= 10) //当按下后自加1,加够10次即1ms*10=10ms去抖动{Key.ScanOnTime=0;if(KeyMo_Bin == 0) //如果按键1为0即按下{Key.Val=Key_Model_C; //付当键1值(看头文件定义)Key.Model=On_C; //置按键已按下标志}else if(KeyAdd_Bin == 0) //如果按键2为0即按下{Key.Val=Key_AddVal_C; //付当键2值(看头文件定义)Key.Model=On_C; //置按键已按下标志}BellOn(200); //蜂鸣器响}}elseKey.ScanOnTime=0; //清去抖延时计数值}else if(Key.Model == Delay_C) //如果当前按键状态为已按下且已处理“Delay_C”{if((KeyMo_Bin == 1) && (KeyAdd_Bin == 1))//如果两按键均抬起{if(++Key.ScanOnTime >= 100) //延时100ms后复位按键状态为“Off_C”{Key.SetInRn=0;Key.ScanOnTime=0;Key.Model=Off_C;}}else //如果按键没有被抬起,对应上面if{if(++Key.ScanOnTime >= 1000) //延时1000ms后再复位按键状态为“Off_C”(为长按处理){Key.ScanOnTime=0;Key.Model=Off_C;}}}}//===================================== ========================================= ========void LoadCheckKeyRest(void){Key.LongKeyRestState=1;Key.ScanOnTime=0;}//===================================== ========================================= ========//处理相应按键(可250ms才调用一次)长按if(Key.Model == On_C) //按键状态为已按下{if(Key.Val == Key_Model_C) //是键1按下(看头文件定义){if(++Key.SetInRn >= 3) //连计3次数3秒后为长按键(对应上面,如果按下未抬起的话会延时1000ms){Key.SetInRn=0;LoadCheckKeyRest(); //调清长按处理BellOn(600); //蜂鸣器响//-----------长按需处理的内容-----下-----------//WorkStateBit.Bit.SettingMo=1;SetOverTime=0;SetMoRn=0;SetBak[0]=Rtc_InitDate.RTC_Year;SetBak[1]=Rtc_InitDate.RTC_Month;SetBak[2]=Rtc_InitDate.RTC_Date;SetBak[3]=Rtc_InitDate.RTC_WeekDay;SetBak[4]=Rtc_InitTime.RTC_Hours;SetBak[5]=Rtc_InitTime.RTC_Minutes;//-----------长按需处理的内容------上----------//Key.Model=Delay_C; //置按键模式为:已处理按键(看头文件定义)return;}}elseKey.SetInRn=0;Key.Model=Delay_C;}。
单片机按键课程设计一、课程目标知识目标:1. 让学生掌握单片机基础知识和按键的工作原理;2. 帮助学生了解按键在单片机系统中的应用和编程方法;3. 使学生能够运用所学知识设计简单的单片机按键控制系统。
技能目标:1. 培养学生动手实践能力,能够独立完成单片机按键电路的搭建;2. 提高学生编程能力,掌握单片机按键程序的设计与调试;3. 培养学生解决问题的能力,能够针对实际需求设计合适的单片机按键方案。
情感态度价值观目标:1. 培养学生对单片机技术及电子制作的兴趣,激发创新意识;2. 培养学生团队合作精神,学会分享和交流;3. 增强学生面对困难的勇气和毅力,培养勇于挑战的精神。
课程性质分析:本课程为实践性较强的课程,注重理论知识与实践操作的相结合,以培养学生的动手能力和创新能力为核心。
学生特点分析:学生处于初中或高中年级,具有一定的物理和数学基础,对电子技术和编程有一定了解,好奇心强,喜欢动手实践。
教学要求:结合学生特点,注重理论与实践相结合,充分调动学生的积极性,引导学生主动参与,提高学生的实践能力和创新能力。
在教学过程中,将课程目标分解为具体的学习成果,以便进行有效的教学设计和评估。
二、教学内容1. 单片机基础知识:介绍单片机的组成、工作原理、引脚功能等,结合教材相关章节,为学生建立单片机的基本概念。
2. 按键工作原理:讲解按键的物理原理、电路连接方式、去抖动方法等,使学生了解按键在单片机系统中的应用。
3. 单片机按键编程:教授单片机按键程序设计方法,包括I/O口编程、中断处理等,结合教材实例进行讲解。
4. 按键电路搭建:指导学生动手搭建单片机按键电路,学会使用面包板、电子元件等,培养实际操作能力。
5. 按键程序设计与调试:教授编程软件的使用,引导学生编写、调试按键程序,掌握程序设计的基本方法。
6. 应用实例分析:分析典型单片机按键控制系统实例,使学生了解实际应用中的设计方法和技巧。
教学进度安排:1. 第1课时:单片机基础知识及按键工作原理介绍;2. 第2课时:单片机按键编程方法讲解;3. 第3课时:按键电路搭建及编程实践;4. 第4课时:按键程序设计与调试;5. 第5课时:应用实例分析及总结。
在分析之前我先说一下ZStack协议栈有很多版本,版本不一样,代码多少有一些不一样,我的ZStack是ZStack-CC2530-2.3.1-1.4.0。
另外我的这篇文章中有很多内容是参考网友的文章,不知道有没有侵犯版权。
我自己总结一下按键处理流程,在ZStack协议栈中,按键的处理有两种方式,一种是中断方式,另一种是轮询方式,在这里,我以中断的方式来处理按键。
我的按键接在P0_1,如图所示:从图中可以看出,当按键没有按下的时候P0_1引脚为高电平,当按键按下时,引脚变成低电平,在这里,我的按键的中断触发方式为下降沿有效。
为了让按键按下后,程序能做点事情,我以LED灯为例,也就是说,当按键按下后,我让LED的状态翻转,也就是说按键按下一次,LED灯亮,在按下一次,LED灯灭,在按一下一次,LED灯亮……。
下图是LED的引脚图:纵观总的ZStack协议栈,我们发现P0_1和P1_0接的正好是按键和LED灯,因此在协议栈中,关于的按键和LED灯的代码我们不需要修改的太多。
我从main函数开始一步一步的分析,为了减小篇幅和代码量,我只分析与按键和中断有关的代码。
Int main(){// Turn off interrupts关闭中断osal_int_disable( INTS_ALL );//就是设置EA为0,EA为各种中断的总开关// Initialization for board related stuff such as LEDs//初始化系统时钟,LED等HAL_BOARD_INIT();//这个里面我没有动//电压检测,最好是能保证芯片能正常工作的电压// Make sure supply voltage is high enough to runzmain_vdd_check();// Initialize board I/O初始化板载IOInitBoard( OB_COLD );// Initialze HAL drivers初始化HAL驱动HalDriverInit();// Initialize NV System初始化NV系统osal_nv_init( NULL );// Initialize the MAC初始化MACZMacInit();// Determine the extended address确定IEEE地址zmain_ext_addr();#if defined ZCL_KEY_ESTABLISH// Initialize the Certicom certificate information. zmain_cert_init();#endif// Initialize basic NV items//初始化基本NV条目zgInit();#ifndef NONWK// Since the AF isn't a task, call it's initialization routine afInit();#endif// Initialize the operating system//初始化操作系统osal_init_system();// Allow interrupts使能所有中断,就是让EA为1 osal_int_enable( INTS_ALL );// Final board initialization最后的板载初始化InitBoard( OB_READY );// Display information about this devicezmain_dev_info();/* Display the device info on the LCD */#ifdef LCD_SUPPORTEDzmain_lcd_init();#endif#ifdef WDT_IN_PM1/* If WDT is used, this is a good place to enable it. */ WatchDogEnable( WDTIMX );#endifosal_start_system(); // No Return from herereturn 0; // Sh}在这里只分析红色部分的代码:// Initialize board I/O初始化板载IOInitBoard( OB_COLD );我们进入到到这个函数void InitBoard( uint8 level ){if ( level == OB_COLD ){// IAR does not zero-out this byte below the XSTACK.*(uint8 *)0x0 = 0;// Interrupts offosal_int_disable( INTS_ALL );// Check for Brown-Out resetChkReset();}else // !OB_COLD{/* Initialize Key stuff *///这个函数的作用是对按键使用的IO进行初始以及设置按键工作方式,按键IO初始化主要是将按键所对应的IO口定义为输入口//如果这个函数的第一个参数是HAL_KEY_INTERRUPT_ENABLE,那么按下该按键会触发IO终端,因此这个函数还要对IO终端//进行初始化的配置;如果这个函数的第一个参数是HAL_KEY_INTERRUPT_DISABLE,那么主程序后周期性的执行按键扫描程序//查看按键状态HalKeyConfig(HAL_KEY_INTERRUPT_ENABLE,OnBoard_KeyCallback);//在TI的源码中,第一个参数是HAL_KEY_INTERRUPT_DISABLE}}进入这个函数的时候,if条件成立,在这个if语句中没有做什么实际的事情,我们不管它,else语句不成立,我暂且先部分分析,在下面还会被调用,在下面我们在分析这个else语句。
最为精辟和实用的按键处理程序1.新型的按键扫描程序不过我在网上游逛了很久,也看过不少源程序了,没有发现这种按键处理办法的踪迹,所以,我将他共享出来,和广大同僚们共勉。
我非常坚信这种按键处理办法的便捷和高效,你可以移植到任何一种嵌入式处理器上面,因为C语言强大的可移植性。
同时,这里面用到了一些分层的思想,在单片机当中也是相当有用的,也是本文的另外一个重点。
对于老鸟,我建议直接看那两个表达式,然后自己想想就会懂的了,也不需要听我后面的自吹自擂了,我可没有班门弄斧的意思,hoho~~但是对于新手,我建议将全文看完。
因为这是实际项目中总结出来的经验,学校里面学不到的东西。
以下假设你懂C语言,因为纯粹的C语言描述,所以和处理器平台无关,你可以在MCS-51,AVR,PIC,甚至是ARM平台上面测试这个程序性能。
当然,我自己也是在多个项目用过,效果非常好的。
好了,工程人员的习惯,废话就应该少说,开始吧。
以下我以AVR的MEGA8作为平台讲解,没有其它原因,因为我手头上只有AVR的板子而已没有51的。
用51也可以,只是芯片初始化部分不同,还有寄存器名字不同而已。
核心算法:unsigned char Trg;unsigned char Cont;void KeyRead( void ){unsigned char ReadData = PINB^0xff; // 1Trg = ReadData & (ReadData ^ Cont); // 2Cont = ReadData; // 3}完了。
有没有一种不可思议的感觉?当然,没有想懂之前会那样,想懂之后就会惊叹于这算法的精妙!!下面是程序解释:Trg(triger)代表的是触发,Cont(continue)代表的是连续按下。
1:读PORTB的端口数据,取反,然后送到ReadData 临时变量里面保存起来。
2:算法1,用来计算触发变量的。
一个位与操作,一个异或操作,我想学过C语言都应该懂吧?Trg为全局变量,其它程序可以直接引用。
单⽚机按键处理⽅式(⼀)——典型的按键处理⽅式前⾔ 按键处理是学习单⽚机的必修课之⼀。
⼀次按键的过程,并⾮是⼀个理想的有⼀定宽度的电平脉冲,⽽是在按下、弹起过程中存在抖动,只有在中间阶段电平信号是稳定的。
⼀次典型的按键过程是酱紫的: 在抖动过程中,电平信号⾼低反复变化,如果你的按键检测是检测下降沿或上升沿或者是⽤外部中断检测按键,都可能在抖动时重复检测到多次按键。
这就是在未消抖的按⼀次键显⽰值加1的程序中,出现按⼀次键显⽰值+2、+3甚⾄加更多的原因。
对于按键消抖,常⽤的有硬件消抖和软件消抖。
本⽂是我个⼈对按键处理的⼀些常见⽅法的总结,由于我本⼈不太懂硬件,所以这⾥只讨论独⽴按键的软件消抖实现。
⽔平有限,如有错误请不吝指正。
硬件环境 本⽂代码均在单⽚机STC90C516RD+、晶振12.0MHz硬件环境下试验通过。
带消抖的简单的按键处理 最简单的消抖处理就是在⾸次检测到电平变化后加⼀个延时,等待抖动停⽌后再次检测电平信号。
这也是⼤多数单⽚机教程讲述的消抖⽅式。
但在实际应⽤中基本不⽤这种⽅式,原因后⾯讲,先看代码://⽅法⼀:带消抖的简单的按键处理#include <reg52.h>#define GPIO_KEY P1 //8个独⽴按键IO⼝#define GPIO_LED P0 //8个LED灯,⽤于显⽰键值unsigned char ScanKey();void DelayXms(unsigned char x);void main(){unsigned char key;GPIO_LED = 0x00; //初始化LEDwhile (1){key = ScanKey(); //读取键值// if (0xff != key) //若有键按下,则更新LED的状态GPIO_LED = ~key; //点亮LED}}unsigned char ScanKey(){unsigned char keyValue = 0xff; //赋初值,0xff表⽰没有键按下GPIO_KEY = 0xff; //给按键IO⼝置位if (0xff != GPIO_KEY) //检查按键IO⼝的电平,如有键按下则不为0xff{DelayXms(15); //延时15ms,滤掉抖动。
单片机按键程序设计及电路设计在单片机应用系统中,按键主要有两种形式:1、直接按键; 2、矩阵编码键盘。
直接按键的每个按键都单独接到单片机的一个I/O口上,直接按键则通过判断按键端口的电位即可识别按键操作;而矩阵键盘通过行列交叉按键编码进行识别。
下面我们以S51增强型单片机实验板的直接按键来学习单片机轻触按键在单片机系统中的应用。
S51增强型单片机实验板的4个轻触按键原理图。
S51增强型单片机轻触按键原理图图 1一、按键时序分析通常所用的按键为轻触机械开关,正常情况下按键的接点是断开的,当我们按压按钮时,由于机械触点的弹性作用,一个按键开关在闭合时不会马上稳定地接通,在断开时也不会一下子断开。
因而机械触点在闭合及断开的瞬间均伴随有一连串的抖动,按键的时序如下图2所示,抖动时间的长短由按键的机械特性及操作人员按键动作决定,一般为5ms~20ms;按键稳定闭合时间的长短是由操作人员的按键按压时间长短决定的,一般为零点几秒至数秒不等。
轻触按键操作时序示意图图 2从上面图2中我们可以看到,一次完整的击键过程,包含以下5个阶段:1. 等待阶段:此时按键尚未按下,处于空闲阶段。
2. 前沿(闭合)抖动阶段:此时按键刚刚按下,但按键信号还处于抖动状态,这个时间一般为5~20ms。
为了确保按键操作不会误动作,此时必须有个前沿消抖动延时。
3. 键稳定阶段:此时抖动已经结束,一个有效的按键动作已经产生。
系统应该在此时执行按键功能;或将按键所对应的键值记录下来,待按键释放时再执行。
4. 后沿(释放)抖动阶段:一般来说,考究一点的程序应该在这里再做一次消抖延时,以防误动作。
但是,如果前面“前沿抖动阶段”的消抖延时时间取值合适的话,可以忽略此阶段。
5. 按键释放阶段:此时后沿抖动已经结束,按键已经处于完全释放状态,如果按键是采用释放后再执行功能,则可以在这个阶段进行按键操作的相关处理。
二、按键实验例程下面我们通过几个实验例程来学习按键扫描编程及按键软件消抖动的编程,通过这些对比实验,给大家一个更加感性的认识。
单片机按键处理技巧及编程方式在基于单片机为核心构成的应用系统中,用户输入是必不可少的一部分。
输入可以分很多种情况,譬如有的系统支持PS2键盘的接口,有的系统输入是基于编码器,有的系统输入是基于串口或者USB或者其它输入通道等等。
在各种输入途径中,更常见的是,基于单个按键或者由单个键盘按照一定排列构成的矩阵键盘(行列键盘)。
我们这一篇章主要讨论的对象就是基于单个按键的程序设计,以及矩阵键盘的程序编写。
按键检测的原理: 它们和我们的单片机系统的I/O口连接一般如下:对于单片机I/O内部有上拉电阻的微控制器而言,还可以省掉外部的那个上拉电阻。
简单分析一下按键检测的原理。
当按键没有按下的时候,单片机I/O通过上拉电阻R接到VCC,我们在程序中读取该I/O的电平的时候,其值为1(高电平); 当按键S按下的时候,该I/O被短接到GND,在程序中读取该I/O的电平的时候,其值为0(低电平) 。
这样,按键的按下与否,就和与该按键相连的I/O的电平的变化相对应起来。
结论:我们在程序中通过检测到该I/O 口电平的变化与否,即可以知道按键是否被按下,从而做出相应的响应。
一切看起来很美好,是这样的吗?在我们通过上面的按键检测原理得出上述的结论的时候,那就是现实中按键按下时候的电平变化状态。
我们的结论是基于理想的情况得出来的,而实际中,由于按键的弹片接触的时候,并不是一接触就紧紧的闭合,它还存在一定的抖动,尽管这个时间非常的短暂,但是对于我们执行时间以us为计算单位的微控制器来说,它太漫长了。
因而,实际的波形图应该如下面这幅示意图一样。
这样便存在这样一个问题。
假设我们的系统有这样功能需求:在检测到按键按下的时候,将某个I/O的状态取反。
由于这种抖动的存在,使得我们的微控制器误以为是多次按键的按下,从而将某个I/O的状态不断取反,这并不是我们想要的效果,假如该I/O控制着系统中某个重要的执行的部件,那结果更不是我们所期待的。
按键控制实验报告按键控制实验报告一、实验目的本实验旨在让学生掌握按键控制的基本原理和方法,学会使用按键控制模块实现简单的控制功能。
二、实验原理按键控制是通过检测按键的状态来控制电路的工作。
按键控制模块内部一般包含有按键输入电路和微控制器,通过微控制器检测按键的状态,从而控制输出电路的工作。
三、实验步骤1.准备实验器材:按键控制模块、LED灯、杜邦线、面包板等。
2.将按键控制模块连接到面包板上,并将LED灯连接到按键控制模块的输出端。
3.通过杜邦线将按键控制模块的输入端连接到面包板上的按键上。
4.给按键控制模块供电,并使用串口调试助手与微控制器进行通信。
5.编写程序,实现按键控制LED灯的亮灭。
具体程序代码如下:#include <reg52.h>sbit led = P1^0; // LED灯连接在P1.0口sbit key = P1^1; // 按键连接在P1.1口void delay(unsigned int t) // 延时函数{while(t--);}void main(){while(1){if(key == 0) // 检测到按键按下{delay(100); // 延时去抖动if(key == 0) // 再次检测按键状态{led = ~led; // 控制LED灯的亮灭while(key == 0); // 等待按键松开}}}}6.将程序下载到微控制器中,并运行程序。
此时,按下按键,LED灯的状态将会改变。
四、实验结果与分析通过本次实验,我们成功地实现了按键控制LED灯的亮灭。
按下按键时,LED 灯的状态会发生改变。
实验结果表明,我们的程序设计是正确的,按键控制模块也能够正常工作。
在实验过程中,我们也遇到了一些问题。
首先,在连接电路时,需要注意按键控制模块的输入输出端口的接线方式,以免出现错误。
其次,在编写程序时,需要考虑按键的去抖动问题,以避免按键的误判。
最后,在下载程序时,需要注意选择与微控制器型号相匹配的下载方式和下载口,以保证程序的正确下载和运行。
目录 (1)前言 (1)1.总体设计方案 (2)2.系统硬件设计 (2)2.1硬件平台 (2)2.1.1 LED灯电路 (2)2.1.2 键盘驱动电路 (3)2.2软件平台 (4)2.2.1 软件简介 (4)2.2.2 ADS基本操作 (4)2.3模块设计 (5)2.3.1 S3C2410的I/O介绍 (5)2.3.2 S3C2410中断介绍 (6)2.3.3 按键驱动 (7)2.3.4 LED灯驱动 (10)3.驱动程序的连接 (11)3.1设备驱动程序接口 (11)3.2ADS驱动程序的加载(超级终端) (11)4.ADS下按键控制闪烁灯驱动的添加和调试 (12)4.1驱动程序下载 (12)4.2驱动测试程序 (12)5.实验效果 (12)6.设计总结 (14)参考文献 (15)附录 (16)近几年,嵌入式系统产品日臻完善,并在全世界各行业得到广泛应用。
嵌入式系统产品的研制和应用已经成为我国信息化带动工业化、工业化促进信息化发展的新的国民经济增长点。
随着消费家电的智能化,嵌入式更显重要。
像我们平常见到的手机、PDA、电子字典、可视电话、VCD/DVD/MP3Player、数字相机(DC)、数字摄像机(DV)、U-Disk 、机顶盒(Set Top Box)、高清电视(HDTV )、游戏机、智能玩具、交换机、路由器、数控设备或仪表、汽车电子、家电控制系统、医疗仪器、航天航空设备等等,都是典型的嵌入式系统。
据预测,随着Internet的迅速发展和廉价微处理器的出现,嵌入式系统将在日常生活里形成更大的应用领域。
在中国,嵌入式软件发展过程中,政府已充分认识到它的重要作用,并在政策、资金等方面给予了大力支持。
2004 年国家发改委、科技部、商务部联合颁布的《当前优先发展的高技术产业化重点领域指南》,把嵌入式软件产业作为国家发展的一个重要领域。
最近几年来,中国的嵌入式软件发展速度一直高于中国软件产业的发展速度和全球嵌入式软件的发展速度,在中国软件产业和全球嵌入式软件产业中所占的比重越来越大。
这里分析了4个按键,还有ENIT8和EINT19没有,不过原理一样的。
4个按键,分别是EINT11/GPG3EINT13/GPG5EINT14/GPG6EINT15/GPG7外部上拉电阻。
EINT8-23共用一个IRQ向量。
初始化步骤1,设置IO的功能,00输入01输出02第二功能P292设置的方法是rGPGCON&=~(3<<3*2|3<<5*2|3<<6*2|3<<7*2);rGPGCON|=(2<<3*2|2<<5*2|2<<6*2|2<<7*2);2,设置EXTINT系列寄存器,设定中断触发的类型P301其中这次用到的EINT1113-15是分布在EXTINT1中触发类型000低电平001高电平01x下降弦10x上升弦11x边缘触发rEXTINT1&=~(7<<12|7<<20|7<<24|7<<28);rEXTINT1|=(2<<12|2<<20|2<<24|2<<28);3,设置EINTPEND,P306如果发生中断,该寄存器对应的位置一,没有中断则为0清零的办法比较特殊,对对应位置一的话表示清零。
所以这里要这样做:rEINTPEND|=(1<<11)|(1<<13)|(1<<14)|(1<<15);4,设置EINTMASK寄存器,P3050表示允许对应位中断,1表示禁止对应位中断,默认是禁止的rEINTMASK&=~((1<<11)|(1<<13)|(1<<14)|(1<<15));5,先清一下IRQ中断作为初始化,需要先清一下,注意,刚才EINTPEND是清次中断,EXTINT8-23都递属于IRQ的中断号5,所以这里清的是主IRQ中断ClearPending(BIT_EINT8_23);其中ClearPending();是一个内联函数,原型在2440addr.h由于在头文件里面不适宜放函数的实现,所以这次移植将函数体放到2440lib.c里面,而2440addr.h保留函数的定义__inline void ClearPending(int bit){register i;rSRCPND=bit;rINTPND=bit;i=rINTPND;}函数很简单,跟前面一样,在INTPND对应位置1就能清除该位的中断标志了。
键盘接口实验实验报告及程序一、实验目的本次实验的主要目的是深入了解计算机键盘接口的工作原理,并通过编程实现对键盘输入的读取和处理。
通过这个实验,我们将掌握如何与计算机硬件进行交互,提高对计算机系统底层运作的认识。
二、实验原理计算机键盘通常通过 PS/2 接口或 USB 接口与主机相连。
在本次实验中,我们以 PS/2 接口为例进行研究。
PS/2 接口使用双向同步串行协议进行通信,数据传输速率约为 10 167Kbps 。
键盘在向主机发送数据时,每个字节包含 11 位,分别是起始位(总是 0 )、 8 位数据位(低位在前)、校验位(奇校验)和停止位(总是 1 )。
主机通过向键盘发送命令来控制键盘的工作模式和获取相关信息。
三、实验设备及环境1、计算机一台2、开发板及相关配件3、编程软件(如 Keil 等)四、实验步骤1、硬件连接将开发板与计算机通过相应的接口连接好,确保连接稳定。
2、软件编程选择合适的编程语言和开发环境。
初始化相关的硬件接口和寄存器。
编写读取键盘输入数据的程序代码。
3、编译与下载对编写好的程序进行编译,检查是否有语法错误。
将编译成功的程序下载到开发板中。
4、实验测试按下键盘上的不同按键,观察开发板的输出结果。
检查读取到的数据是否准确,校验位是否正确。
五、程序代码实现以下是一个简单的基于 C 语言的键盘接口读取程序示例:```cinclude <reg51h>//定义 PS/2 接口相关引脚sbit PS2_CLK = P1^0;sbit PS2_DATA = P1^1;//读取一个字节的数据unsigned char ReadByte(){unsigned char data = 0;unsigned char i;while(PS2_CLK == 1);//等待时钟线拉低for(i = 0; i < 8; i++){while(PS2_CLK == 0);//等待时钟上升沿data =(data << 1) | PS2_DATA; //读取数据位}while(PS2_CLK == 1);//等待时钟线拉低return data;}void main(){unsigned char key;while(1){key = ReadByte();//读取键盘输入的数据//在此处对读取到的数据进行处理和显示}}```六、实验结果与分析在实验过程中,我们按下不同的键盘按键,开发板能够准确地读取到相应的键值。
第1篇一、实验背景按键作为电子设备中常见的输入装置,其功能丰富,应用广泛。
本实验旨在通过设计和实现一系列按键功能,加深对按键工作原理的理解,并提高电子设计实践能力。
二、实验目的1. 掌握按键的基本原理和电路设计方法。
2. 熟悉按键在不同应用场景下的功能实现。
3. 培养电子设计实践能力,提高问题解决能力。
三、实验内容1. 实验器材:51单片机最小核心电路、按键、LED灯、电阻、电容、面包板等。
2. 实验内容:(1)单按键控制LED灯闪烁(2)按键控制LED灯点亮与熄灭(3)按键控制LED灯亮度调节(4)按键实现数字时钟调整(5)按键实现多功能计数器(6)按键实现密码输入与验证四、实验步骤1. 根据实验要求,设计电路图,并选择合适的元器件。
2. 使用面包板搭建实验电路,包括单片机、按键、LED灯、电阻、电容等。
3. 编写程序,实现按键功能。
4. 对程序进行调试,确保按键功能正常。
5. 实验完成后,撰写实验报告。
五、实验结果与分析1. 单按键控制LED灯闪烁实验结果:按下按键,LED灯闪烁;松开按键,LED灯停止闪烁。
分析:本实验通过单片机定时器实现LED灯的闪烁。
当按键按下时,定时器开始计时;当定时器达到设定时间后,LED灯点亮;定时器继续计时,当达到设定时间后,LED灯熄灭。
如此循环,实现LED灯的闪烁。
2. 按键控制LED灯点亮与熄灭实验结果:按下按键,LED灯点亮;再次按下按键,LED灯熄灭。
分析:本实验通过单片机的I/O口控制LED灯的点亮与熄灭。
当按键按下时,单片机将I/O口置为高电平,LED灯点亮;当按键再次按下时,单片机将I/O口置为低电平,LED灯熄灭。
3. 按键控制LED灯亮度调节实验结果:按下按键,LED灯亮度逐渐增加;松开按键,LED灯亮度保持不变。
分析:本实验通过单片机的PWM(脉宽调制)功能实现LED灯亮度的调节。
当按键按下时,单片机调整PWM占空比,使LED灯亮度逐渐增加;松开按键后,PWM占空比保持不变,LED灯亮度保持不变。
按键处理程序分析与设计参考程序:/************************************************时钟显示程序设计:黄有全2011年10月26日关键词:动态显示程序设计显示连接:P3→J_WM,接数码管的位控制,P1→J_DM,接共阳极数码管段码,动态显示。
按键连接:按键KEY→P2。
k1→P2.0,k2→P2.1,k3→P2.2,k4→P2.3。
按键作用说明:k1、k2小时加减,k3、k4分钟加减************************************************/#include<reg51.h>unsigned char duanma[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x8 3,0xc6,0xa1,0x86,0x8e,0x89,0xc7,0x8c,0xbf,0xff};//数组,定义共阳极数码管显示段码:0,1,2,3,4,5,6,7,8,9,A,b,C,d,E,F,H,L,P,-,熄灭。
#define uchar unsigned charuchar ms=0,sec=0,min=30,hour=10;uchar keyv;/**************延时2.5ms函数***************/void delay() //延时函数,带参数i。
{ //在调用函数时通过设置参数,改变延时时间。
int j=0,k=0;// for(j=0;j<i;j++)for(k=0;k<350;k++);}/**************延时250ms函数***************/void delay_250() //延时函数,带参数i。
{ //在调用函数时通过设置参数,改变延时时间。
int j=0,k=0;for(j=0;j<100;j++)for(k=0;k<350;k++);}/**************时间显示函数***************/void display(){P1=duanma[sec%10]; //送秒的个位的段码,显示;P3=0xfe; //送第一位的位码,点亮第1位数码管。
单片机按键程序设计单片机按键的基本原理其实并不复杂。
通常,按键就是一个简单的开关,当按键按下时,电路接通,对应的引脚电平发生变化;当按键松开时,电路断开,引脚电平恢复到初始状态。
在程序设计中,我们需要不断检测引脚的电平变化,从而判断按键是否被按下。
在实际的按键程序设计中,有多种方式可以实现按键检测。
其中一种常见的方法是查询法。
这种方法是通过不断地读取按键对应的引脚状态来判断按键是否被按下。
以下是一个简单的查询法示例代码:```cinclude <reg51h> //包含 51 单片机的头文件sbit key = P1^0; //定义按键连接的引脚void main(){while(1) //无限循环{if(key == 0) //如果按键按下,引脚为低电平{//执行按键按下的操作//比如点亮一个 LED 灯P2 = 0xfe;while(key == 0);//等待按键松开}}}```上述代码中,我们首先定义了按键连接的引脚`key`,然后在主函数的无限循环中不断检测按键引脚的状态。
当检测到按键按下时,执行相应的操作,并通过`while(key == 0)`等待按键松开。
除了查询法,还有中断法可以用于按键检测。
中断法的优点是能够及时响应按键动作,不会因为程序的其他操作而导致按键响应延迟。
```cinclude <reg51h> //包含 51 单片机的头文件sbit key = P1^0; //定义按键连接的引脚void int0_init()//中断初始化函数{IT0 = 1; //下降沿触发中断EX0 = 1; //使能外部中断 0EA = 1; //开总中断}void int0() interrupt 0 //外部中断 0 服务函数{//执行按键按下的操作//比如点亮一个 LED 灯P2 = 0xfe;}void main(){int0_init();//初始化中断while(1);//无限循环,保持程序运行}```在上述代码中,我们首先在`int0_init` 函数中对中断进行了初始化设置,然后在`int0` 函数中编写了按键按下时的处理代码。
按键处理程序分析与设计
参考程序:
/************************************************
时钟显示程序
设计:黄有全
2011年10月26日
关键词:动态显示程序设计
显示连接:P3→J_WM,接数码管的位控制,P1→J_DM,接共阳极数码管段码,动态显示。
按键连接:按键KEY→P2。
k1→P2.0,k2→P2.1,k3→P2.2,k4→P2.3。
按键作用说明:k1、k2小时加减,k3、k4分钟加减
************************************************/
#include<reg51.h>
unsigned char duanma[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x8 3,0xc6,0xa1,0x86,0x8e,0x89,0xc7,0x8c,0xbf,0xff};
//数组,定义共阳极数码管显示段码:0,1,2,3,4,5,6,7,8,9,A,b,C,d,E,F,H,L,P,-,熄灭。
#define uchar unsigned char
uchar ms=0,sec=0,min=30,hour=10;
uchar keyv;
/**************延时2.5ms函数***************/
void delay() //延时函数,带参数i。
{ //在调用函数时通过设置参数,改变延时时间。
int j=0,k=0;
// for(j=0;j<i;j++)
for(k=0;k<350;k++);
}
/**************延时250ms函数***************/
void delay_250() //延时函数,带参数i。
{ //在调用函数时通过设置参数,改变延时时间。
int j=0,k=0;
for(j=0;j<100;j++)
for(k=0;k<350;k++);
}
/**************时间显示函数***************/
void display()
{
P1=duanma[sec%10]; //送秒的个位的段码,显示;P3=0xfe; //送第一位的位码,点亮第1位数码管。
delay(); //延时2.5ms
P1=duanma[sec/10]; //送秒的十位的段码,显示;
P3=0xfd; //送第二位的位码,点亮第2位数码管。
delay(); //延时2.5ms
P1=duanma[19]; //送-的段码,显示-;
P3=0xfb; //送第三位的位码,点亮第3位数码管。
delay(); //延时2.5ms
P1=duanma[min%10]; //送分的个位的段码,显示;
P3=0xf7; //送第4位的位码,点亮第4位数码管。
delay(); //延时2.5ms
P1=duanma[min/10]; //送秒的十位的段码,显示;
P3=0xef; //送第5位的位码,点亮第5位数码管。
delay(); //延时2.5ms
P1=duanma[19]; //送-的段码,显示-;
P3=0xdf; //送第6位的位码,点亮第7位数码管。
delay(); //延时2.5ms
P1=duanma[hour%10]; //送小时的个位的段码,显示;P3=0xbf; //送第7位的位码,点亮第7位数码管。
delay(); //延时2.5ms
P1=duanma[hour/10]; //送秒的十位的段码,显示;
P3=0x7f; //送第8位的位码,点亮第8位数码管。
delay(); //延时2.5ms
}
/**************按键处理函数**************/
void key()
{ uchar i;
keyv=P2;
keyv=~keyv&0x1f; //取反,去掉高三位(只要5个按键)
if(keyv==1) //K1按键按下,小时单元在0-23之间循环加1
{if(hour<23)hour++;else hour=0; }
if(keyv==2) //K2按键按下,小时单元在0-23之间循环减1
{if(hour>0)hour--;else hour=23; }
if(keyv==4) //K3按键按下,分钟单元在0-59之间循环加1
{if(min<59)min++;else min=0; }
if(keyv==8) //K4按键按下,分钟单元在0-59之间循环减1
{if(min>0)min--;else min=59; }
if(keyv!=0){for(i=0;i<10;i++)display();}//延时0.2秒,用显示程序代替延时,等待按键松开
}
/**************时间数据产生函数************** */
void time()
{
ms++; //ms单元增加1
if(ms>=50) //ms单元>50(是否到1秒)
{
sec++;ms=0; //到1秒,则sec增加1,且ms清0.
if(sec>59) //sec单元>59(是否到1分)
{
min++;sec=0; //秒进位到分钟,即分钟加1.且sec清0. if(min>59)
{
hour++;min=0;
if(hour>23)
{
hour=0;
}
}
}
}
}
/**************主函数************** */
void main()
{
while(1)
{
display(); //调用显示函数,显示时钟。
耗时20ms time(); //时间测试函数
key(); //按键处理函数
}
}。