外部中断扫描矩阵键盘
- 格式:doc
- 大小:83.00 KB
- 文档页数:8
单片机按键程序设计单片机按键的基本原理其实并不复杂。
通常,按键就是一个简单的开关,当按键按下时,电路接通,对应的引脚电平发生变化;当按键松开时,电路断开,引脚电平恢复到初始状态。
在程序设计中,我们需要不断检测引脚的电平变化,从而判断按键是否被按下。
在实际的按键程序设计中,有多种方式可以实现按键检测。
其中一种常见的方法是查询法。
这种方法是通过不断地读取按键对应的引脚状态来判断按键是否被按下。
以下是一个简单的查询法示例代码:```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` 函数中编写了按键按下时的处理代码。
二○一六~二○一七学年第一学期电子信息工程系电子综合设计II报告书班级:电信(产业)1401班设计时间:2016/12/29学生姓名:曹子龙学号:201404135024指导教师:赵敏二○一六年十二月一、设计要求.题目内容:设计一个基于51单片机的电子密码锁:1.可以使用4*4的矩阵键盘与红外遥控器输入密码。
2.可以通过按特殊组合键重设开锁密码。
3.显示通过1602液晶屏显示电子密码锁界面,输入密码时显示输入个数显示为‘*’,如果密码正确,进入欢迎界面。
4.密码连续输入3次错误报警,LCD显示报警,倒计时十秒后重新进入密码输入界面。
5.可以通过特殊的按键组合跳过输入界面直接进入欢迎界面。
实现方法:1.通过红外接收头,连接单片机的P3.2外部中断INT0口,可以实现单片机接收遥控器的信号输入。
2.通过矩阵键盘扫描函数,可以实现对键盘输入的响应。
3.通过引脚的高低电平变化频率,控制蜂鸣器的输入占空比和频率(低电平时间固定,通过输入给函数值的不同改变高电平时间,固定响300个周期),对不同按键实现不同声音响应。
4.1602显示屏有16*2个单元格,每个单元格由5*8个像素点组成,可以很好的显示数字,符号,英文字符。
功能需求分析:液晶屏显示:根据题意,需要设计并显示输入密码界面、修改密码界面、欢迎界面、错误警告界面密码输入:根据题意,每次输入一个数字,则显示一个‘*’符号代替,只能看出输入的位数,若输入密码位数达到六位,则与正确密码比较,若正确,进入系统。
根据日常的手机使用习惯,默认长度为6位,且第六位输入之后立即判断,正确则进入,错误则清空重输。
组合键实现密码修改:密码修改必须通过不易被他人发现的特殊方法改变,所以设计为,若同时按住矩阵键盘的5,10 或6,9两个键,则进入密码修改函数。
输入密码错误三次则报错:一般的密码系统对密码输入错误次数过多的情况进行了限制,所以在密码锁里设置,若密码输入错误三次,则进入警报界面,显示10s倒计时,必须在倒计时结束后才能再次输入密码。
STM32矩阵键盘原理详解引言矩阵键盘是一种常见的输入设备,广泛应用于电子产品中。
在STM32微控制器中,利用GPIO引脚实现矩阵键盘控制相对简单,本文将详细介绍STM32矩阵键盘的基本原理。
基本原理矩阵键盘由多个按键组成,通常采用行列式排列。
每个按键都由一个触点和一个按键外壳组成,触点一般为弹簧式结构,按下按键时触点接通,释放按键时触点断开。
矩阵键盘的连接方式矩阵键盘的每个按键都被分配一个行号和列号,通过行线和列线来连接按键和控制芯片。
STM32通过GPIO来控制行线和列线的电平,实现按键的扫描和检测。
在STM32中,行线和列线可以连接到不同的GPIO引脚上。
行线连接到输出引脚,列线连接到输入引脚。
这样,通过对行线的输出和对列线的输入,可以实现对矩阵键盘的扫描和检测。
矩阵键盘的扫描原理矩阵键盘的扫描原理可以简单描述为以下几个步骤:1.将所有行线设置为高电平,所有列线设置为输入模式。
2.逐个将行线设置为低电平,并同时检测列线引脚的电平状态。
3.如果某一列的输入引脚检测到低电平,表示该列对应的按键被按下。
4.通过行线和列线的对应关系,确定被按下的按键的行号和列号。
矩阵键盘的按键映射通过扫描后,可以得到被按下的按键的行号和列号,STM32可以根据行列号的映射关系将按键信息转化为相应的按键值。
通常,矩阵键盘的按键映射是通过二维数组来实现的。
数组的行号对应行线,列号对应列线。
数组中的元素对应按键的键值。
例如,要实现一个4x4的矩阵键盘,可以通过以下数组表示按键的映射关系:uint8_t keyMap[4][4] = {{ '1', '2', '3', 'A' },{ '4', '5', '6', 'B' },{ '7', '8', '9', 'C' },{ '*', '0', '#', 'D' }};通过行列号可以确定数组中的元素,从而得到按键的键值。
51单片机矩阵键盘控制数码管显示过程中出现的问题及解决方法在使用51单片机控制矩阵键盘同时驱动数码管显示的过程中,可能会遇到一些常见的问题。
以下是一些可能的问题及相应的解决方法:按键无法正常响应:* 问题可能原因:接线错误、按键损坏、软件扫描不到按键信号。
* 解决方法:检查按键连接是否正确,确保按键没有损坏。
在软件中进行适当的按键扫描,确保能够正确检测到按键的状态。
数码管显示异常或不亮:* 问题可能原因:数码管接线问题、数码管损坏、数码管驱动程序错误。
* 解决方法:仔细检查数码管的接线是否正确,确保数码管没有损坏。
检查数码管的驱动程序,确保它按照正确的顺序和时序进行驱动。
按键重复响应或漏按现象:* 问题可能原因:按键抖动、软件扫描速度过快。
* 解决方法:在软件中增加适当的按键抖动延时,确保在按键按下或抬起时只响应一次。
调整软件扫描速度,避免扫描间隔过短导致的重复响应。
矩阵键盘的多个按键同时按下导致混乱:* 问题可能原因:矩阵键盘硬件连接错误、软件扫描算法问题。
* 解决方法:检查矩阵键盘的硬件连接,确保矩阵行和列没有短路或断路。
调整软件扫描算法,确保同时按下多个按键时能够正确识别。
数码管显示不正常的数字或乱码:* 问题可能原因:程序错误、数码管接线错误。
* 解决方法:仔细检查程序,确保数码管段选和位选的控制逻辑正确。
检查数码管的接线,确保每个数码管的连接都正确。
在解决问题时,建议逐步排除可能的原因,通过调试工具、逻辑分析仪或输出调试信息的方式来定位问题。
另外,仔细查阅51单片机的数据手册和相关文档,以确保硬件连接和软件设计都符合标准。
简谈单片机检测按键原理和中断按键检测的办法单片机检测按键原理首先说一下独立键盘检测,在单片机外围电路中,通常用到的按键都是机械弹性开关,当开关闭合时,线路导通,开关断开时,线路断开。
单片机检测按键的原理:按键的一端接地,另一端与单片机的某个I/O口相连,开始先给I/O赋一高电平,然后让单片机不断检测该I/O口是否变为低电平,当按键闭合时,相当于I/O口与地相连,就会变为低电平。
在单片机检测按键是否被按下时,电压的实际波形与理想波形时有一点=定差别的,波形在按下和释放瞬间都有抖动现象,抖动时间的长短和按键的机械特性有关。
所以单片机在检测键盘是否被按下都要加上去抖操作,所以在编写单片机的键盘检测程序时,一般在检测按下时加入去抖延时。
独立键盘与单片机连接时每一个按键都需要一个I/O口,会过多占用I/O口资源。
所以就引出了矩阵键盘。
矩阵键盘的连接方式,每一行将每个按键的一端连接在一起构成行线,每一列将按键的另一端连接在一起构成列线。
这样的话,16个按键排成4行4列就只要8根线。
它的按键检测,简单点说,就是先送一列低电平,其余均为高电平,然后轮流检测,确认行列。
这里就要提到另外一个东西,switch-case语句又称开关语句,它是一个专门用于处理多分支结构的条件选择语句。
使用switch语句可直接处理多个分支。
按键检测是初学单片机的同学玩的前几个例程,按键的种类有许多(普通按钮,矩阵键盘等等),按键检测的方法也有许多。
对于普通按钮当然你会说设计一个外围电路通过GPIO 口读一下还不简单,或许你说通过外部中断做边沿检测,对于矩阵键盘来说,往往你会通过行列分别扫描的方法做按键检测,通常我们会加一个按键防抖(经典的方法是通过延时二次确认的方法进行按键防抖,还有就是按键释放的时候你可能会通过while语句去防抖,也就是按键如果一直按下,让程序一直死在while里),这些都是初学者常用的方法,但是如果是一个大的程序,往往是不允许你有这么多延时和死循环的。
实验5 独立键盘和矩阵键盘一、实验目的1、学会用C语言进行独立按键应用程序的设计。
2、学会用C语言进行矩阵按键应用程序的设计。
二、实验内容1、独立按键:对四个独立按键编写程序:当按k1时,8个LED同时100ms闪烁;当按k2时,8个LED从左到右流水灯显示;当按k3时,8个LED从右到左流水灯显示;当按k4时,8各LED同时从两侧向中间逐步点亮,之后再从中间向两侧逐渐熄灭;2、矩阵按键:采用键盘扫描方式,顺序按下矩阵键盘后,在一个数码管上顺序显示0~F,采用静态显示即可。
3、提高部分(独立按键、定时器、数码管动态扫描):编写程序,实现下面的功能。
用数码管的两位显示一个十进制数,变化范围为00~59,开始时显示00,每按一次k1,数值加1;每按一次k2,数值减1;每按一次k3,数值归零;按下k4,利用定时器功能使数值开始自动每秒加1;再按一次k4,数值停止自动加1,保持显示原数。
三、实验步骤1、硬件连接(1)使用MicroUSB数据线,将实验开发板与微型计算机连接起来;(2)在实验开发板上,用数据线将相应接口连接起来;2、程序烧入软件的使用使用普中ISP软件将HEX文件下载至单片机芯片内。
查看结果是否正确。
四、实验结果——源代码1. #include "reg52.h"typedef unsigned char u8;typedef unsigned int u16;#define LED P2sbit key1=P3^1;sbit key2=P3^0;sbit key3=P3^2;sbit key4=P3^3;const char tab[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f}; u8 code begMid[]={0x7e, 0xbd,0xdb,0xe7, 0xdb, 0xbd, 0x7e}; void Delay(u16 i){ while(i--);}void KeyDown(){u8 i;if(key2==0){Delay(1000);if(key2==0){for(i=0;i<8;i++){LED=tab[i];Delay(50000);}while(!key2);}LED=0xff;}else if(key1==0){Delay(1000);if(key1==0)for(i=0;i<3;i++){LED=0x00;Delay(10000);LED=0xff;Delay(10000);}}}}void Int0Init(){IT0=1;EX0=1;EA=1;}void Int1Init(){IT1=1;EX1=1;EA=1;} void main(){Int0Init();Int1Init();while(1){KeyDown();}}void Int0() interrupt 0{u8 i;if(key3==0){Delay(1000);if(key3==0)for(i=7;i>=0;i--){LED=tab[i];Delay(50000);}}}}void Int1() interrupt 2{u8 i;if(key4==0){Delay(1000);if(key4==0){for(i=0;i<=6;i++){LED=begMid[i];Delay(50000);}}}}2.#include "reg52.h"typedef unsigned int u16;typedef unsigned char u8;#define GPIO_DIG P0#define GPIO_KEY P1sbit LSA=P2^2;sbit LSB=P2^3;sbit LSC=P2^4;u8 KeyValue;u8 code smgduan[17]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};//??0~F?? void delay(u16 i){while(i--);}void KeyDown(void){char a=0;GPIO_KEY=0x0f;if(GPIO_KEY!=0x0f){delay(1000);if(GPIO_KEY!=0x0f){GPIO_KEY=0X0F;switch(GPIO_KEY){case(0X07): KeyValue=0;break;case(0X0b): KeyValue=1;break;case(0X0d): KeyValue=2;break;case(0X0e): KeyValue=3;break;}GPIO_KEY=0XF0;switch(GPIO_KEY){case(0X70): KeyValue=KeyValue;break;case(0Xb0): KeyValue=KeyValue+4;break;case(0Xd0): KeyValue=KeyValue+8;break;case(0Xe0): KeyValue=KeyValue+12;break;}while((a<50)&&(GPIO_KEY!=0xf0)){delay(1000);a++;}}}}void main(){LSA=0;LSB=0;LSC=0;while(1){KeyDown();GPIO_DIG=smgduan[KeyValue];}}3.#include <reg52.h>typedef unsigned int u16;typedef unsigned char u8;#define KEYPORT P3sbit LSA=P2^2;sbit LSB=P2^3;sbit LSC=P2^4;sbit key1=P3^1;sbit key2=P3^0;sbit key3=P3^2;sbit key4=P3^3;u16 t;u8 sec;u8 DisplayData[2];u8 code smgduan[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f}; void Time1Init(){TMOD |= 0x10;TH1=0Xd8;TL1=0Xf0;EA=1;ET1=1;}void delay(u16 i){while(i--); }void DigDisplay(){u8 i;for(i=0;i<2;i++){switch(i){case 0:LSA=0;LSB=0;LSC=0;break;case 1:LSA=1;LSB=0;LSC=0;break;}P0=DisplayData[i];delay(100);P0=0x00;}}void datapros(){DisplayData[0]=smgduan[sec%10];DisplayData[1]=smgduan[sec/10];}void main(){Time1Init();while(1){if(key4==0){delay(1000);if(key4==0){TR1=!TR1;while(key4==0);}}if(key3==0){delay(1000);if(key3==0){sec=0;while(key3==0);}}if(key2==0){delay(1000);if(key2==0){sec--;while(key2==0);}}if(key1==0){delay(1000);if(key1==0){sec++;while(key1==0);}}}}void Time1() interrupt 2{TH1=0Xd8;TL1=0Xf0;t++;if(t==100){t=0;sec++;if(sec>=60){sec=0;}}datapros();DigDisplay();}五、实验体会——结果分析1、独立按键:位定义四个按键key1、key2、key3、key4,宏定义LED为P2口,tab数组保存流水灯D0-D7依次点亮的数值,begMid数组保存流水灯同时从两侧向中间逐步点亮,之后再从中间向两侧逐渐熄灭的赋值方式。
外部中断扫描矩阵键盘;将4个7段数码显示器显示的内容放在4个显存中,4个显存空间定义如下LED0 EQU30HLED1 EQU31HLED2 EQU32HLED3 EQU 33HORG 0000HLJMP MAINORG0003H;转入外部中断0服务程序入口LJMP INP0ORG0040HMAIN: MOV SP, #60HSETB EX0 ;开INT0中断SETB IT0 ;设置中断触发方式SETB EA ;开总中断MOV LED0, #0MOV LED1, #1MOV LED2, #2MOV LED3, #3START: MOV P0, #00H;使显示器不显示MOV P2, #0FFH;关闭显示器位选择码目的也是使显示器不显示MOV A, LED0LCALL DISP0 ;调用将数值转换为显示段码并在P0端口输出的子程序CLR P2.0;最后一位七段数码管显示LCALL DELAY ;少许延时目的是使得数码管更亮MOV P0, #00H;使显示器不显示MOV P2, #0FFH ;MOV A, LED1LCALL DISP0 ;调用将数值转换为显示段码并在P0端口输出的子程序CLR P2.1;倒数第二位七段数码管显示LCALL DELAYMOV P0, #00H;使显示器不显示MOV P2, #0FFH ;MOV A, LED2LCALL DISP0 ;调用将数值转换为显示段码并在P0端口输出的子程序CLR P2.2 ;倒数第三位七段数码管显示LCALL DELAYMOV P0, #00H;使显示器不显示MOV P2, #0FFH ;MOV A, LED3LCALL DISP0 ;调用将数值转换为显示段码并在P0端口输出的子程序CLR P2.3;倒数第四位七段数码管显示LCALL DELAYLJMP START ;跳回初始位置,使程序循环;;;;;;;;;;;;;;;;;;;;;;;;;;;中断程序INP0: CLR EAPUSH PSWPUSH ACCPUSH BJB P2.3, NP2 ;P2.3口输出低电平,扫描K0,K1,K2,K3SK0: JB P2.4, SK1 ;P2.4为高电平扫描K0LCALL OPRK0 ;P2.4为低电平执行K0对应子程序LCALL DELAY1 ;延时去除抖动LJMP SKLOOP ;重新循环扫描SK1: JB P2.5, SK2LCALL OPRK1LCALL DELAY1 ;延时去除抖动LJMP SKLOOPSK2: JB P2.6, SK3LCALL OPRK2LCALL DELAY1 ;延时去除抖动LJMP SKLOOPSK3: JB P2.7, NP2 ;换一次输出位LCALL OPRK3LCALL DELAY1 ;延时去除抖动LJMP SKLOOPNP2: JB P2.2, NP3 ;P2.2口输出低电平,扫描K4,K5,K6,K7 SK4: JB P2.4, SK5 ;P2.4为高电平扫描K5LCALL OPRK4 ;P2.4为低电平执行K5对应子程序LCALL DELAY1 ;延时去除抖动LJMP SKLOOP ;重新循环扫描SK5: JB P2.5, SK6LCALL OPRK5LCALL DELAY1 ;延时去除抖动LJMP SKLOOPSK6: JB P2.6, SK7LCALL OPRK6LCALL DELAY1 ;延时去除抖动LJMP SKLOOPSK7: JB P2.7, NP3 ;换一次输出位LCALL OPRK7LCALL DELAY1 ;延时去除抖动LJMP SKLOOPNP3: JB P2.1, NP4 ;P2.1口输出低电平,扫描K8,K9,KA,KB SK8: JB P2.4, SK9 ;P2.4为高电平扫描K8LCALL OPRK8 ;P2.4为低电平执行K8对应子程序LCALL DELAY1 ;延时去除抖动LJMP SKLOOP ;重新循环扫描SK9: JB P2.5, SKALCALL OPRK9LCALL DELAY1 ;延时去除抖动LJMP SKLOOPSKA: JB P2.6, SKBLCALL OPRKALCALL DELAY1 ;延时去除抖动LJMP SKLOOPSKB: JB P2.7, NP4 ;换一次输出位LCALL OPRKBLCALL DELAY1 ;延时去除抖动LJMP SKLOOPNP4: JB P2.0, SKLOOP;P2.0口输出低电平,扫描KC,KD,KE,KF SKC: JB P2.4, SKD ;P2.4为高电平扫描KCLCALL OPRKCLCALL DELAY1 ;延时去除抖动LJMP SKLOOP ;重新循环扫描SKD: JB P2.5, SKELCALL OPRKDLCALL DELAY1 ;延时去除抖动LJMP SKLOOPSKE: JB P2.6, SKFLCALL OPRKELCALL DELAY1 ;延时去除抖动LJMP SKLOOPSKF: JB P2.7, SKLOOP ;换一次输出位LCALL OPRKFLCALL DELAY1 ;延时去除抖动LJMP SKLOOPSKLOOP: POP BPOP ACCPOP PSWSETB EARETI;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;子程序OPRK0: MOV P1, #00HSETB P1.0MOV LED3, #16MOV LED1, #1MOV LED0, #0RETOPRK1: MOV P1, #00HSETB P1.1MOV LED3, #16MOV LED2, #18MOV LED1, #1MOV LED0, #1RETOPRK2: MOV P1, #00HSETB P1.2MOV LED3, #16MOV LED2, #18MOV LED1, #1MOV LED0, #2RETOPRK3: MOV P1, #00HSETB P1.3MOV LED3, #16MOV LED2, #18MOV LED1, #1MOV LED0, #3RETOPRK4: MOV P1, #00HSETB P1.4MOV LED3, #16MOV LED2, #18MOV LED1, #1MOV LED0, #4RETOPRK5: MOV P1, #00HSETB P1.5MOV LED3, #16MOV LED2, #18MOV LED1, #1RETOPRK6: MOV P1, #00HSETB P1.6MOV LED3, #16MOV LED2, #18MOV LED1, #1MOV LED0, #6RETOPRK7: MOV P1, #00HSETB P1.7MOV LED3, #16MOV LED2, #18MOV LED1, #1MOV LED0, #7RETOPRK8: MOV P1, #00HSETB P1.0MOV LED3, #16MOV LED2, #18MOV LED1, #3MOV LED0, #0RETOPRK9: MOV P1, #00HSETB P1.1MOV LED3, #16MOV LED2, #18MOV LED1, #3MOV LED0, #1RETOPRKA: MOV P1, #00HSETB P1.2MOV LED3, #16MOV LED2, #18MOV LED1, #3MOV LED0, #2RETOPRKB: MOV P1, #00HSETB P1.3MOV LED3, #16MOV LED2, #18MOV LED1, #3MOV LED0, #3RETOPRKC: MOV P1, #00HSETB P1.4MOV LED3, #16MOV LED2, #18MOV LED1, #3MOV LED0, #4RETOPRKD: MOV P1, #00HSETB P1.5MOV LED3, #16MOV LED2, #18MOV LED1, #3MOV LED0, #5RETOPRKE: MOV P1, #00HSETB P1.6MOV LED3, #16MOV LED2, #18MOV LED1, #3MOV LED0, #6RETOPRKF: MOV P1, #00HSETB P1.7MOV LED3, #16MOV LED2, #18MOV LED1, #3MOV LED0, #7RETDELAY: MOV R6, #1;D2: MOV R7, #200;DJNZ R7, $ ;DJNZ R6, D2 ;RET ;DELAY1: MOV R2, #1D1: MOV R3, #200;D3: MOV R4, #200;DJNZ R4, $ ;DJNZ R3, D3 ;DJNZ R2, D1RETDISP0: MOV DPTR, #TABMOVC A, @A+DPTR ;将数值转换为显示段码MOV P0, A;将查得的段码显示RET;;;;;;;;;;;;;;;;;;;;;;;;;;;;;段码表TAB: DB 3FH,06H,5BH,4FH,66H,6DH,7DH,07H,7FH,6FH,77H,7CH,39H,5EH,79H,71H,40H,80H,73H ; '0' '1' '2' '3' '4' '5' '6' '7' '8 ' '9' 'A' 'B' 'C' 'D' 'E' 'F' '-' '.' 'P'; 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 END;结束程序。