【STM32 基础实验矩阵按键】

一、元器件矩阵键盘说明

本次实验采用4*4矩阵键盘进行应用,矩阵键盘为了节约引脚的占用,提供了多行多列的排列组合为矩形的按键,所以为矩阵按键或矩阵键盘。如图所示:
矩阵键盘

二、基于stm32f10c8t6 基础实验矩阵按键

(1)实验功能实现说明

本实验通过stm32和矩阵按键实现点亮LED,以二进制的方式显示。如二进制的0000,对应四颗LED都熄灭;二进制的0001,对应第四颗LED点亮,其余三颗熄灭,以此类推;即1亮0灭。0.96寸OLED显示反馈的键值(以两个单位),如key1—01,key5----05,key11—11…;以按键响应对应的键值和二进制显示的LED。矩阵按键实现方法:1.响应对应中断的方法。2.行列扫描的方法。本实验主要是采用第二种方法,更容易理解。

(2)矩阵键盘原理

原理图

在这里插入图片描述

行列扫描法:
矩阵按键扫描方式理解图如下:
矩阵按键
解释说明:左边的填充以横向理解,右边的填充以竖向理解。
首先可以看到0x00ff,表示行列的按键均未接触,0x00fe 竖向1110表示第一行接触,那么等待第一行的第几列进行下一步接触,当第一行的第一列同时响应接触,那么表示第一行第一列对应的LED以二进制0001的方式进行显示,即点亮第四颗灯。
0x00fd 竖向1101表示第二行接触,那么等待第二行的第几列进行下一步接触,当第二行的第三列同时响应接触,那么表示第二行第三列对应的LED以二进制1101的方式进行显示,即点亮第一、二、四颗灯。
0x00fb 竖向1011表示第三行接触,那么等待第三行的第几列进行下一步接触,当第三行的第一、三列同时响应接触,那么表示第三行第一、三列对应的LED以二进制0101的方式进行显示,即点亮第二、四颗灯。
第四行同理可得。

(3)代码部分

keys.c


#include "stm32f10x.h"
#include "keys.h"
#include "delay.h"
//	 

//********************************************************************************
u8 FLAG = 0;

void KEY_4x4_Init(void) //IO初始化
{
 	GPIO_InitTypeDef GPIO_InitStructure;
	
 	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	GPIO_InitStructure.GPIO_Pin  = KEY_HANG;  //行  0123
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  GPIO_Init(KEY_PROT, &GPIO_InitStructure);
	GPIO_SetBits(KEY_PROT,KEY_HANG);
	
	//init GPIOA	  上拉输入
	GPIO_InitStructure.GPIO_Pin  = KEY1|KEY2|KEY3|KEY4;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; 
	GPIO_Init(KEY_PROT, &GPIO_InitStructure);
	GPIO_SetBits(KEY_PROT,KEY1|KEY2|KEY3|KEY4);
		 

}


