1、单片机按键的解决解决方案1、 单片机上的按键控制一般采用两种控制方法:中断和查询。中断必须借助中断引脚,而查询按键可用任何 IO 端口。按键较少时,一个按键占用一个端口,而按键较多时,多采用矩阵形式( 如:经常用 4 个端口作为输出,4 个端口作为输入的 4X4 矩阵来获得16 个按键);还可以用单片机的 AD 转换功能一个引脚接多个按键,根据电阻分压原理判断是哪个按键按下。2、 中断形式STM32 可支持 68 个中断通道,已经固定分配给相应的外部设备,每个中断通道都具备自己的中断优先级控制字节 PRI_n(8 位,但是 STM32 中只使用 4 位,高 4 位有效) ,每4 个通道的 8
2、位中断优先级控制字构成一个 32 位的优先级寄存器。68 个通道的优先级控制字至少构成 17 个 32 位的优先级寄存器.4bit 的中断优先级可以分成 2 组,从高位看,前面定义的是抢占式优先级,后面是响应优先级。按照这种分组,4bit 一共可以分成 5 组 第 0 组:所有 4bit 用于指定响应优先级; 第 1 组:最高 1 位用于指定抢占式优先级,后面 3 位用于指定响应优先级; 第 2 组:最高 2 位用于指定抢占式优先级,后面 2 位用于指定响应优先级; 第 3 组:最高 3 位用于指定抢占式优先级,后面 1 位用于指定响应优先级; 第 4 组:所有 4 位用于指定抢占式优先级。所
3、谓抢占式优先级和响应优先级,他们之间的关系是:具有高抢占式优先级的中断可以在具有低抢占式优先级的中断处理过程中被响应,即中断嵌套。当两个中断源的抢占式优先级相同时,这两个中断将没有嵌套关系,当一个中断到来后,如果正在处理另一个中断,这个后到来的中断就要等到前一个中断处理完之后才能被处理。如果这两个中断同时到达,则中断控制器根据他们的响应优先级高低来决定先处理哪一个;如果他们的抢占式优先级和响应优先级都相等,则根据他们在中断表中的排位顺序决定先处理哪一个。每一个中断源都必须定义 2 个优先级。有几点需要注意的是: 1)如果指定的抢占式优先级别或响应优先级别超出了选定的优先级分组所限定的范围,将可
4、能得到意想不到的结果; 2)抢占式优先级别相同的中断源之间没有嵌套关系;3)如果某个中断源被指定为某个抢占式优先级别,又没有其它中断源处于同一个抢占式优先级别,则可以为这个中断源指定任意有效的响应优先级别。GPIO 外部中断:STM32 中,每一个 GPIO 都可以触发一个外部中断,但是,GPIO 的中断是以组为一个单位的,同组间的外部中断同一时间智能使用一个,如:PA0,PB0,PC0,PD0,PE0,PF0 这些为 1 组,如果我们使用 PA0 作为外部中断源,那么别的就不能使用了,在此情况下我们使用类似于 PB1,PC2 这种末端序号不同的外部中断源,每一组使用一个中断标志EXTI x.
5、EXTI0EXTI4 这 5 个外部中断有着自己单独的中断响应函数。EXTI5EXTI9 共用一个中断响应函数,EXTI10EXTI15 共使用一个中断响应函数。对于中断的控制,STM32 有一个专用的管理机构 NVIC.中断的使能,挂起,优先级,活动等等都是由 NVIC 在管理的。编写 IO 口外部中断步骤及其注意事项:(1) 设置中断优先级组;(2)开启时钟(IO 口时钟,复用时钟);(3)设置中断线并对中断进行初始化配置( 设置中断线,确定中断模式,中断触发沿设置,使用指定设置初始化外部中断); (4)设置中断管理器 NVIC 各参数(包括:使能产生外部中断外设的 IO口所在的外部中断通
6、道;设置外部中断的优先级-抢占优先级,响应优先级;使能外部中断通道;使用设置好的各个中断管理器上的参数来初始化中断管理器)。外部中断服务函数完成中断操作需要最终达到的目标。3、 矩阵形式键盘矩阵原理:a*b 矩阵键盘由 a 条行线和 b 条列线组成,行线接端口 P3(p3 表任一端口)P3.0、P3.1、P3.2p3.(a-1); 列线接 p 3.a,p3.(a+1)P3.(b-1).按键位于每条行线和列线的交叉点上。按键的识别可采用行扫描法和线反转法,这里采用简单的线反转法,只需三步。第一步,执行程序使 X0X3 均为低电平,此时读取各列线 Y0Y3 的状态即可知道是否有键按下。当无键按下时
7、,各行线与各列线相互断开,各列线仍保持为高电平;当有键按下时,则相应的行线与列线通过该按键相连,该列线就变为低电平,此时读取Y0Y1Y2Y3 的状态,得到列码。第二步,执行程序使 Y0Y3 均为低电平,当有键按下时,X0X3 中有一条行线为低电平,其余行线为高电平,读取 X0X1X2X3 的状态,得到行码。第三步,将第一步得到的列码和第二步得到的行码合并得到按键的位置码,即是Y3Y2Y1Y0X3X2X1X0(因为行线和列线各有一条电平,其余为高电平,所以位置码低四位和高四位分别只有一位低电平,其余为高电平)。也就是说,当某个键按下时,该键两端所对应的行线和列线为低电平,其余行线和列线为高电平.
8、比如,当 0 键按下时,行线 X0 和列线 Y0 为低电平,其余行列线为高电平,于是可以得到 0 键的位置码 Y3Y2Y1Y0x3X2X1X0 为 11101110 即是 0xEE.全部按键码为:矩阵键盘在单片机上的简单应用-显示数码管:0F(51 单片机)#include#define uchar unsigned char#define uint unsigned intSbit buzzer =P10;Uchar code_dis=/09,AF0xC0,0XF9,0XA4,0xB0,0x99,0x92,0x82,0xf8,0x80,0x90,0z88,0x83,0xC6,0xA1,0x8
9、6,0x8E;Uchar code_tab=/矩阵键盘按键位置码0x77,0xb7,0xd7,0xe7,0x7b,0xbb,0xdb,0xeb,0x7d,0xbd,0xdd,0xed,0x7e,0xbe,0xde,0xee;void delay(uint x) /延时函数uchar i; while(x-) for(i=0;i0;x-)for(y=110;y0;y-);uchar keyscan();/声明一下/void display(uchar num1);/这里可以做个显示函数,但是我没做。void main()num = 17;/让它显示 0 什么都不显示。 因为函数返回 num 值d
10、ula =1 ;P0= 0;dula =0;wela = 1;P0= 0xc0;wela = 0;/以上 P0 口控制数码管的一上电什么都不显示while(1)num1 = keyscan();/没按下返回 17dula =1;P0= tablenum1-1;/17-1 =16dula = 0;/用 uchar keyscan() 带返回值的函数 代替整个矩阵键盘 当然显示就不要了 dula 那3 行我注释掉了uchar keyscan()P3= 0xfe; /高 4 位是 f 等于写了 1 1 1 1 也满足了先写 1 的要求temp =P3;/读回来了temp /因为我们只是读回来高 4
11、位while (temp != 0xf0) /下面的几个 while 循环判断可以用 if 好理解。只看到第一行就行了。/这几个 while 都是做判断用的delay(5);/消除抖动的temp=P3;temp while(temp != 0xf0) /确实不等于 0xf0 有按键按下temp = P3;/我们这个时候只是把 P3 口的值赋给了 tempswitch (temp) /检测 P3 口。case 0xee:num = 1; break;case 0xde: num=2;break;case 0xbe:num=3; break;case 0x7e:num=4;break;while(
12、temp != 0xf0)/有按键按下可能是不等于的 循环在这里面 松手检测temp = P3;temp = temp /这个是松手检测 松手这里就等于了 0xf0/下面就显示一下 退出整个一行的循环,不加松手检测会退不出去循环/到这里是把第一行检测了。/以下下是其他几行检测的代码P3= 0xfd; /高 4 位是 f 等于写了 1 1 1 1 也满足了先写 1 的要求temp =P3;/读回来temp /因为我们只是读回来高 4 位while (temp != 0xf0)delay(5);/消除抖动的temp=P3;temp while(temp != 0xf0) /确实不等于 0xf0 有
13、按键按下temp = P3;/我们这个时候只是把 P3 口的值赋给了 tempswitch (temp) /检测 P3 口。case 0xed:num = 5; break;case 0xdd: num=6;break;case 0xbd:num=7; break;case 0x7d:num=8;break;while(temp != 0xf0)/有按键按下可能是不等于的 循环在这里面 松手检测temp = P3;temp = temp /这个是松手检测 松手这里就等于了 0xf0/下面就显示一下 退出整个 2 行的循环。不加松手检测会退不出去循环/到这里是把第 2 行检测了。P3= 0xfb
14、; /高 4 位是 f 等于写了 1 1 1 1 也满足了先写 1 的要求temp =P3;/读回来了temp /因为我们只是读回来高 4 位while (temp != 0xf0)delay(5);/消除抖动的temp=P3;temp while(temp != 0xf0) /确实不等于 0xf0 有按键按下temp = P3;/我们这个时候只是把 P3 口的值赋给了 tempswitch (temp) /检测 P3 口。case 0xeb:num =9; break;case 0xdb: num=10;break;case 0xbb:num=11; break;case 0x7b:num=
15、12;break; while(temp != 0xf0)/有按键按下可能是不等于的 循环在这里面 松手检测 temp = P3;temp = temp /这个是松手检测松手这里就等于了 0xf0 /下面就显示一下 退出整个 3 行的循环。 不加松手检测会退不出去循环 /到这里是把第 3 行检测了。P3= 0xf7; /高 4 位是 f 等于写了 1 1 1 1 也满足了先写 1 的要求temp =P3;/读回来了temp /因为我们只是读回来高 4 位while (temp != 0xf0)delay(5);/消除抖动的temp=P3;temp while(temp != 0xf0) /确实
16、不等于 0xf0 有按键按下temp = P3;/我们这个时候只是把 P3 口的值赋给了 tempswitch (temp) /检测 P3 口 case 0xe7:num =13 ; break;case 0xd7: num=14;break;case 0xb7:num=15; break;case 0x77:num=16;break; while(temp != 0xf0)/有按键按下可能是不等于的 循环在这里面 松手检测temp = P3;temp = temp /这个是松手检测 松手这里就等于了 0xf0/下面就显示一下 退出整个 4 行循环。不加松手检测会退不出去循/到这里是把第 4 行检测了。return num; /其实键盘扫描就需要一个值。4、 电阻分压控制按键电阻分压控制按键方式原理:利用电阻分压,使得不同按键处的电压值不同,通过检测按键处的电压值,判断是哪个按键按下了。不同的按键可以看做是使用一个电位器旋钮采集一个 ADC 通道上的 ADC 值过程中电位器旋钮旋动过程中的不同位置。注:串联在电路中的电阻可以是相同阻值的电阻,也可以是不同电阻值的电阻。一切视具体情况而定。