资源描述
9.2 汇编语言键盘中断模块编程实例
(2)键盘编程汇编语言子程序
下面给出有关键盘编程的汇编语言子程序。它们是:键盘中断初始化子程序、扫描法读取键值子程序、键值转为定义值子程序。即使不使用中断方式识别按键,三个子程序仍然需要使用。只不过键盘初始化子程序中改为不允许中断进入。扫描法读取键值与键值转为定义值两个子程序在键盘编程中通常需要使用的。
KBsub.ASM
*------------------------------------------------------*
*文件描述:包含3个键盘子程序,分别为: *
* (1)键盘初始化子程序(KB_Init) *
* (2)扫描读取键值子程序(KB_Scan) *
* (3)键值转为定义值子程序(KB_Def) *
*------------------------------------------------------*
*===================以下为子程序源代码=================*
KB_P EQU PTA ;键盘接在PTA口上
KB_D EQU DDRA ;相应的方向寄存器
KB_PUE EQU PTAPUE ;相应的上拉电阻允许寄存器
*KB_Init:键盘初始化子程序------------------------------*
*功能:初始化键盘中断的引脚,但未开放键盘中断 *
*入口:无 *
*出口:无 *
*堆栈深度:2 *
*------------------------------------------------------*
KB_Init:
PSHA ;保护A
LDA #$00 ;复位相应寄存器
STA KB_P
LDA #%00001111 ;定义7-4为输入,3-0为输出
STA KB_D
LDA #%11110000 ;定义输入引脚有内部上拉电阻
STA KB_PUE
BSET 1,INTKBSCR ;屏蔽键盘中断(IMASK=1)
LDA #%11110000 ;允许输入引脚的中断可进入
STA INTKBIER
BSET 2,INTKBSCR ;清除键盘中断请求(ACKK=1)
PULA ;恢复A
RTS
*KB_Scan:扫描读取键值子程序----------------------------*
*功能:扫描4*4键盘,读取键值->A,无按键,为$FF *
*入口:无 *
*出口:A=键值 *
*堆栈深度:2+2=4 *
*------------------------------------------------------*
KB_Scan:
AIS #-!2 ;开辟临时变量
LDA #%11111110 ;使第一根行线为0(低电平)
STA !1,SP
LDA #$04 ;将扫描4根行线
STA !2,SP
KB_Scan1:
LDA KB_P ;取KB_P->A
ORA #%00001111 ;KB_P.7-4保留,KB_P.3-0为1
AND $1,SP ;令KB_P.n=0,n=0、1、2、3
STA KB_P
NOP
NOP
LDA KB_P ;看第n行是否有键按下
AND #%11110000 ;KB_P.7-4保留,令低4位=0
CBEQA #$F0,KB_Scan2 ;本行无键按下,转KB_Scan2
LDA KB_P ;本行有键按下
BRA KB_Scan_Exit
KB_Scan2:
SEC ;C=1
ROL $1,SP ;使下一个行线为0
DBNZ !2,SP,KB_Scan1 ;对行线循环
LDA #$FF ;没有键被按下返回$FF
KB_Scan_Exit:
AIS #!2 ;释放临时变量
RTS
*KB_Def:键值转为定义值子程序---------------------------*
*功能:键值转为键盘定义值 *
*入口:A=键值 *
*出口:A=键定义值 *
*堆栈深度:2+3=5 *
*------------------------------------------------------*
KB_Def:
PSHH ;保护HX
PSHX
AIS #-!1 ;开辟临时变量
STA !1,SP ;把键值存入(!1,SP)
LDHX #KB_Table ;取键盘定义表首地址
KB_Def1:
LDA ,X
CMP #$00 ;与0(定义表结束标志)相比较
BEQ KB_Def3 ;=0,表示即表中无次定义值
CMP $1,SP ;与键值相比较
BNE KB_Def2 ;不等,未找到转KB_Def2
AIX #!1 ;找到
LDA ,X ;取键定义值-〉A
BRA KB_DefR
KB_Def2:
AIX #!2 ;指向下一个键值
BRA KB_Def1 ;继续判断
KB_Def3:
LDA #$FF ;无此定义,用FF标志
KB_DefR:
AIS #!1 ;释放临时变量
PULX ;恢复HX
PULH
RTS
;键盘定义表
KB_Table FCB $EE,"1",$DE,"2",$BE,"3",$7E,"A"
FCB $ED,"4",$DD,"5",$BD,"6",$7D,"B"
FCB $EB,"7",$DB,"8",$BB,"9",$7B,"C"
FCB $E7,"*",$D7,"0",$B7,"#",$77,"D"
FCB $00
9.2.2 键盘中断编程举例
下面给出的实例程序的功能是,当按下键盘上任何一个键,产生键盘中断,在键盘中断程序中,通过串行口发送“键值”及“键定义值”。PC机方程序,接收它们,并显示。
(1)键盘中断编程汇编主程序
实例编号:A03 路径:\ASM\ A03_键盘实验 (Keyboard.asm)
*----------------------------键盘实验---------------------------*
*文 件 名:Keyboard.asm *
*硬件连接:PTA.7-4接键盘4根列线,PTA.3-0接键盘4根行线 *
*程序描述:按下键盘按键,串口发送对应的键值 *
*目 的:键盘扫描,键盘中断,键值识别,键盘编码 *
*注 意:如果键盘插在实验板的上排插孔,无须连线,若插在下排 *
* 插孔,需手工接线 *
*---------《嵌入式应用技术基础教程》教学实例-----------*
*[头文件]
$include "GP32ASM.H"
*[两个起始地址]
RAMstartAddr equ $0040 ;RAM的起始地址
FlashStartAddr equ $8000 ;程序开始地址
*=======================================================
*[主程序]
org FlashStartAddr ;程序起始地址
MainInit: ;复位后程序从此开始执行
;[系统初始化]
SEI ;关中断
LDHX #$023F
TXS
JSR GP32Init ;调系统初始化子程序GP32Init
JSR SCIInit ;调串行口初始化子程序SCIInit
JSR KB_Init ;调键盘初始化子程序
BCLR 1,INTKBSCR ;开放键盘中断(IMASK=0)
CLI ;开中断
;[程序总循环入口,无中断时空操作]
MainLoop:
NOP
NOP
BRA MainLoop
*==================以下为子程序存放处============================
*KB_Int:键盘中断处理程序-------------------------------*
*功能:键盘中断程序,把键定义值从串口发送出去 *
*调用子程序:(1)扫描法读取键值子程序(KB_Scan) *
* (2)键值转为定义值子程序(KB_Def) *
*------------------------------------------------------*
KB_Int:
SEI ;关总中断
PSHH ;保护H
BSET 1,INTKBSCR ;禁止键盘中断
JSR KB_Scan ;扫描键盘,读取键值->A
JSR SCISend1 ;发送键值
JSR KB_Def ;转成键定义值->A
JSR SCISend1 ;发送键定义值
JSR KB_Init
BCLR 1,INTKBSCR ;开放键盘中断(IMASKK=0)
PULH ;恢复H
CLI ;开总中断
RTI
*[外部子程序存放处]
$include "GP32init.asm"
$include "SCIInit.asm"
$include "H08SCI.asm"
$include "KBsub.asm"
*[中断向量]
ORG $FFE0 ;键盘中断矢量
DW KB_Int
ORG $FFFE ;复位矢量
DW MainInit
(2)键盘中断编程的PC机方的VB界面与程序
图9-4 键盘中断编程的PC机方的VB界面
图9-4为针对上述MCU程序的PC机方的VB界面。通过它可以清楚地知道定义值与键值的对应关系,若显示不对,可以修改键值转为定义值子程序中的键值表。
实例编号:A03 路径:\ASM\A03_键盘实验\VB_KB
'程序描述:把接收到的数据显示在接收窗口中
'-------------------------------------------------------
Option Explicit '检查未经声明的变量
Dim RecvData() As Byte '接收数据数组
Private Sub Form_Load()
'清空有关文本框
Txthex.Text = ""
Txtchr.Text = ""
'串行口初始化
Call SCIinit(MSComm1, 1, "9600,N,8,1")
'开放串行中断
MSComm1.RThreshold = 1
End Sub
Public Sub MSComm1_OnComm() '串行接收中断
Dim i As Integer
Dim S1 As String, S2 As String
MSComm1.RThreshold = 0 '关闭串行中断
RecvData = MSComm1.Input
S1 = Hex(RecvData(0))
S2 = Chr(RecvData(1))
Txthex.Text = S2
Txtchr.Text = S1
MSComm1.RThreshold = 1 '开放串行中断
End Sub
Private Sub CmdCLR_Click() '单击"清空"按钮
Txthex.Text = ""
Txtchr.Text = ""
End Sub
Private Sub CmdEXIT_Click() '单击"退出"按钮
If MSComm1.PortOpen = True Then MSComm1.PortOpen = False
End
End Sub
Private Sub CmdEXIT_Click() '单击"退出"按钮
If MSComm1.PortOpen = True Then MSComm1.PortOpen = False
End
End Sub
9.3 08C语言键盘中断模块编程实例
本节给出与汇编程序相对应的08C语言程序。PC机部分的VB程序相同。
9.3.1 按键识别与键盘定义函数
H08KB.C
/*-----------------------------------------------------*
*文件描述:本文件包含了H08C键盘中断子函数,分别为: *
*(1)KB_Init:键盘初始化函数 *
* void KB_Init(void) *
*(2)KB_Scan:扫描读取键值函数 *
* unsigned char KB_Scan(void) *
*(3)KB_Def:键值转为定义值函数 *
* unsigned char KB_Def(unsigned char KB_valve) *
*-----------------------------------------------------*/
/*[以下为子程序源代码]*/
/*[头文件]*/
#include "GP32C.H"
#include "KB.h"
/*KB_Init:键盘初始化函数-------------------------------*
*功 能:初始化键盘中断的引脚,但未开放键盘中断 *
*参 数:无 *
*返 回:无 *
*-----------------------------------------------------*/
void KB_Init(void)
{
KB_P=0x00; //复位KB_P
KB_D=0b00001111; //定定义7-4为输入,3-0为输出
KB_PUE=0b11110000; //定义输入引脚有内部上拉电阻
INTKBSCR|= (1<<IntBit);//屏蔽键盘中断(IMASKk=1)
INTKBIER=0b11110000; //允许输入引脚的中断可进入
INTKBSCR|= (1<<ACKKBit); //清键盘中断请求(ACKK=1)
}
/*KB_Scan:扫描读取键值函数-----------------------------*
*功 能:扫描一次4*4键盘上的按键,读取键值->*p ,若无按键, *
* *p为0xff *
*参 数:无 *
*返 回:扫描到的键值 *
*-----------------------------------------------------*/
unsigned char KB_Scan(void)
{
unsigned char line,i,tmp;
line=0b11111110; //使第一根行线为0(低电平)
for(i=1;i<=4;i++) //将扫描4根行线
{
tmp=KB_P; //取KB_P->tmp
tmp|=0b00001111; //KB_P.7-4保留,KB_P.3-0为1
KB_P=tmp&line; //令KB_P.n=0,n=0、1、2、3
asm("NOP"); //等待,消除按键抖动
asm("NOP");
tmp=KB_P;
tmp&=0b11110000; //看第n行是否有键按下
if(tmp!=0xf0) //本行有键按下
{
tmp=KB_P;
break;
}
else //本行无键按下,扫描下一行
line=(line<<1)|0x01;
}
if(i==5) tmp=0xff;
return(tmp);
}
/*KB_Def:键值转为定义值函数----------------------------*
*功 能:键值转为定义值 *
*参 数:键值 *
*返 回:键定义值 *
*-----------------------------------------------------*/
//键盘定义表
const unsigned char KB_Table[]=
{0xEE,'1',0xDE,'2',0xBE,'3',0x7E,'A',
0xED,'4',0xDD,'5',0xBD,'6',0x7D,'B',
0xEB,'7',0xDB,'8',0xBB,'9',0x7B,'C',
0xE7,'*',0xD7,'0',0xB7,'#',0x77,'D',
0x00};
unsigned char KB_Def(unsigned char KB_valve)
{
unsigned char KeyPress;
unsigned char i;
unsigned char j;
i=0;
while(1)
{
j=KB_Table[i];
//与0(定义表结束标志)相比较
if (j==0) //=0,即表中无次定义值
{KeyPress=0xff; break;} //返回0xff
else
//与键值相比较
if (j==KB_valve) //找到
{KeyPress=KB_Table[i+1];break;} //取键定义值
else
i+=2; //指向下一个键值,继续判断
};
return KeyPress;
}
9.3.2 键盘中断编程08C语言举例
(1)键盘中断编程实例的08C主函数
实例编号:C03 路径:\C\ C03_C03_键盘实验
/*-------------------键盘实验--------------------------*
*工 程 名:Keyboard.prj *
*硬件连接:PTA.7-4接键盘4根列线,PTA.3-0接键盘4根行线 *
*程序描述:按下键盘按键,串口发送对应的键值 *
*目 的:键盘扫描,键盘中断,键值识别,键盘编码 *
*注 意:如果键盘插在实验板上排插孔,无须连线,若插在下 *
* 排插孔,需手工接线 *
*-------《嵌入式应用技术基础教程》教学实例------------*/
/*[头文件]*/
#include "GP32C.H"
#include "KB.h" //键盘中断头文件
/*[主程序]*/
void main()
{
asm("SEI"); //关总中断
KB_Init();
INTKBSCR&= ~(1<<IntBit); //打开键盘中断(IMASKk=1)
asm("CLI"); //开总中断
//无中断时空操作
while(1);
}
(2)键盘中断编程实例的08C中断矢量表文件
vectors08.c
/*-----------------------------------------------------*
*文件名:vectors08.c *
*功 能:用于定义中断矢量表 *
*-----------------------------------------------------*/
/*[头文件]*/
#include "GP32C.H"
#include "KB.h"
#include "SCI.h"
/*键盘中断处理函数------------------------------------*/
#pragma interrupt_handler isrKBI
void isrKBI(void)
{
unsigned char KB_valve;
asm("SEI"); //关总中断
INTKBSCR|= (1<<IntBit); //屏蔽键盘中断(IMASKK=1)
KB_valve=KB_Scan(); //扫描键值
SCISend1(KB_valve);
KB_valve=KB_Def(KB_valve); //键值转化为定义值
SCISend1(KB_valve);
KB_Init(); //重新初始化键盘
INTKBSCR&= ~(1<<IntBit); //打开键盘中断(IMASKK=0)
asm("CLI"); //开总中断
}
//未定义的中断处理函数,本函数不能删除
#pragma interrupt_handler isrDummy
void isrDummy(void)
{
}
//中断矢量表,需定义中断函数,可修改下表中的相应项目
#pragma abs_address:0xffdc //中断向量表起始地址
void (* const _vectab[])(void) = {
isrDummy, //Timebase
isrDummy, //ADC
isrKBI, //KBI
isrDummy, //SCI TC/TE
isrDummy, //SCI RF/IDLE
isrDummy, //SCI PE/FE/NF/OR
isrDummy, //SPI TE
isrDummy, //SPI MOD/OVR/RF
isrDummy, //TIM2 OVR
isrDummy, //TIM2 channel 1
isrDummy, //TIM2 channel 0
isrDummy, //TIM1 OVR
isrDummy, //TIM1 channel 1
isrDummy, //TIM1 channel 0
isrDummy, //CGM
isrDummy, //IRQ
isrDummy //SWI
//RESET也是中断,定义在 crt08.o中
};
#pragma end_abs_address
展开阅读全文