经典矩阵按键的扫描方法及个人编写的矩阵按键扫描

51单片机矩阵按键扫描

矩阵按键原理图
经典扫描方法:(存在一个弊端:当使用一个按键,按一次变量加1,真实情况是按一次,结果变量加了好多次。)

unsigned char Check_key(void)
{
	unsigned char row,col,temp1,temp2,keyvalue;
	temp1 = 0x01;
	for(row=0;row<4;row++)                // 行扫
	{
		P0 = 0xF0;                        // 先将P0.4~P0.7置高
		P0 = ~temp1;                      // 使P0.1~P0.3中有一位为0
		temp1 *= 2;                       // temp1左移一位
		if((P0 & 0xF0) < 0xF0)            // 当按键按下时,(P0 & 0xF0) 高四位不在是F,可能为7或B或D或E。
		{                                    // 这时可以确定按下的是(row+1)行
			temp2 = 0x80;
			for(col=0;col<4;col++)        // 列扫
			{
				if((P0 & temp2)==0x00)    // 当(P0 & temp2)等于0x00时,可以确定按下的位置是(col+1)列
				{
					keyvalue = row*4+col; // 得到所按下按键的键值
					return keyvalue;      // 把得到的键值作为返回值
				}
				temp2 /= 2;               // temp2右移一位
			}
		}
	}
	return 16;  // 因为定义数码管段选表中,16对应的是全灭,故无按键按下时返回16
}

我个人写了一个矩阵按键扫描,可以解决上面那个弊端,代码如下:

#define GPIO_KEY P0     // 重定义矩阵按键端口

/*************************************************
 * 函数名:delay_ms
 * 描述  :延时函数  (具体情况以自己的板子为准)
 * 参数  :xms  , xms是几延时几毫秒 。晶振:12MHz
 * 返回值:无
 * 调用  :内部调用
 *************************************************/
void delay_ms(unsigned int xms)
{
	unsigned int i, j;
	for(i=xms;i>0;i--)
	{
		for(j=921;j>0;j--);
	}
}
/*************************************************
 * 函数名:key_scan
 * 描述  :矩阵键盘的键值返回(在没有按任何键时,
 *         函数返回值为16,只有在按下按键的瞬间返
 *         回的键值才是你真正按下按键的键值,正是这样才能实现长按连续加或减)
 * 参数  :无
 * 返回值:键值
 * 调用  :外部调用
 *************************************************/
unsigned char key_scan()
{
	unsigned char keyvalue, a=0;
	GPIO_KEY = 0xf0;              // 高四位为1,低四位为0
	if(GPIO_KEY != 0xf0)
	{
		delay_ms(10);             // 延时消抖
		if(GPIO_KEY != 0xf0)
		{
			GPIO_KEY=0xf0;
			switch(GPIO_KEY)
			{
			case 0xe0: keyvalue = 3;break;     // 确定矩阵按键被按下的位置是第几列
			case 0xd0: keyvalue = 2;break;     // 0、1、2、3
			case 0xb0: keyvalue = 1;break;
			case 0x70: keyvalue = 0;break;
			}
			GPIO_KEY=0x0f;   
			     
			// 确定矩阵按键被按下位置的键值:列(或0或1或2或3) + 行(或0或4或8或12)
			
//			switch(GPIO_KEY)   // 经测试对于我使用的开发板,这条switch语句不能得到想要的结果
//			{
//			case 0x0e: keyvalue = keyvalue;break;    
//			case 0x0d: keyvalue = keyvalue+4;break;    
//			case 0x0b: keyvalue = keyvalue+8;break;
//			case 0x07: keyvalue = keyvalue+12;break;
//			}
            
            // 使用下面这种形式,则可以达到目的
			if((GPIO_KEY != 0x0d)||(GPIO_KEY != 0x0b)||(GPIO_KEY != 0x07))
			{
				keyvalue = keyvalue;
			}
			if(GPIO_KEY == 0x0d)
			{
				keyvalue = keyvalue+4;
			}
			if(GPIO_KEY == 0x0b)
			{
				keyvalue = keyvalue+8;
			}
			if(GPIO_KEY == 0x07)
			{
				keyvalue = keyvalue+12;
			}
			while((a<50)&&(GPIO_KEY!=0x0f))
			{
				delay_ms(10);
				a++;
			}
		}			
	}
	if(GPIO_KEY==0xF0)
	{
		keyvalue = 16;
	}
	return keyvalue;
}

行列扫描解析
行:
1
2
3
4
5
从上面五幅图片,我们得到:第一行(0x0E)、第二行(0x0D)、第三行(0x0B)、第四行(0x07)。因为每一行有四列,所以定义这四行的起点分别是:0、4、8、12(04、14、24、34)。
列:
1
2
3
4
5
从上面的五幅图片中,我们得到:第一列(0x70)、第二列(0xB0)、第三列(0xD0)、第四列(0xE0)。因为每一行有四列,所以定义这四列分别固定为:0、1、2、3。
【最后确定键值:列号(0/1/2/3)+行起点(0/4/8/12)】

0 — 1 — 2 — 3 (列扫0/1/2/3)+(行扫0)
4 — 5 — 6 — 7 (列扫0/1/2/3)+(行扫4)
8 — 9 – 10 – 11 (列扫0/1/2/3)+(行扫8)
12 - 13 - 14 - 15 (列扫0/1/2/3)+(行扫12)

矩阵键盘程序中的扫描原理:首先进行列扫描,确定按下的是第几列(即每一列固定的列号),接着进行行扫描,确定是第几行(即确定行起点)。

  • 6
    点赞
  • 36
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值