【矩阵键盘】

        通俗来讲,按键的原理其实就是按下S,使得电路短路。比方说按下S7低四位的P30和高四位的P44连通,这样两端的电平则相同,我们可以根据这个来检测在键盘中到底是哪个键盘按下了。

(注意:矩阵键盘在J5中1,2连通才有作用,需要跳线帽连接)

        基本编程思路是:

        1.检测在哪一列:给低四位赋值0,检测高四位哪一位是0

        2.检测在哪一列:给高四位赋值0,检测低四位哪一位是0

        3.根据行和列的位置,确定是哪个按键按下

        (值得注意的是,在高四位的P4口中,可以直接对寄存器赋值,因为单片机中其他的外设没用到除了P42和P44口以外的口,所以检测的时候可以直接赋值P4=0xff或者0x00)

        根据这个思路,我们可以这样写:

//矩阵键盘 - 获取键值
u8 vKBD_KeyIO()
{
	u8 key_io = 0;
	P3=0xf0;P4=0xff;	//列扫描,低四位输出0,读取高四位的值
	if(P44==0) key_io=4;
	if(P42==0) key_io=8;
	if(P35==0) key_io=12;
	if(P34==0) key_io=16;

	P3=0x0f;P4=0x00;	//行扫描,高四位输出0,读取低四位的值
	if(P33==0) key_io=key_io + 0;
	if(P32==0) key_io=key_io + 1;
	if(P31==0) key_io=key_io + 2;
	if(P30==0) key_io=key_io + 3;
	
	return key_io;
}

        检测列的时候,给定义的变量key_io在不同列的情况下赋值基础值,如第一列是4,第二列是8等,是应为他们列的第一个键值就是这个,并没有其他的特殊含义。接着进行行检测时,每到哪一行我们就在key_io加多少,像第0行加0,低一行加1,完美实现了对key_io变量赋值键值。最后返回获取的键值key_io。

        在知道怎么获取的键值后,我们接下来要做的工作就是需要判断按键按下,长按和弹起这几种状态,这里有两个方法,就是之前文章提到的状态机法和三行按键法。

        1.状态机法

        首先我们需要宏定义三个变量,代表着是三个状态,无按键状态,按下状态和弹起状态

可以看到在Switch循环中,有三个if语句分别判断按键的状态,用来执行不同的语句。其中 key_state是一个静态变量,保存每次按键的状态。此外还需要用到key_io, key_return这两个变量分别来存取IO的状态和返回的键值。在确定好按键的按下和弹起后,返回键值key_return。需要注意的是这里的两个key_io都是局部变量,与上面的获取键值函数没有关系,在后面的语句中也能看到上面这个函数的键值key_io作为函数的返回值已经赋值给了下面这个函数的键值key_io。

#define KEY_NO   0  //无按键状态,用于判断是否按下
#define KEY_DOWN 1  //有按键按下状态,判断是否为抖动
#define KEY_UP   2  //等待松手状态,判断是否弹起
u8 vKBD_Read_State()
{
	static u8 key_state = 0; 		// 定义key_state为静态变量,用于保存每次按键的状态
	u8 key_io = 0, key_return = 0;  // key_io:读取的IO状态, key_return:返回的键值;
	
	key_io = vKBD_KeyIO();
	switch(key_state) 
	{ 	
		case KEY_NO:     								//无按键状态,用于判断是否按下
			if(key_io) key_state = KEY_DOWN; 
		break; 

		case KEY_DOWN:    								//有按键按下状态,判断是否为抖动
			if(key_io)
			{
				key_state = KEY_UP;
				key_return = key_io;
			} 
			else 
				key_state = KEY_NO;  
		break;  
		
		case KEY_UP: 									//等待松手状态,判断是否弹起
			if(key_io==0) key_state = KEY_NO; 
		break; 
	} 
	return key_return; 
}

        2.三行按键法

        这段代码和上面的状态机法实现效果一模一样,但是代码数量减少了很多,有利于比赛中的应用,但是内容可能有点抽象,便不再讲述。

unsigned char Trg_KBD; 
unsigned char Cont_KBD; 
void vKBD_Read_ThreeLine() 
{ 
    unsigned char ReadData = vKBD_KeyIO_ThreeLine() ^ 0xff;  
    Trg_KBD  = ReadData & (ReadData ^ Cont_KBD); 
    Cont_KBD = ReadData; 
} 

### 矩阵键盘的工作原理 矩阵键盘通过行列交叉的方式连接多个按键,形成一个二维数组结构。对于4×4的矩阵键盘而言,共有四条行线和四条列线,这使得仅需8根I/O口线即可控制多达16个按键的操作[^1]。 当检测到某个按键被按下时,对应的行线与列线之间会产生电平变化信号。具体来说,在扫描过程中,微控制器会逐次向各行发送低电平脉冲并读取各列的状态;如果某一行处于低电平时某一列为低,则说明该位置上的键已被按压。这种工作方式不仅减少了所需的硬件资源数量,还简化了电路设计复杂度。 一旦识别出特定按键的动作(即不考虑去抖处理的情况下),程序会在相应的事件发生之后执行预设功能——例如在此案例中是在数码管上显示出指定字符:“从左至右,从上到下”,依次显示0~F表示十六进制数中的每一位数值。 ```c // 假设定义了一个函数用于获取当前按下的键值 char getKey() { char key; // 行驱动循环 for (int row = 0; row < ROW_COUNT; ++row) { setRowLow(row); // 设置当前行为低电平 // 列状态读取 for (int col = 0; col < COL_COUNT; ++col) { if (!isColumnHigh(col)) { // 如果此列为低电平则认为有按键闭合 while(!isColumnHigh(col)); // 等待按键释放 // 计算对应按键编号并返回其代表的字符 int index = row * COL_COUNT + col; switch(index){ case 0 ... 9 : return '0' + index;break; default : return 'A' + index - 10;break; } } } resetAllRows(); // 所有行恢复高阻态或高电平 } } ``` 上述代码片段展示了如何实现简单的矩阵键盘扫描逻辑以及按键映射关系转换成所需输出的过程。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值