使用状态机进行矩阵键盘检测

写在前面

  这篇blog分享一下前段时间学到的用状态机完成矩阵键盘扫描的方法。是从别的前辈那里学来的方法,出处由于参考的帖子和网站太多,已经忘记是参照哪里的写出来的了,如有侵权,请直接留言给我。

用状态机的目的

  在学习单片机的过程中,不断看到有前辈告诫CPU的工作时间十分宝贵,用delay或者while的话,CPU就一直被耽误在某段循环里,无法处理其他语句,十分浪费CPU的资源。于是乎引入状态机来处理按键扫描。废话不多说,下面是程序:

#include <reg52.h>
typedef unsigned char uint8;
typedef unsigned int  uint16;

#define key P3
#define no_key 0xff
#define key_state0 0
#define key_state1 1
#define key_state2 2

code uint8 num[]={0xc0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0x8E};

uint8 key_value;
bit flag;

void delay(uchar k){
	uint8 i,j;
	for(i=k;i>0;i--)
		for(j=110;j>0;j--);
}

void scankey(){
	static char key_state;
	uint8 key_temp;
	uint8 key1,key2;
	
	key = 0xf0;
	key1 = key;				//高四位为行标志,有键按下则相应行的I/O口变为0
	key1 = key&0xf0; 		//清掉低四位只保留高四位,值保存在key1中
	key = 0x0f;
	key2 = key;				//低四位为行标志,有键按下则相应行的I/O口变为0
	key2 = key&0x0f; 		//清掉高四位只保留低四位,值保存在key2中	
	key_temp = key1|key2;	//无键按下则为0xff,有键按下的会有类似(1101 1011)的值
							//								   key1 key2
	switch(key_state){
		case key_state0:
			if(key_temp != no_key){
				key_state = key_state1;
			}
		break;
		case key_state1:
			if(key_temp == no_key){
				key_state = key_state0;
			}
			else{
				switch(key_temp){
					case 0xee: key_value = 0;break;
					case 0xed: key_value = 1;break;
					case 0xeb: key_value = 2;break;
					case 0xe7: key_value = 3;break;
					case 0xde: key_value = 4;break;
					case 0xdd: key_value = 5;break;
					case 0xdb: key_value = 6;break;
					case 0xd7: key_value = 7;break;
					case 0xbe: key_value = 8;break;
					case 0xbd: key_value = 9;break;
					case 0xbb: key_value = 10;break;
					case 0xb7: key_value = 11;break;
					case 0x7e: key_value = 12;break;
					case 0x7d: key_value = 13;break;
					case 0x7b: key_value = 14;break;
					case 0x77: key_value = 15;break;
				}
				key_state = key_state2;
			}
		break;
		case key_state2:
			if(key_temp == no_key){
				key_state = key_state0;
			}
		break;
	}
}

void init_timer(){
	EA   = 0;
	TR0  = 0;
	TMOD = 0x01;
	TH0  = 0XDC;
	TL0  = 0X00;
	
	ET0  = 1;
	EA   = 1;
	TR0  = 1;
}

void timer0() interrupt 1 using 0{		
	TH0  = 0XDC;						//10ms
	TL0  = 0X00;
	flag = 1;
}

void main(){
	init_timer();
	while(1){
		if(flag){
			flag = 0;
			scankey();
			P2 = num[key_value];
		}
	}
}

电路图如下:矩阵键盘电路图
  希望能这篇文章对初学单片机的小白能有所帮助,如果有大神看过之后觉得有不妥之处,希望能在评论区留下您的建议。工作任务重,就不多写其他废话了。

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值