首页 技术 正文
技术 2022年11月10日
0 收藏 845 点赞 2,677 浏览 3465 个字

1.按键的使用特点

  按键的应用主要是在按键闭合时改变电路的电平,但是一般情况下按键的开关都是机械弹性触点开关,即利用触点的接触和分离来实现电路的通断,所以在按键按下和释放时往往会产生抖动干扰。

消除抖动干扰的两种方式:

  (1)硬件设计:硬件消抖要在硬件设计上增加消抖电路,如用R-S触发器等,这样就会增加系统成本。

  (2)软件设计:在软件中对按键进行二次测试确认,即当第一次检测到按键被按下后,间隔10 毫秒左右再次检测该按键是否被按下,只有两次都册到按键按下时才确认该按键被按下了,从而消除抖动干扰。

2.单键盘扫描应用

用PB口接一个LED数码管,来显示按下按键的次数;

用PC0端口接一个按键电路;

ATmega8仿真——键盘扫描的学习

  实现的功能是每一次按键,LED数码管显示的数据加1,到9回0。

 #include <iom8v.h>
#include "Delay.h"
/**
*PB口:连接一个LED数码管
*PC0:连接一个按键电路,按下呈低电平
*
*/
unsigned char CountNum; //全局变量,用来计数 //按键扫描函数
void ScanKey(void)
{
unsigned char key; key = PINC; //检测按键状态
if(0x01 == key) //未按下,退出
return;
delay_ms(); key = PINC; //再次检测,防抖动
if(0x01 == key) //未按下,退出
return;
CountNum++;
while( == key&0x01) //等到按键释放
key = PINC;
} //主函数,扫描按键显示数据
void main()
{
unsigned char num[] = {0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};
//初始化端口
DDRB = 0xFF; //设置B口为输出模式
PORTB = 0xFF; //置高电平
DDRC = 0x00; //设置C口为输入模式 CountNum = ; //初始化全局变量
while()
{
ScanKey(); //扫描按键
if(CountNum >= )
CountNum -= ;
PORTB = num[CountNum];
}
} //按键长按的情况
void ScanKey_Long(void)
{
unsigned char key; key = PINC; //检测按键状态
if(0x01 == key) //未按下,退出
return;
delay_ms(); key = PINC; //再次检测,防抖动
if(0x01 == key) //未按下,退出
return; while(0x00 == key) //按键长按,不断加加
{
CountNum++;
key = PINC;
}
}

按键一次LED加一

问:上面的程序没有考虑长按的情况,如果向我们使用的键盘一样,长时间按下一个按键,在屏幕上就不断的打印该字符,在这个例子里怎样实现:若长时间按下按键,CountNum就不断加加?

答:只需要更改ScanKey函数,更改结果如下

 //按键长按的情况
void ScanKey_Long(void)
{
unsigned char key; key = PINC; //检测按键状态
if(0x01 == key) //未按下,退出
return;
delay_ms(); key = PINC; //再次检测,防抖动
if(0x01 == key) //未按下,退出
return; while(0x00 == key) //按键长按,不断加加
{
CountNum++;
key = PINC;
}
}

长按按键不断加加

3.矩阵按键(键盘)扫描的应用

  按键太多的情况下,为了节省I/O资源,通常采用矩阵式的接口。矩阵键盘由行和列组成,每个键都有它的行值和列值,行值和列值的组合就是识别每个键盘的编码。

确定是哪个按键的流程:(???)

(1)在行和列的一个口中输出高电平,在另一个行列口读取一个扫描码;

(2)在后一个行列口中输出高电平,在前一行列口读取第二个扫描码;

(3)查表确定哪个按键被按下。

电路图如下:

ATmega8仿真——键盘扫描的学习

程序实现步骤:

(1)确定有无按键按下;

(2)确定是哪个按键;

(3)返回该按键值或处理对应的任务;

