矩阵按键
*觉得有用有帮助的评论下,谢谢~
矩阵按键
原理图
独立按键一个按键就要占用一个IO口,整个单片机也就32个IO口,全部用完也控制不了几个按键,太占用资源,而矩阵按键则在这方面更有优势,可以只用8个IO口就可以控制16个按键。
使用方法
- 逐行扫描:我们可以通过高四位轮流输出低电平来对矩阵键盘进行逐行扫描,当低四位接收到的数据不全为1的时候,说明有按键按下,然后通过接收到的数据是哪一位为0来判断是哪一个按键被按下。
如
P-10~P-17
的电平为0111 1111
,假如这时 S2 按键被按下,这时P-10~P-17
数据则则为0111 1011
P-10~P-13
的电平轮流为0
,0111-1011-1101-1110,每变一次就查一遍低四位的电平数据
- 行列扫描:我们可以通过高四位全部输出高电平,低四位输出低电平。当接收到的数据,高四位不全为高电平时,说明有按键按下,然后通过接收的数据值,判断是哪一行有按键按下,然后再反过来,高四位输出低电平,低四位输出高电平,然后根据接收到的低四位的值判断是那一行有按键按下,这样就能够确定是哪一个按键按下了。
如先把
P-10~P-17
设置为1111 0000
进行 行 测试,假如这时第一行有按键按下,这时JP4
的数据则为1110 0000
,这时还不知道第一行的哪个按键按下,我们就反过来,设置JP4
值为0000 1111
,如果测得JP4
的值为0000 1011
,则可知是 第2列 有按键按下,再结合行测试,就可知是 S2 按下。
C语言语句
- 这里我们要用到
switch
语句,这是一个选择语句
switch(表达式)
{
case(常量表达式1): 语句1; break;
case(常量表达式2): 语句2; break;
case(常量表达式3): 语句3; break;
case(常量表达式4): 语句4; break;
default:break;//默认..可以省略
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
表达式与哪个常量表达式值相同就执行哪个语句
程序
- 效果:按下
S1~S16
,在静态数码管上一一对应显示1~F
#include <reg52.H>
#include "intrins.h"
typedef unsigned char u8;
#define GPIO_DIG P0 //通用接口输入
#define GPIO_KEY P1 //按键接口输入
u8 KeyValue; //定义一个全局变量,用来存放按键的值
u8 code smgduan[17]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};//共阴
void delay10ms() //误差 0us
{
unsigned char a,b,c;
for(c=1;c>0;c–)
for(b=38;b>0;b–)
for(a=130;a>0;a–);
}
void JzKey() //矩阵按键程序
{
u8 a=0;
GPIO_KEY=0xf0; //矩阵按键低4位低电平,高四位为高电平,测试行
if(GPIO_KEY!=0xf0)
{
delay10ms(); //消抖
if(GPIO_KEY!=0xf0)
{
switch(GPIO_KEY)
{
case(0xe0): KeyValue=0;break;
case(0xd0): KeyValue=1;break;
case(0xb0): KeyValue=2;break;
case(0x70): KeyValue=3;break;
<span class="token punctuation">}</span>
GPIO_KEY<span class="token operator">=</span><span class="token number">0x0f</span><span class="token punctuation">;</span><span class="token comment">//与上相反,测试列 </span>
<span class="token keyword">switch</span><span class="token punctuation">(</span>GPIO_KEY<span class="token punctuation">)</span>
<span class="token punctuation">{</span>
<span class="token keyword">case</span><span class="token punctuation">(</span><span class="token number">0x0e</span><span class="token punctuation">)</span><span class="token punctuation">:</span> KeyValue<span class="token operator">=</span>KeyValue<span class="token punctuation">;</span><span class="token keyword">break</span><span class="token punctuation">;</span>
<span class="token keyword">case</span><span class="token punctuation">(</span><span class="token number">0x0d</span><span class="token punctuation">)</span><span class="token punctuation">:</span> KeyValue<span class="token operator">=</span>KeyValue<span class="token operator">+</span><span class="token number">4</span><span class="token punctuation">;</span><span class="token keyword">break</span><span class="token punctuation">;</span>
<span class="token keyword">case</span><span class="token punctuation">(</span><span class="token number">0x0b</span><span class="token punctuation">)</span><span class="token punctuation">:</span> KeyValue<span class="token operator">=</span>KeyValue<span class="token operator">+</span><span class="token number">8</span><span class="token punctuation">;</span><span class="token keyword">break</span><span class="token punctuation">;</span>
<span class="token keyword">case</span><span class="token punctuation">(</span><span class="token number">0x07</span><span class="token punctuation">)</span><span class="token punctuation">:</span> KeyValue<span class="token operator">=</span>KeyValue<span class="token operator">+</span><span class="token number">12</span><span class="token punctuation">;</span><span class="token keyword">break</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">while</span><span class="token punctuation">(</span><span class="token punctuation">(</span>a<span class="token operator"><</span><span class="token number">50</span><span class="token punctuation">)</span><span class="token operator">&&</span><span class="token punctuation">(</span>GPIO_KEY<span class="token operator">!=</span><span class="token number">0x0f</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token comment">//检测按键松手检测</span>
<span class="token punctuation">{</span>
<span class="token function">delay10ms</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
a<span class="token operator">++</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
}
void main()
{
while(1)
{
JzKey();
GPIO_DIG=~smgduan[KeyValue];//数码管显示
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
扩展
- 当我做完上面的实验时,突然想起来以前用计算器的时候,每按一下,都会响一声,这样就可以知道你按到没有,因此我就想在这实现每当按键按下时,蜂鸣器就响,松开时,蜂鸣器就停。
定时器中断
- 为了实现上述功能,我在这里用到了 定时器 ,这里我就直接介绍它的用法
用法
- 一般比较常用的 方式1 和 方式2
要注意的是,用 方式1 时,要手动重装初值!
定时器中断程序
void InitTimer0(void) //定时器0程序
{
TMOD = 0x01; //设置工作方式
TH0 = 0x0FF; //设置初值
TL0 = 0x9C;
EA = 1; //中断总开关
ET0 = 1; //定时/计数器0中断允许控制
TR0 = 1; //定时器开关
}
void Timer0Interrupt(void) interrupt 1 //定时器中断程序
{
TH0 = 0x0FF; //重装初值
TL0 = 0x9C;
fmq=~fmq; //蜂鸣器
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 要实现扩展功能,只需加个定时器中断, 定时器中断 来控制 蜂鸣器 的响与停,先把 定时器0程序 里的定时器开关
TR0=0
;在按键按下后,在让TR0=1
,让定时器开始定时,蜂鸣器就响了,在检测到按键松开后,这时在让TR0=0
,停止定时器,这时蜂鸣器就停了。
完美收工~~~~
</div>
<link href="https://csdnimg.cn/release/phoenix/mdeditor/markdown_views-e9f16cbbc2.css" rel="stylesheet">
</div>
</article>
<div class="postTime">
<div class="article-bar-bottom">
<span class="time">
文章最后发布于: 2018-11-22 13:44:57 </span>
</div>
</div>
*觉得有用有帮助的评论下,谢谢~
矩阵按键
原理图
独立按键一个按键就要占用一个IO口,整个单片机也就32个IO口,全部用完也控制不了几个按键,太占用资源,而矩阵按键则在这方面更有优势,可以只用8个IO口就可以控制16个按键。
使用方法
- 逐行扫描:我们可以通过高四位轮流输出低电平来对矩阵键盘进行逐行扫描,当低四位接收到的数据不全为1的时候,说明有按键按下,然后通过接收到的数据是哪一位为0来判断是哪一个按键被按下。
如
P-10~P-17
的电平为0111 1111
,假如这时 S2 按键被按下,这时P-10~P-17
数据则则为0111 1011
P-10~P-13
的电平轮流为0
,0111-1011-1101-1110,每变一次就查一遍低四位的电平数据
- 行列扫描:我们可以通过高四位全部输出高电平,低四位输出低电平。当接收到的数据,高四位不全为高电平时,说明有按键按下,然后通过接收的数据值,判断是哪一行有按键按下,然后再反过来,高四位输出低电平,低四位输出高电平,然后根据接收到的低四位的值判断是那一行有按键按下,这样就能够确定是哪一个按键按下了。
如先把
P-10~P-17
设置为1111 0000
进行 行 测试,假如这时第一行有按键按下,这时JP4
的数据则为1110 0000
,这时还不知道第一行的哪个按键按下,我们就反过来,设置JP4
值为0000 1111
,如果测得JP4
的值为0000 1011
,则可知是 第2列 有按键按下,再结合行测试,就可知是 S2 按下。
C语言语句
- 这里我们要用到
switch
语句,这是一个选择语句
switch(表达式)
{
case(常量表达式1): 语句1; break;
case(常量表达式2): 语句2; break;
case(常量表达式3): 语句3; break;
case(常量表达式4): 语句4; break;
default:break;//默认..可以省略
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
表达式与哪个常量表达式值相同就执行哪个语句
程序
- 效果:按下
S1~S16
,在静态数码管上一一对应显示1~F
#include <reg52.H>
#include "intrins.h"
typedef unsigned char u8;
#define GPIO_DIG P0 //通用接口输入
#define GPIO_KEY P1 //按键接口输入