整理第8章键盘.docx
- 文档编号:23234503
- 上传时间:2023-05-15
- 格式:DOCX
- 页数:26
- 大小:103.19KB
整理第8章键盘.docx
《整理第8章键盘.docx》由会员分享,可在线阅读,更多相关《整理第8章键盘.docx(26页珍藏版)》请在冰豆网上搜索。
整理第8章键盘
第8章键盘
键盘是嵌入式应用的常用外部设备之一。
识别键盘是否有键被按下的方法有查询法、定时扫描法与中断法等,中断法是较常用的方法。
GP32单片机PTA口的引脚与键盘中断输入引脚复用。
本章介绍键盘中断模块的编程方法,并给出规范的扫描法识别键值子程序、键值转为定义值子程序,及测试实例。
本章重点是掌握扫描法读取键值、键值转为定义值的编程方法。
8.1键盘基本问题与GP32的键盘中断口
本节首先简要阐明有关键盘识别的一些基本问题,随后给出GP32单片机的键盘中断口的使用方法。
8.1.1键盘模型及接口
键盘是由若干个按键组成的开关矩阵,它是最简单的单片机的数字量输入设备,操作员通过键盘输入数据或命令,实现简单的人-机通信。
(1)键盘模型式
图8-1键盘模型及按键抖动示意图
键盘的基本电路是一个接触开关,通、断两种状态分别表示0和1,如图8-1所示的简单电路,微处理器很容易检测到开关的闭合。
当开关打开时,提供逻辑“1”;当开关闭合时,提供逻辑“0”。
(2)键盘接口
键盘接口按照不同的标准有不同的分类方法。
按键盘排布的方式可分成独立方式和矩阵方式;按读入键值的方式可分为直读方式和扫描方式;按是否进行硬件编码可分成非编码方式和硬件编码方式;按微处理器响应方式可分为中断方式和查询方式。
将以上各种方式组合可构成不同的键盘接口方式。
以下介绍较为常用的两种方式。
①独立方式
独立方式是指将每个独立按键按一对一的方式直接接到I/O输入线上。
如图8-2所示。
读键值时直接读I/O口,每一个键的状态通过读入键值来反映,所以也称这种方式为一维直读方式,按习惯称为独立式。
这种方式查键实现简单,但占用I/O资源较多,一般在键的数量较少时采用。
图8-2独立键盘
图8-3矩阵键盘
②矩阵方式
矩阵方式是用n条I/O线组成行输入口,m条I/O线组成列输出口,在行列线的每一个交点上设置一个按键,如图8-3所示。
读键值方法一般采用扫描方式,即输出口按位轮换输出低电平,再从输入口读入键信息,最后获得键码。
这种方式占用I/O线较少,在实际应用系统中采用较多。
设计键盘的时候,通常小于4个按键的应用,可以使用独立式接口。
如果多于4个按键,为了减少微处理器的I/O端口线的占用,可以使用矩阵式键盘。
8.1.2键盘的基本问题
键盘是由若干个按键组成的开关矩阵,它是最简单的单片机的数字量输入设备,操作员通过键盘输入数据或命令,实现简单的人-机通信。
为了能实现对键盘的编程至少应该了解下面几个问题:
第一,如何识别键盘上的按键?
第二,如何区分按键是被真正地按下,还是抖动?
第三,如何处理重键问题?
了解这些问题有助于键盘编程。
(1)键的识别
如何知道键盘上哪个键被按下就是键的识别问题。
若键盘上闭合键的识别由专用硬件实现,称为编码键盘;而靠软件实现的称为未编码键盘。
在这里我们主要讨论未编码键盘的接口技术和键盘输入程序的设计。
识别是否有键被按下,主要有查询法、定时扫描法与中断法等。
而要识别键盘上哪个键被按下主要有行扫描法与行反转法。
(2)抖动问题
当手按下一个键时,会出现所按的键在闭合位置和断开位置之间跳几下才稳定到闭合状态的情况,当释放一个按键时也会出现类似的情况,这就是抖动问题。
抖动持续的时间因操作者而异,一般为5~10ms之间,稳定闭合时间一般为十分之几秒~几秒,由操作者的按键动作所确定。
在软件上,解决抖动的方法通常是延迟等待抖动的消失或多次识别判定。
(3)重键问题
所谓重键问题就是有两个及两个以上按键同时处于闭合状态的处理问题。
在软件上,处理重键问题通常有连锁法与巡回法。
图8-44×4键盘的结构
为了正确理解MCU键盘接口方法与编程技术,下面以4×4键盘为例说明按键识别的基本编程原理。
4×4的键盘结构如图8-4所示,图中列线(n1~n4)通过电阻接+5V,当键盘上没有键闭合时,所有的行线和列线断开,列线n1~n4都呈高电平。
当键盘上某一个键闭合时,则该键所对应的行线与列线短路。
例如,第2排第3个按键被按下闭合时,行线m2和列线n3短路,此时n3线上的电平由m2的电位所决定。
那么如何确定键盘上哪个按键被按下呢?
我们可以把列线n1~n4接到微机的输入口,行线m1~m4接到微机的输出口,则在微机的控制下,使行线m1为低电平(0),其余三根行线m2、m3、m4都为高电平,读列线n1~n4状态。
如果n1~n4都为高电平,则m1这一行上没有键闭合,如果读出列线n1~n4的状态不全为高电平,那么为低电平的列线和m1相交的键处于闭合状态;如果m1这一行上没有键闭合,接着使行线m2为低电平,其余行线为高电平,用同样方法检查m2这一行上有无键闭合;以此类推,最后使行线m4为低电平,其余的行线为高电平,检查m4这一行上是否有键闭合。
这种逐行逐列地检查键盘状态的过程称为对键盘的一次扫描。
CPU对键盘扫描可以采取程序控制的随机方式,CPU空闲时扫描键盘。
也可以采取定时控制,每隔一定时间,CPU对键盘扫描一次,CPU可随时响应键输入请求。
也可以采用中断方式,当键盘上有键闭合时,向CPU请求中断,CPU响应键盘输入中断,对键盘扫描,以识别哪一键处于闭合状态,并对键盘输入信息作出相应处理。
CPU对键盘上闭合键的键号确定,可以根据行线和列线的状态计算求得,也可以根据行线和列线状态查表求得。
8.1.3MC908GP32单片机的键盘中断模块
MC908GP32单片机的A口的8根引脚与键盘中断模块(KeyboardInterruptModule—KBI)的引脚复用,这里讨论A口作为键盘中断模块引脚的功能。
作为KBI引脚时,下面把8个引脚分别称为KBIE7pin—KBIE0pin。
它们提供了以中断方式识别是否有键被按下的硬件手段。
当然,如果不以中断方式识别键盘按键,可以屏蔽键盘中断,把A口作为一般I/O口对待。
本小节仅从编程角度介绍KBI,若需要详细了解有关KBI电路逻辑,可参阅芯片手册。
(1)键盘状态和控制寄存器(KeyboardStatusandControlRegister,INTKBSCR)
INTKBSCR包含了键盘中断请求标志、屏蔽键盘中断请求、定义键盘中断的触发方式、清除键盘中断标志等功能。
其地址是$001A。
数据位
D7
D6
D5
D4
D3
D2
D1
D0
定义
KEYF
ACKK
IMASKK
MODEK
复位
0
0
0
0
0
0
0
0
D7-D4:
未用。
读出均为0,没有具体含义。
D3—KEYF位(只读位):
键盘(中断)标志位(KeyboardFlagBit)。
KEYF=1,键盘中断已产生;KEYF=0,未产生键盘中断。
D2—ACKK位(只写位):
键盘(中断)应答位(KeyboardAcknowledgeBit)。
写入1,则清除键盘中断请求。
D1—IMASKK位:
键盘中断屏蔽位(KeyboardInterruptMaskBit)。
IMASKK=1,屏蔽键盘中断请求;IMASKK=0,开放键盘中断。
D0—MODEK位:
键盘中断引脚触发方式位(KeyboardTriggeringSensitivityBit)。
MODEK=1,下降沿及低电平触发;MODEK=0,仅下降沿触发。
(2)键盘中断允许寄存器(KeyboardInterruptEnableRegister,INTBIER)
INTBIER的各位决定所对应的引脚是否允许中断进入。
地址为:
$001B。
数据位
D7
D6
D5
D4
D3
D2
D1
D0
定义
KBIE7
KBIE6
KBIE5
KBIE4
KBIE3
KBIE2
KBIE1
KBIE0
复位
0
0
0
0
0
0
0
0
D7~D0,分别记为KBIE7—KBIE0,可读写。
若KBIEx=1,表示相应引脚KBIExpin(也就是引脚PTAxpin)被定义为中断输入引脚,反之则不能作为中断输入引脚。
复位时,全为0。
(3)键盘中断编程相关问题
要进行键盘中断方面的编程,下列问题也需要了解:
①键盘中断矢量地址:
$FFE0—$FFE1
②键盘中断初始化顺序:
先设置键盘状态和控制寄存器(INTKBSCR),后设置键盘中断允许寄存器(INTKBIER)。
一旦设置了引脚KBIExpin为键盘中断引入引脚,就默认了它为输入,但先它之前通过A口数据方向寄存器定义该引脚为输入且通过上拉电阻寄存器设置其有上拉电阻,再设置其为键盘中断引入引脚,则更可靠。
③当定义KBIExpin为键盘中断引入引脚时,由于内部上拉到逻辑1也许需要一些时间,可能产生开始时的键盘误中断。
为避免键盘误中断,建议在键盘初始化时,按下列顺序工作:
令IMASKK=1(屏蔽键盘中断)、设置KBIEx=1(定义中断引脚)、写ACKK=1(清除键盘中断请求)、令IMASKK=0(开放键盘中断)
也可以用下述方法:
通过DDRA定义PTAxpin为输出、写1到PTAx(使得PTAxpin为高电平)、设置KBIEx=1(定义中断引脚)
④注意在中断子程序中的入口和出口参数。
⑤在Wait和Stop模式下,键盘中断仍可发生。
8.2汇编语言键盘中断模块编程实例
本节给出一个实际的4×4键盘编程实例。
8.2.1按键识别与键盘定义子程序
(1)键值计算方法
图8-54×4键盘与单片机接法示例
本节给出键盘编程实例,其中涉及到如何扫描键盘取得键值、中断获取键值、键盘编码等问题。
键盘与单片机接线见图8-5,图8-6给出了键的定义符号“0”-“9”、“A”-“D”、“*”、“#”等。
如何识别“1”键呢?
这里将列线n1-n4分别接PTA4-PTA7,且编程时将PTA4-PTA7定义为输入并有内部上拉电阻,行线m1-m4分别接PTA0-PTA3,且编程时将PTA0-PTA3定义为输出,那么“1”键对应于:
PTA7~PTA0=11101110,即$EE;“2”键对应于:
PTA7~PTA0=11011110,即$DE;……;“D”键对应于:
PTA7~PTA0=01110111,即$77。
前者是我们的定义符号,后者是“键值”,这种情况“键值”是一个字节。
这样,按图8-5的接法可以得出键值表,见图8-6。
键值可以通过扫描法获得,由键值通过查表法编程得到定义值。
图8-6键盘定义
(2)键盘编程汇编语言子程序
下面给出有关键盘编程的汇编语言子程序。
它们是:
键盘中断初始化子程序、扫描法读取键值子程序、键值转为定义值子程序。
即使不使用中断方式识别按键,三个子程序仍然需要使用。
只不过键盘中断初始化子程序中改为不允许中断进入。
扫描法读取键值与键值转为定义值两个子程序在键盘编程中通常需要使用的。
①键盘子程序头文件KB.h
//[KB.h]键盘子程序定义头文件-----------------------------
//键盘控制引脚定义
KB_P=PTA//键盘接在PTA口上
KB_D=DDRA//相应的方向寄存器
KB_PUE=PTAPUE//相应的上拉电阻允许寄存器
②键盘子程序文件KB.s
//[KB.s]键盘子程序定义----------------------------------*
//本文件包含:
*
//
(1)KBInit:
初始化键盘控制及中断的相关寄存器*
//
(2)KBScan:
扫描4*4键盘,读取键值->A*
//(3)KBDef:
键值转为定义值*
//硬件连接:
*
//PTA7-4接键盘4根列线,PTA3-0接键盘4根行线*
//------------------------------------------------------*
.include"KB.h"//该头文件包含键盘控制引脚定义
//KBInit:
键盘初始化子程序-------------------------------*
//功能:
初始化键盘控制及中断的相关寄存器,但未开放键盘中断*
//入口:
无*
//出口:
无*
//堆栈深度:
2+1=3*
//------------------------------------------------------*
KBInit:
:
PSHA//[A进栈](保护寄存器A)
//复位相应寄存器
LDA#$00
STAKB_P
LDA#%00001111//使列线(7-4位)为输入
STAKB_D//使行线(3-0位)为输出
LDA#%11110000//输入引脚(列线)有内部上拉电阻
STAKB_PUE
BSET#1,INTKBSCR//屏蔽键盘中断(IMASKK=1)
LDA#%11110000//允许输入引脚的中断可进入
STAINTKBIER
BSET#2,INTKBSCR//清除键盘中断请求(ACKK=1)
PULA//[A出栈](恢复寄存器A)
RTS
//KBScan:
扫描读取键值子程序-----------------------------*
//功能:
扫描4*4键盘,读取键值->A,若无按键,$FF->A*
//入口:
无*
//出口:
A=键值*
//堆栈深度:
2+2=4*
//------------------------------------------------------*
KBScan:
:
AIS#-2//开辟临时变量
KBScan_1:
LDA#%11111110//使第一根行线为0(低电平)
STA1,SP
LDA#$04//最多将扫描4根行线
STA2,SP
KBScan_2:
//当前扫描的一行,输出低电平
LDAKB_P
ORA#%00001111
AND$1,SP
STAKB_P
//等待键按下
NOP
NOP
LDAKB_P
//通过观察4根列线中是否出现低电平
//来判断当前行有无按键
AND#%11110000//仅保留列线的值
CBEQA#$F0,KBScan_3//当前行无按键,转KBScan_3
//当前行有按键
LDAKB_P//A中存入按键值
BRAKBScan_Exit
KBScan_3:
//准备扫描下一行
SEC//C=1
ROL1,SP//使下一根行线输出低电平
DBNZ2,SP,KBScan_2//没有扫到按键且没有扫完4行
//4行扫完仍未扫到按键(认为无按键)
LDA#$FF
KBScan_Exit:
AIS#2//释放临时变量
RTS
//KBDef:
键值转为定义值子程序----------------------------*
//功能:
键值转为键盘定义值*
//入口:
A=键值*
//出口:
A=键定义值*
//堆栈深度:
2+3=5*
//------------------------------------------------------*
KBDef:
:
PSHH//[HX进栈](保护寄存器HX)
PSHX
AIS#-1//开辟临时变量
STA1,SP//键值存入[SP+1]
LDHX#KBTable//取键盘定义表首地址
KBDef_1:
//在键盘定义表中搜索欲转换的键值,直至表尾($00)
LDA,X
CMP#$00
BEQKBDef_3//表已搜完,表中无对应的键值定义
//表未搜完
CMP1,SP//表中当前键值与欲转换键值相比较
BNEKBDef_2//未找到对应键值,转KBDef_2
//找到对应键值
AIX#1//取相应定义值->A,并完成转换
LDA,X
BRAKBDef_Exit
KBDef_2:
AIX#2//指向下一个表中键值
BRAKBDef_1//继续判断
KBDef_3:
LDA#$FF//表中无对应的键值定义$FF->A
KBDef_Exit:
AIS#1//释放临时变量
PULX//[HX出栈](恢复寄存器HX)
PULH
RTS
//键盘定义表
KBTable:
:
.byte$EE,'1',$DE,'2',$BE,'3',$7E,'A'
.byte$ED,'4',$DD,'5',$BD,'6',$7D,'B'
.byte$EB,'7',$DB,'8',$BB,'9',$7B,'C'
.byte$E7,'*',$D7,'0',$B7,'#',$77,'D'
.byte$00
8.2.2键盘中断编程举例
下面给出的实例程序的功能是,当按下键盘上任何一个键,产生键盘中断,在键盘中断程序中,通过串行口发送“键值”及“键定义值”。
PC机用7.5.4节介绍的串口调试器,接收并显示。
键盘中断汇编工程文件组织如表8-1所示。
表8-1键盘中断汇编工程文件
工程文件名
KeyBoard_Int.prj
所在路径
MC08Ex2007\GP32\GP32S\S04_键盘中断编程
文件类型
文件名
功能简述
讲解章节
头文件
GP32ASM.h
芯片头文件
[汇编工程文件组织]4.3
Includes.h
总头文件
[汇编工程文件组织]4.3
KB.h
键盘子程序定义头文件
[本章]
SCI.h
串行通信头文件
[参见本工程实例]
汇编语言
子程序文件
MCUinit.s
芯片初始化文件
[初始化及PLL编程实例]14.2.5
EnDisInt.s
开放或禁止MCU各模块
[参见本工程实例]
Vectors08.s
中断处理子程序与中断向量表文件
[本章]
SCI.s
串行通信文件
[参见本工程实例]
KB.s
键盘子程序定义文件
[本章]
汇编语言主程序文件
Main.s
主程序文件
[本章]
(1)键盘中断编程汇编主程序
//------------------------------------------------------*
//工程名:
KeyBoard_Int.prj*
//硬件连接:
*
//
(1)MCU的A口接键盘(见"KB.s"文件中的说明)*
//程序描述:
按下键盘按键,串口发送对应的键值*
//目的:
键盘中断,键盘扫描,键值识别,键值转换*
//注意:
如果键盘插在实验板的上排插孔,无须连线,若插在*
//下排插孔,需手工接线*
//日期:
2007.07*
//--------清华2007版《嵌入式技术基础与实践》实例--------*
//头文件
.include"Includes.h"//总头文件
//主程序
.areaflash(abs)
.orgFlashStartAddr
MainInit:
:
//复位后从此处执行(见Vectors08.s文件末尾处)
SEI//关总中断
//1.堆栈初始化为RAM最高端
LDHX#RAMendAddr+1//HX=#RAMendAddr+1
TXS//HX-1->SP
//2.系统初始化
JSRMCUinit//初学时跳过此处
//3.串行口初始化
JSRSCIinit
//4.键盘初始化
JSRKBinit
JSREnableKBint//开放键盘中断
CLI//开总中断
//程序总循环入口
MainLoop:
NOP
NOP
BRAMainLoop
//包含本工程的其他文件-----------------------------------
.include"MCUinit.s"//芯片初始化
.include"SCI.s"//串行通信
.include"KB.s"//键盘子程序
.include"EnDisInt.s"//允许/禁止MCU各模块中断
//包含中断处理子程序与中断向量表文件"Vectors08.s"--------
//注意:
这个包含语句的存放位置必须放在最后
.include"Vectors08.s"//中断处理子程序与中断向量表
(2)键盘中断处理程序
//[Vectors08.s]中断处理子程序与中断向量表---------------*
//功能:
*
//
(1)定义中断处理子程序*
//
(2)放置中断向量表*
//本文件包含:
*
//
(1)键盘中断处理函数*
//
(2)未定义的中断处理函数*
//说明:
该文件与芯片具体型号有关*
//
(1)芯片型号MC68HC908GP32*
//
(2)注意本文件内容的顺序不能变动*
//------------------------------------------------------*
//isrKeyBoard:
键盘中断处理程序--------------------------*
//功能:
识别按键并发送键值,把键值转换成对应的定义值,再从*
//串口发送出去*
//调用子程序:
*
//
(1)扫描法读取键值子程序(KBScan)*
//
(2)键值转为定义值子程序(KBDef)*
//------------------------------------------------------*
isrKeyBoard:
:
SEI//关总中断
PSHH//[H进栈](保护寄存器H)
BSET#1,INTKBSCR//禁止键盘中断
JSRKBScan//扫描键盘,读取键值->A
JSRSCISend1//发送键值
JSRKBDef//转成相应的定义值->A
JSRSCISend1//发送定义值
JSRKBInit//键盘初始化
BCLR#1,INTKBSCR//开放键盘中断(IMASKK=0)
PULH//[H出栈](恢复寄存器H)
CLI//开总中断
RTI
//未定义的中断处理子程序,本子程序不能删除
isrDummy:
:
RTI
//中断矢量表,用户若需开放某中断,可修改下表中的相应项目
//(interruptserviceroutine,isr中断处理程序)
.areamemory(abs)
.org0xffdc//中断向量表起始地址(注意:
与芯片型号有关)
vectab:
:
//…………省略其他未使用的中断向量定义
.wordisrKeyBoard//键盘中断
//…………省略其他未使用的中断向量定义
(3)键盘中断编程的PC机方程序
利用串口调试工具,接收按键后的键值,通过它可以清楚地知道定义值与键值的对应关系,若显示不对,可以修改键值转为定义值子程序中的键值表。
8.308C语言键盘中断模块编程实例
本节给出与汇编程序相对应的08C语言程序,键盘中断08C工程文件组织如表8-2所示。
表8-2
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 整理 键盘