题:用任意一单片机设计一个4X4的键盘并编出程序得到键值,要求有去抖,去抖时单片机可以做其它事情,按一下键盘蜂鸣器叫一下,蜂鸣器叫过程中也要单片机可以做其它事情。(提示:用定时器产生基本节拍)
题目是我做后记下来的,当时在做得时候写的很乱,被老师评为编程不怎么样。回来后想想其实很简单就一个中断函数搞定:
void time1_sv() interrupt 5 using 2{ EA=0; TF2=0; //清中断标志位 if((spcnt--)==0){spcnt=0;SPEAK=0x00;} if(scankey()){count++; if(count>8){getkeyval();count=0;spcnt=30;SPEAK=0xff;} } else {count=0;} EA=1; }
思路是:连续n次进入中断时都检测到有按键,那就去取按键值,并使蜂鸣器叫,蜂鸣器叫多长时间由spcnt的值决定。
试验源程序:
#include "mydef.h" //定义外围器件地址 #define SPEAK XBYTE[0xC000] #define KEYIN XBYTE[0xE000] #define KEYOUT XBYTE[0xF000] #define PORTA XBYTE[0xa000] #define PORTB XBYTE[0xb000] #define LEDD XBYTE[0x9000] //3000个机器周期中断一次 #define TIME_H (65535-3000)/256 #define TIME_L (65535-3000)%256 //LED显示译码 uchar code table[]={0x0C0,0x0F9,0x0A4,0x0B0,0x99,0x92,0x82,0x0F8,0x80,0x90,0x88,0x83,0x0C6,0x0A1,0x86,0x8E,0x7F,0x89}; //全局变量 uchar key_value,count,spcnt; //判断有无按键 uchar scankey() { KEYOUT=0x00; if(((~KEYIN)&0x0f)!=0) return(1); //有键按下 else return(0); } //得到键值 void getkeyval(void) { KEYOUT=0x0e; switch(KEYIN&0x0f) { case 14:key_value=0;break; case 13:key_value=1;break; case 11:key_value=2;break; case 7:key_value=3;break; default:break; } KEYOUT=0x0d; switch(KEYIN&0x0f) { case 14:key_value=4;break; case 13:key_value=5;break; case 11:key_value=6;break; case 7:key_value=7;break; default:break; } KEYOUT=0x0b; switch(KEYIN&0x0f) { case 14:key_value=8;break; case 13:key_value=9;break; case 11:key_value=10;break; case 7:key_value=11;break; default:break; } KEYOUT=0x07; switch(KEYIN&0x0f) { case 14:key_value=12;break; case 13:key_value=13;break; case 11:key_value=14;break; case 7:key_value=15;break; default:break; } } //定时T2中断 89c52,w78e58之类的单片机都有定时器2 void time1_sv() interrupt 5 using 2{ EA=0; TF2=0; //清中断标志位 if((spcnt--)==0){spcnt=0;SPEAK=0x00;} if(scankey()){count++; if(count>8){getkeyval();count=0;spcnt=30;SPEAK=0xff;} } else {count=0;} EA=1; } //粗劣延时mS级 void msec(uint x) { unsigned int j; while((x--)!=0) { for(j=0;j<=123;j++) {;} } }
//数码管显示 void dir(uchar leddat) { ORTA=0x00; ORTB=0xff; LEDD=table[leddat]; msec(2); ORTA=0xff; LEDD=table[leddat]; ORTB=0x00; msec(2); ORTB=0xFF; }
//主函数 main() { C_T2=0; //T2工作在定时器 CP_RL2=0; //自动装栽 RCAP2H=TH2=TIME_H; RCAP2L=TL2=TIME_L; EA=1; ET2=1; TR2=1; while(1) { dir(key_value); } }
|