E F 1 1 1 1 1 1 1 0 0 0 0 0 1 1 79 71 86 8E 五.编程提示
1.利用构件式方法编程,可以使程序结构清晰,可移植性好;
2.矩阵式键盘采用扫描法来确定哪一个键被按下,键盘的接口硬件确定后,每个键的键值就确定了,但每个键的键码可以根据需要定义;
3.PTD7,3,2及PTG4-PTG0与键盘中断输入引脚复用,设置键盘中断允许寄存器,当键盘有键被按下时,立即产生中断,中断程序处理按键事件,比如确定哪个键被按下,然后转换为该键的定义值。
4.键盘的键面标示码(键码)键盘扫描的键值对应关系通过列表对应起来,即键盘定义表对应表示。当通过“行扫描”法获得某个键的键值时,通过查表法就可以得到它的定义值。
六.实验报告要求
1.按实验报告格式认真完成实验报告,要求画出工程的总体流程图;
2.本实验中用的是键盘中断编程方式,也可以使用查询编程方式,请尽量少修改代码改用查询编程方式重新编写相应的子程序和主程序。提示:注意重键问题。
2.识别是否有键按下以及哪个键被按下有哪些方法? 3.有哪些方法可以用来消除键盘抖动?
4.AW60的键盘中断模块用行扫描方式最多能够实现几列的键盘?
七.参考例程:
void main(void) {
//1 关总中断
DisableInterrupts; //2 芯片初始化 MCUInit();
//3 模块初始化 //3.1 SCI初始化
SCI1Init(SYSTEM_CLOCK,9600); //用SCI1,系统时钟为时钟源,波特率为9600 //3.2 键盘初始化 KBInit(); //4 开中断
//4.1 开键盘中断 KBI1SC |=(1<<1); //4.2 开总中断
EnableInterrupts;
//5 主循环
while (1) { } }
键盘模块初始化 void KBInit(void) {
PTDD &= 0b01110011; //键盘口复位 PTGD &= 0b11100000; PTDDD &= 0b01110011; //定义列线(7-4位)为输入 PTGDD &= 0b11101111; PTDPE |= 0b10001100; //输入引脚(列线)有内部上拉电阻 PTGPE |= 0b00010000;
PTGDD |= 0b00001111; //行线(3-0位)为输出
KBI1SC &=~(1<<1); //屏蔽键盘中断(KBIE = 0) KBI1PE = (0
|KBI1PE_KBIPE7_MASK |KBI1PE_KBIPE6_MASK |KBI1PE_KBIPE5_MASK
|KBI1PE_KBIPE4_MASK); //允许输入引脚(列线)的中断可进入 KBI1SC = (0
|KBI1SC_KBACK_MASK); //清除键盘中断请求(KBACK = 1) }
键盘一次扫描
uint8 KBScan1(void) {
uint8 line,i,tmp,tmp1,tmp2; line=0b11111110; //使第一根行线为0(低电平) for (i = 1; i <= 4; i++) //最多将扫描4根行线 {
//当前扫描的一行,输出低电平 PTGD = line; //输出开始扫描 asm(\ asm(\
//读取键盘口数据寄存器 tmp1 = PTDD; //输入扫描结果 tmp2 = PTGD;
//整合扫描结果,即键盘输入引脚的4位 tmp = (tmp1 & 0x80); tmp1 &= 0x0C; tmp1 = (tmp1<<3); tmp |= tmp1;
tmp |= (tmp2 & 0x1f);
//通过观察4根列线中是否出现低电平来判断当前行有无按键 if ((tmp & 0xF0) != 0xF0) //当前行有键按下 {
break; //退出循环不再扫描
}
else //当前行无按键,准备扫描下一行 line = (line << 1) | 0x01; }
if (i == 5) //无按键,以后将返回0xFF tmp = 0xFF; return (tmp); }
键盘进行N次扫描(去抖)
uint8 KBScanN(uint8 KB_count) {
uint8 i, KB_value_last, KB_value_now; //先扫描一次得到的键值,便于下面比较 if (0 == KB_count || 1 == KB_count) return KBScan1();
KB_value_now = KB_value_last = KBScan1(); //以下多次扫描消除误差 for (i=0; i KB_value_now = KBScan1(); if (KB_value_now == KB_value_last) return KB_value_now; //返回扫描的键值 else KB_value_last = KB_value_now; } //返回出错标志 return 0xFF; } 键码表: const uint8 KBtable[] = { //自已添入键值键码表 0x00 //键码表结束标志 }; 键码转换 uint8 KBDef(uint8 valve) { uint8 KeyPress; //键定义值 uint8 i; i = 0; KeyPress = 0xff; while (KBtable[i] != 0x00) //在键盘定义表中搜索欲转换的键值,直至表尾 { if(KBtable[i] == valve) //在表中找到相应的键值 { KeyPress = KBtable[i+1]; //取出对应的键定义值 break; } i += 2; //指向下一个键值,继续判断 } return KeyPress; } 键盘中断程序(自行设计) interrupt 22 void isrKeyBoard(void) { uint8 value; uint16 i; for(i=0; i<1000; i++); DisableInterrupts; //关总中断 KBI1SC &=~(1<<1); //屏蔽键盘中断 value = KBScanN(10); //扫描键值,存于value中 SCI1Send1(value); //发送键值 SCI1Send1(KBDef(value)); //键值转化为定义值并发送 KBInit(); //键盘初始化键盘中断 KBI1SC |=(1<<1); //开放键盘中断 EnableInterrupts ; //开总中断 } LED显示: void main(void) { LEDBUF[0]='2'; LEDBUF[1]='0'; LEDBUF[2]='1'; LEDBUF[3]='1'; DisableInterrupts; MCUInit(); LEDinit(); EnableInterrupts; while(1){ LEDshow(LEDBUF); } } LED.C中包含三个函数及段码表和位码表: void LEDinit(void) { PTBDD = 0xFF; //数据口为输出 PTDDD |= 0x33; //位选口为输出 } void LEDshow(uint8 *Buf) { uint8 i,c; //uint16 j; for (i = 0;i <= 3;i++) { c = Buf[i]-'0'; LEDshow1(3-i,c); //延时 Delay(10); } } void LEDshow1(uint8 i, uint8 c) { PTDD = CStable[i]; PTBD = Dtable[c]; } //显示码表 (共阴极) const uint8 Dtable[10] = // 0 1 2 3 4 5 6 7 8 9 {0x3F,0x06,0x5B,0x4F,0x66, 0x6D,0x7D,0x07,0x7F,0x6F}; //片选表 (电平为低片选) const uint8 CStable[4] = // 0 1 2 3 {0xDF,0xEF,0xFD,0xFE}; 公共函数中包含一个延时程序: void Delay(uint16 count) { uint8 i ; uint16 j; for(j=0; j