第三个任务,实现键盘扫描,并通过串口通讯显示被按下的键位。

在上一节,了解了矩阵键盘的大致工作原理,那么应该怎样去实现显示被按下的按钮的键位呢?通过行列扫描,即拉高某一行或者某一列的电平,然后去扫描全部列或者全部行。

例如将所有列对应的针脚设置为推挽输出,剩下的全部行设置为上拉输入,然后假设我们按下了图上所示的7号按钮。程序应该怎么检测这一事件呢?先检测每一列,因为当按钮被按下后,某一列的电平肯定会变为0,那么我们可以知道是哪一列有按钮被按下了,此时我们需要知道是这一列中的哪一行的按钮被按下。那么通过下面的扫描函数可以得到返回值“1011”即0x0B,也就是第二行被按下;

uint8_t key_row[1]={0xff};//给key_row赋初值
key_row[0] = GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_12)<<3;//第一行的结果左移3位
key_row[0] = key_row[0] | GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_13)<<2;//第二行的结果左移2位
key_row[0] = key_row[0] | GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_14)<<1;//第三行的结果左移1位
key_row[0] = key_row[0] | GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_15);

然后我们可以通过一个switch语句来判断扫描函数返回的数值所代表的是哪一行被按下,此时通过这个函数将返回3;

if(key_row[0]!=0x0f){//如果返回值不为1111
	delay_ms(10);//延迟10毫秒,消抖
	if(key_row[0]!=0x0f){//判断有按钮被按下
		switch(key_row[0]){
			case 0x07://返回0111,第一行被按下,返回1
				return 1;
			case 0x0b://返回1011,第二行被按下,返回2
				return 2;
			case 0x0d://返回1101,第三行被按下,返回3
				return 3;
			case 0x0e://返回1110,第四行被按下,返回4
				return 4;
			default://默认返回0
				return 0;
			}
	}else return 0;//没有被按下,只是机械抖动,返回0
}else return 0;//没有被按下,返回0

那么结合起来的思路就是,我们拉低每一列的电平,然后检查有没有哪一列的返回值不等于0,这是扫描列的思路;同理也可以通过扫描行来实现,具体代码如下:

有了上面的代码后,在main.c中添加引用,调用函数进行判断,并通过串口输出结果:

具体代码: