STM32 基础实验:矩阵按键

文章目录

  • 一、元器件矩阵键盘说明
  • 二、基于stm32f10c8t6 基础实验矩阵按键
  • (1)实验功能实现说明
  • (2)矩阵键盘原理
  • (3)代码部分
  • (4)效果展示
  • 三、总结与扩展
  • 附上参考文献链接与视频链接出处
  • 一、元器件矩阵键盘说明

    本次实验采用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

    物联沃分享整理
    物联沃-IOTWORD物联网 » STM32 基础实验:矩阵按键

    发表评论