void KEY_Scan(u8 *key) 
{	 
	
	GPIO_Write(KEY_PROT,0x00fe);//第一行
	if((KEY1_Input==RESET)||(KEY2_Input==RESET)||(KEY3_Input==RESET)||(KEY4_Input==RESET))   
	{
		delay_ms(10);//去抖动 
		
		if(KEY1_Input==RESET)
		{
				FLAG = 1;
				*key = 1;
				while(!GPIO_ReadInputDataBit(KEY_PROT,KEY1));
		}
		else if(KEY2_Input==RESET)
		{
	 	 
	     	FLAG = 1;
				*key = 2;
				while(!GPIO_ReadInputDataBit(KEY_PROT,KEY2));
		}
		else if(KEY3_Input==RESET)
		{
	 
	    	FLAG = 1;
				*key = 3;
				while(!GPIO_ReadInputDataBit(KEY_PROT,KEY3));
		}
		else if(KEY4_Input==RESET)
		{
	 
	    	FLAG = 1;
				*key = 4;
				while(!GPIO_ReadInputDataBit(KEY_PROT,KEY4));
		}else 
					{
						FLAG = 0;
						GPIO_Write(KEY_PROT,0x00ff);
					}
		}
	GPIO_Write(KEY_PROT,0x00fd);//第二行
	if((KEY1_Input==RESET)||(KEY2_Input==RESET)||(KEY3_Input==RESET)||(KEY4_Input==RESET))
	{
		delay_ms(10);//去抖动 
		
		if(KEY1_Input==RESET)
		{
				FLAG = 1;
				*key = 5;
				while(!GPIO_ReadInputDataBit(KEY_PROT,KEY1));
		}
		else if(KEY2_Input==RESET)
		{
	 	 
	     	FLAG = 1;
				*key = 6;
				while(!GPIO_ReadInputDataBit(KEY_PROT,KEY2));
		}
		else if(KEY3_Input==RESET)
		{
	 
	    	FLAG = 1;
				*key = 7;
				while(!GPIO_ReadInputDataBit(KEY_PROT,KEY3));
		}
		else if(KEY4_Input==RESET)
		{
	 
	    	FLAG = 1;
				*key = 8;
				while(!GPIO_ReadInputDataBit(KEY_PROT,KEY4));
		}else 
					{
						FLAG = 0;
						GPIO_Write(KEY_PROT,0x00ff);
					}
		}
	GPIO_Write(KEY_PROT,0x00fb);//第三行
	if((KEY1_Input==RESET)||(KEY2_Input==RESET)||(KEY3_Input==RESET)||(KEY4_Input==RESET))
	{
		delay_ms(10);//去抖动 
		
		if(KEY1_Input==RESET)
		{
				FLAG = 1;
				*key = 9;
				while(!GPIO_ReadInputDataBit(KEY_PROT,KEY1));
		}
		else if(KEY2_Input==RESET)
		{
	 	 
	     	FLAG = 1;
				*key = 10;
				while(!GPIO_ReadInputDataBit(KEY_PROT,KEY2));
		}
		else if(KEY3_Input==RESET)
		{
	 
	    	FLAG = 1;
				*key = 11;
				while(!GPIO_ReadInputDataBit(KEY_PROT,KEY3));
		}
		else if(KEY4_Input==RESET)
		{
	 
	    	FLAG = 1;
				*key = 12;
				while(!GPIO_ReadInputDataBit(KEY_PROT,KEY4));
		}else 
					{
						FLAG = 0;
						GPIO_Write(KEY_PROT,0x00ff);
					}
		}
		GPIO_Write(KEY_PROT,0x00f7);//第四行
	if((KEY1_Input==RESET)||(KEY2_Input==RESET)||(KEY3_Input==RESET)||(KEY4_Input==RESET))
	{
		delay_ms(10);//去抖动 
		
		if(KEY1_Input==RESET)
		{
				FLAG = 1;
				*key = 13;
				while(!GPIO_ReadInputDataBit(KEY_PROT,KEY1));
		}
		else if(KEY2_Input==RESET)
		{
	 	 
	     	FLAG = 1;
				*key = 14;
				while(!GPIO_ReadInputDataBit(KEY_PROT,KEY2));
		}
		else if(KEY3_Input==RESET)
		{
	 
	    	FLAG = 1;
				*key = 15;
				while(!GPIO_ReadInputDataBit(KEY_PROT,KEY3));
		}
		else if(KEY4_Input==RESET)
		{
	 
	    	FLAG = 1;
				*key = 16;
				while(!GPIO_ReadInputDataBit(KEY_PROT,KEY4));
		}else 
					{
						FLAG = 0;
						GPIO_Write(KEY_PROT,0x00ff);
					}
		}
	
}




keys.h

#ifndef __KEYS_H
#define __KEYS_H	 
//	 

//********************************************************************************
//V1.1修改说明
//修改按键扫描函数,使整个代码可以支持SWD下载。
//	 
#include "stm32f10x.h"

#define KEY_HANG 0x000f   //0123
#define KEY1 GPIO_Pin_4   
#define KEY2 GPIO_Pin_5	   
#define KEY3 GPIO_Pin_6	 
#define KEY4 GPIO_Pin_7   

#define KEY1_Input GPIO_ReadInputDataBit(KEY_PROT,KEY1)
#define KEY2_Input GPIO_ReadInputDataBit(KEY_PROT,KEY2)
#define KEY3_Input GPIO_ReadInputDataBit(KEY_PROT,KEY3)
#define KEY4_Input GPIO_ReadInputDataBit(KEY_PROT,KEY4)

#define KEY_PROT GPIOA

extern u8 FLAG;

void KEY_4x4_Init(void);//IO初始化
//u8 KEY_Scan(void);
void KEY_Scan(u8 *key);  //按键扫描函数		

#endif

main.c

#include "stm32f10x.h"
#include "led.h"
#include "delay.h"
#include "sys.h"
#include "keys.h"
//#include "usart.h"
#include "OLED.h"




/*接线说明
PA0~PA3-------R4~R1   //行
PA4~PA7-------C4~C1   //列
*/

 u8 key = 0;
 u8 i;
 int main(void)
 {
	
		LED_Init(); 	
		delay_init();
		KEY_4x4_Init();
		//uart_init(115200);
		OLED_Init();
		/*OLED初始化界面*/
		OLED_ShowChar(1, 1, 'A');
		OLED_ShowString(1, 3, "HelloWorld!");
		OLED_ShowNum(2, 1, 12345, 5);
		OLED_ShowSignedNum(2, 7, -66, 2);
		OLED_ShowHexNum(3, 1, 0xAA55, 4);
		OLED_ShowBinNum(4, 1, 0xAA55, 16);
	 
		while(1)
		{   
			
			KEY_Scan(&key);   //获取键值key
			
			if(FLAG == 1)    //按键按下
			{
				FLAG = 0;
				OLED_Clear();
				OLED_ShowNum(2, 1, key, 2);   //显示键值key
				//Printf("KEY = %d\r\n",key);
				if(key==1)  //0001
				{
					GPIO_SetBits(GPIOB,GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_14);
					GPIO_ResetBits(GPIOB,GPIO_Pin_15);	
				}				
				if(key==2)  //0010
				{
					GPIO_SetBits(GPIOB,GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_15);
					GPIO_ResetBits(GPIOB,GPIO_Pin_14);	
				}								
				if(key==3)  //0011
				{
					GPIO_SetBits(GPIOB,GPIO_Pin_12|GPIO_Pin_13);
					GPIO_ResetBits(GPIOB,GPIO_Pin_14|GPIO_Pin_15);	
				}				
				if(key==4)  //0100
				{
					GPIO_SetBits(GPIOB,GPIO_Pin_12|GPIO_Pin_14|GPIO_Pin_15);
					GPIO_ResetBits(GPIOB,GPIO_Pin_13);	
				}		
				if(key==5)  //0101
				{
					GPIO_SetBits(GPIOB,GPIO_Pin_12|GPIO_Pin_14);
					GPIO_ResetBits(GPIOB,GPIO_Pin_13|GPIO_Pin_15);	
				}				
				if(key==6)  //0110
				{
					GPIO_SetBits(GPIOB,GPIO_Pin_12|GPIO_Pin_15);
					GPIO_ResetBits(GPIOB,GPIO_Pin_13|GPIO_Pin_14);	
				}		 
				if(key==7)  //0111
				{
					GPIO_SetBits(GPIOB,GPIO_Pin_12);
					GPIO_ResetBits(GPIOB,GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15);	
				}				
				if(key==8)  //1000
				{
					GPIO_SetBits(GPIOB,GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15);
					GPIO_ResetBits(GPIOB,GPIO_Pin_12);	
				}		
				if(key==9)  //1001
				{
					GPIO_SetBits(GPIOB,GPIO_Pin_13|GPIO_Pin_14);
					GPIO_ResetBits(GPIOB,GPIO_Pin_12|GPIO_Pin_15);	
				}				
				if(key==10)  //1010
				{
					GPIO_SetBits(GPIOB,GPIO_Pin_13|GPIO_Pin_15);
					GPIO_ResetBits(GPIOB,GPIO_Pin_12|GPIO_Pin_14);	
				}		
				if(key==11) //1011
				{
					GPIO_SetBits(GPIOB,GPIO_Pin_13);
					GPIO_ResetBits(GPIOB,GPIO_Pin_12|GPIO_Pin_14|GPIO_Pin_15);	
				}				
				if(key==12)  //1100
				{
					GPIO_SetBits(GPIOB,GPIO_Pin_14|GPIO_Pin_15);
					GPIO_ResetBits(GPIOB,GPIO_Pin_12|GPIO_Pin_13);	
				}		
				if(key==13)  //1101
				{
					GPIO_SetBits(GPIOB,GPIO_Pin_14);
					GPIO_ResetBits(GPIOB,GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_15);	
				}				
				if(key==14)  //1110
				{
					GPIO_SetBits(GPIOB,GPIO_Pin_15);
					GPIO_ResetBits(GPIOB,GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_14);	
				}		
				if(key==15)  //1111
				{
					GPIO_ResetBits(GPIOB,GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15);	
				}				
				
				if(key==16)  //来回闪烁4次
				{
					for(i=0;i<4;i++)
					{
						GPIO_ResetBits(GPIOB,GPIO_Pin_12|GPIO_Pin_13);
						GPIO_SetBits(GPIOB,GPIO_Pin_14|GPIO_Pin_15);	
						delay_ms(1000);					
						GPIO_SetBits(GPIOB,GPIO_Pin_12|GPIO_Pin_13);
						GPIO_ResetBits(GPIOB,GPIO_Pin_14|GPIO_Pin_15);	
						delay_ms(1000);	
					}						
				}				
				//LCD12864_Write_Number(0x8d,key);
			
				}
			
		}
 }