(4)再加上,考虑抖动消除,等待按键的断开。

要实现每按下一个按键,就在LED数码管显示出该按键对应的值,按键断开后或默认显示“-”:

 #include <iom8v.h>
#include "Delay.h"
/**
*PB口:连接一个LED数码管
*PC0-PC5:连接9个按键电路,按下呈低电平
* PC0-PC2:按键的行
* PC3-PC5:按键的列
*
*1:确定有无按键按下,main函数两次判断实现;
*2:确定是哪个按键,ScanKey函数实现;
*3:返回该键值或处理对应的任务,main函数中处理。
*/ //按键扫描函数,确定是哪个按键,返回按键的值
unsigned char ScanKey(void)
{
unsigned char tempH,tempL,key; tempH = PINC & 0x07; //取PC0-PC2用于判断行
switch (tempH)
{
case 0x06:
DDRC = 0x07; PORTC = 0x38;//将PC3-PC5(列)置为输入模式
delay_us();
tempL = PINC & 0x38; //取PC3-PC5用于判断列
switch (tempL)
{
case 0x30: key = 0x01; //得到键值
break;
case 0x28: key = 0x02;
break;
case 0x18: key = 0x03;
break;
default: key = ;
break;
}
DDRC = 0x38; PORTC = 0x07;//输入完毕恢复默认输出模式
break; case 0x05:
DDRC = 0x07; PORTC = 0x38;//将PC3-PC5(列)置为输入模式
delay_us();
tempL = PINC & 0x38; //取PC3-PC5用于判断列
switch (tempL)
{
case 0x30: key = 0x04; //得到键值
break;
case 0x28: key = 0x05;
break;
case 0x18: key = 0x06;
break;
default: key = ;
break;
}
DDRC = 0x38; PORTC = 0x07;//输入完毕恢复默认输出模式
break; case 0x03:
DDRC = 0x07; PORTC = 0x38;//将PC3-PC5(列)置为输入模式
delay_us();
tempL = PINC & 0x38; //取PC3-PC5用于判断列
switch (tempL)
{
case 0x30: key = 0x07; //得到键值
break;
case 0x28: key = 0x08;
break;
case 0x18: key = 0x09;
break;
default: key = ;
break;
}
DDRC = 0x38; PORTC = 0x07;//输入完毕恢复默认输出模式
break; default:
key = ;
break;
}
return (key); } //主函数,扫描按键显示数据
void main()
{
unsigned char temp,keynum;
unsigned char num[] = {0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};
//初始化端口
DDRB = 0xFF; //设置B口为输出模式
PORTB = 0xFF; //置高电平
//将PC0-PC2(行)置为输入模式
DDRC = 0x38;
PORTC = 0x07; while() //两次检测行中有没有按下
{
PORTC = 0x40; //没有按键时,LED默认显示-
//第一次检验
temp = PINC & 0x07;
if(0x07 == temp)
continue;
delay_ms();
//第二次检验
temp = PINC & 0x07;
if(0x07 == temp)
continue; //有按下,LED显示键值
keynum = ScanKey();
PORTB = num[keynum];
//等到按键被释放
while(0x07 != temp)
temp = PINC & 0x07;
}
}

矩阵键盘,LED显示其值

代码总结:

  主函数:判断是否有按键按下,并消除抖动干扰,若有则将获得的键值显示在LED数码管中;

  ScanKey函数:得到扫描码确定是哪个按键,等待按键释放,返回该按键的值。

方法扩展:

(1)除了像上面的对按键的接口不停的扫描,

(2)还可以使用定时扫描,例如用一个定时器,每隔10MS 对按键接口进行扫描,看是否有按键按下;

(3)也可以使用中断的方式去扫描,当按键按下时由硬件电路产生一个中断,MCU 响应该中断,确定哪个按键被按下,处理相应函数。

相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:9,104
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,581
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,428
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,200
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:7,835
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:4,918