(4)效果展示

矩阵按键实验效果:

矩阵按键

三、总结与扩展

总结:
根据以上内容,学习矩阵按键,跟轻触按键类似还是容易理解的,给输入信号给stm32以驱动LED相应点亮或熄灭。矩阵按键主要是应用需求多数按键解决引脚少的情况。
总结调试代码或硬件中,针对可能出现的问题,说明一下:
(1)出现按键响应慢的情况:因为矩阵按键模块的触发所用的为行列扫描,比中断触发响应的速度较慢;代码部分按键扫描延迟过高,或者去抖动(10ms~20ms)。
(2)出现按键硬件无响应的情况:可能是由于键盘模块引脚与stm32引脚接线错误或接反;也可能是对应引脚冲突占用,需要调用AFIO端口复用转换为普通I/O,也许即可解决;还可能是硬件坏了的问题,或者铜暴露出来导致的短路。
扩展: 可通过矩阵键盘模块可以做简易计算器、密码锁、功能键等实验。那么就分享到这,大胆尝试实践探索吧,欢迎讨论。

今日就分享到此了,要有信心一步步积累理论和实践经验,一起学习加油!

附上参考文献链接与视频链接出处

链接: 参考文献
链接: 参考视频
链接: 矩阵按键视频分享
链接: 源码例程
提取码:3232

  • 27
    点赞
  • 252
    收藏
    觉得还不错? 一键收藏
  • 13
    评论
"2017 电赛 滚球控制系统源代码(pixy ds3115舵机 stm32 矩阵按键 lcd12864).zip" 是一个包含源代码的压缩文件。该文件主要用于电赛中滚球控制系统的开发。在这个项目中,使用了一些特定的硬件设备,包括pixy ds3115舵机、stm32单片机、矩阵按键和lcd12864液晶屏。 根据文件名和硬件设备的记述,可以推测这个源代码项目的目的是控制一个滚球,使其按照特定的规则进行运动。pixy ds3115舵机可能用来检测滚球的位置和方向,并通过与stm32单片机的通信,控制舵机转动来改变滚球的运动路径。矩阵按键可能用来提供用户与系统的交互界面,比如调整滚球速度、选择不同的运动模式等等。lcd12864液晶屏则可能用于显示滚球的状态、系统参数等信息。 这个源代码项目的压缩文件中应该包含了相关的源代码文件,供开发者参考和使用。通过阅读源代码,开发者可以了解整个滚球控制系统的工作原理和实现方式。源代码可能包含对硬件设备的初始化和配置、算法逻辑实现、运动控制代码等。 如果您需要使用或了解这个源代码项目,可以解压缩压缩文件,并通过合适的开发工具打开源代码文件进行阅读和使用。为了更好地理解和运行源代码,建议您先了解相关的硬件设备和编程平台(如stm32)的基本知识。 总之,这个源代码项目是为了实现一个滚球控制系统而开发的,提供了相关的源代码文件供开发者使用。希望以上解释对您有所帮助。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值