精华内容
下载资源
问答
  • stm32矩阵按键

    2018-08-16 22:10:01
    自己改写的stm32矩阵按键程序,解决stm32系列单片机没有矩阵按键的问题
  • STM32矩阵按键控制
  • STM32矩阵按键原理介绍及程序

    千次阅读 2019-05-24 19:48:05
    STM32矩阵按键原理介绍及程序 第一次发描述不太好请见谅; 程序下载链接:链接:https://pan.baidu.com/s/11J66Pr0BQZPDidnUoB3lQQ 提取码:r3hs

    STM32矩阵按键原理介绍及程序

    在这里插入图片描述第一次发描述不太好请见谅;
    程序下载链接:链接:https://pan.baidu.com/s/11J66Pr0BQZPDidnUoB3lQQ
    提取码:r3hs

    展开全文
  • stm32矩阵按键程序.rar

    2020-06-16 13:19:05
    键盘扫描
  • 4*4矩阵按键,输出数字OLED显示。代码自己写的,实测可以用。
  • 矩形键盘程序(中断方式)
  • 矩阵按键原理 矩阵按键有两种扫描方式: 方法一: 逐行扫描:我们可以通过低四位轮流输出低电平来对矩阵键盘进行逐行扫描,当高四位接收到的数据不全为1的时候,说明有按键按下,然后通过接收到的数据是哪一位为0来...

    一 .矩阵按键原理
    矩阵按键有两种扫描方式:
    方法一:
    逐行扫描:我们可以通过低四位轮流输出低电平来对矩阵键盘进行逐行扫描,当高四位接收到的数据不全为1的时候,说明有按键按下,然后通过接收到的数据是哪一位为0来判断是哪一个按键被按下。
    方法二:
    行列扫描:我们可以通过高四位全部输出低电平,低四位输出高电平。当接收到的数据,低四位不全为高电平时,说明有按键按下,然后通过接收的数据值,判断是哪一列有按键按下,然后再反过来,高四位输出高电平,低四位输出低电平,然后根据接收到的高四位的值判断是那一行有按键按下,这样就能够确定是哪一个按键按下了。
    此次采用的是行扫描方式,与单片机连接如下:
    在这里插入图片描述
    二.完整程序
    最开始我使用的是GPIOD的Pin0-Pin5,但是导致了LCD无法正常使用,猜测是GPIOD中的某个IO在LCD中也使用了,导致冲突,具体是哪一个还不知道(技术太菜,LCD里面太多内容,看不懂…)
    1.MatrixButton.h头文件:

    #ifndef __MatrixButton_H
    #define __MatrixButton_H
    #include "sys.h"
    #define DelayTimes 10
    void GPIOF_Int_Init(void);
    void GPIOB_Int_Init(void);
    void KEY_Scan(void);
    void Multiple_Control(void);
    #endif
    
    

    2.MatrixButton.c文件代码:

    #include "MatrixButton.h"
    #include "delay.h"
    u16 KeyValue=17;//17只是为了在没有按键按下的时候给一个数值让LCD显示
    void GPIOF_Int_Init(void)
    {
    	GPIO_InitTypeDef GPIO_InitStructure;
    	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF,ENABLE);//使能GPIOF时钟
    	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5;//IO输出引脚选用PF0-PF5
    	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_OUT;//输出模式
    	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;//输出速度50MHZ
    	GPIO_InitStructure.GPIO_OType=GPIO_OType_PP;//推挽输出
    	GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_DOWN;//下拉
    	GPIO_Init(GPIOF,&GPIO_InitStructure);//初始化GPIOF
    }
    void GPIOB_Int_Init(void)
    {
    	GPIO_InitTypeDef GPIO_InitStruct;
    	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB,ENABLE);//使能GPIOB的时钟
    	GPIO_InitStruct.GPIO_Pin=GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3;
    	GPIO_InitStruct.GPIO_Mode=GPIO_Mode_OUT;//输出模式
    	GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
    	GPIO_InitStruct.GPIO_OType=GPIO_OType_PP;
    	GPIO_InitStruct.GPIO_PuPd=GPIO_PuPd_UP;
    	GPIO_Init(GPIOB,&GPIO_InitStruct);
    	
    	GPIO_InitStruct.GPIO_Pin=GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7;
    	GPIO_InitStruct.GPIO_Mode=GPIO_Mode_IN;//输入模式,用来检测哪一行按下
    	GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
    	GPIO_InitStruct.GPIO_PuPd=GPIO_PuPd_UP;
    	GPIO_Init(GPIOB,&GPIO_InitStruct);
    		
    }
    void KEY_Scan(void)									
    {
    	
    	GPIOB_Int_Init();					//PB4-PB5的状态全部置1
    	GPIO_ResetBits(GPIOB,GPIO_Pin_3); 	//第一行检测
    	GPIO_SetBits(GPIOB,GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2);                              
    	if(((GPIOB->IDR )&0xF0)!=0xF0)	 //说明PD4-PD7状态发生变化,列检测
    	{
    		delay_ms(DelayTimes);			//按键消抖
    		if(((GPIOB->IDR )&0xF0)!=0xF0) 		//再次判断是否有按键按下
    		{
    			switch((GPIOB->IDR )&0xF7)//检测输入数据寄存器PB4-PB7对应位的电平状态
    			{ 
    				case 0xE7:KeyValue=1;break;//说明PB4接收到低电平,第一行第一列对应第一个按键
    				case 0xD7:KeyValue=2;break; 
    				case 0xB7:KeyValue=3;break;
    				case 0x77:KeyValue=4;break; 
    				default:break;
    			}
    
    		 }	
    	 }
    	GPIOB_Int_Init();
    	GPIO_ResetBits(GPIOB,GPIO_Pin_2); 
    	GPIO_SetBits(GPIOB,GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_3);
    	if(((GPIOB->IDR )&0xF0)!=0xF0)	 //说明PD4-PD7状态发生变化,列检测
    	{
    		delay_ms(DelayTimes);									//按键消抖
    		if(((GPIOB->IDR )&0xF0)!=0xF0) 		//再次判断是否有按键按下
    		{
    			switch((GPIOB->IDR )&0xFB)
    			{ 
    				case 0xEB:KeyValue=5;break;
    				case 0xDB:KeyValue=6;break; 
    				case 0xBB:KeyValue=7;break;
    				case 0x7B:KeyValue=8;break; 
    				default:break;
    			}
    
    		}		
    	 }
    	 GPIOB_Int_Init();
    	 GPIO_ResetBits(GPIOB,GPIO_Pin_1);		//Pin1输出低电平
    	 GPIO_SetBits(GPIOB,GPIO_Pin_0|GPIO_Pin_2|GPIO_Pin_3);//Pin0,Pin2,Pin3输出高电平
    	 if(((GPIOB->IDR )&0xF0)!=0xF0)	 //说明PD4-PD7状态发生变化,列检测
    	{
    		delay_ms(DelayTimes);									//按键消抖
    		if(((GPIOB->IDR )&0xF0)!=0xF0)		//再次判断是否有按键按下
    		{
    			switch((GPIOB->IDR )&0xFD)
    				 { 
    					case 0xED:KeyValue=9;break;
    					case 0xDD:KeyValue=10;break; 
    					case 0xBD:KeyValue=11;break;
    					case 0x7D:KeyValue=12;break; 
    					default: break;
    				}
    
    		 }	
    	 }	
    	GPIOB_Int_Init();
    	GPIO_ResetBits(GPIOB,GPIO_Pin_0); 			//Pin0输出低电平
    	GPIO_SetBits(GPIOB,GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3);//Pin1-Pin3输出高电平
    	if(((GPIOB->IDR )&0xF0)!=0xF0)	 //说明PD4-PD7状态发生变化,列检测
    	{
    		delay_ms(DelayTimes);									//按键消抖
    		if(((GPIOB->IDR )&0xF0)!=0xF0) 		//再次判断是否有按键按下
    		{
    			switch((GPIOB->IDR )&0xFE)
    				{ 
    					case 0xEE:KeyValue=13;break; 
    				    case 0xDE:KeyValue=14;break; 
    				    case 0xBE:KeyValue=15;break; 
    				    case 0x7E:KeyValue=16;break; 
    					default:break;
    				} 
    		 }
    	 }
    	
    	
    							 
    }
    void Multiple_Control(void)//控制IO口输出
    {
    	if(KeyValue!=17)	 //说明有按键按下
    	{
    		switch(KeyValue) 
    		{ 
    			case 1:
    			{
    				GPIO_ResetBits(GPIOF,GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2);break;//000
    			}
    			case 2:
    			{
    				GPIO_ResetBits(GPIOF,GPIO_Pin_1|GPIO_Pin_2);
    				GPIO_SetBits(GPIOF,GPIO_Pin_0);break;//001
    			}
    			case 3:
    			{
    				GPIO_ResetBits(GPIOF,GPIO_Pin_0|GPIO_Pin_2);
    				GPIO_SetBits(GPIOF,GPIO_Pin_1);break;//010
    			}
    			case 4:
    			{
    				GPIO_ResetBits(GPIOF,GPIO_Pin_2);
    				GPIO_SetBits(GPIOF,GPIO_Pin_0|GPIO_Pin_1);break;//011
    			}
    			case 5:
    			{
    				GPIO_ResetBits(GPIOF,GPIO_Pin_0|GPIO_Pin_1);
    				GPIO_SetBits(GPIOF,GPIO_Pin_2);break;//100
    			}
    			case 6:
    			{
    				GPIO_ResetBits(GPIOF,GPIO_Pin_1);
    				GPIO_SetBits(GPIOF,GPIO_Pin_0|GPIO_Pin_2);break;//101
    								
    			}
    			case 7:
    			{
    				GPIO_ResetBits(GPIOF,GPIO_Pin_0);
    				GPIO_SetBits(GPIOF,GPIO_Pin_1|GPIO_Pin_2);break;//110
    								
    			}
    			case 8:
    			{
    				GPIO_SetBits(GPIOF,GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2);break;//111
    			}
    			case 9:
    			{
    				GPIO_ResetBits(GPIOF,GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5);break;//000
    			}
    			case 10:
    			{
    				GPIO_ResetBits(GPIOF,GPIO_Pin_4|GPIO_Pin_5);
    				GPIO_SetBits(GPIOF,GPIO_Pin_3);break;//001
    			}
    			case 11:
    			{
    				GPIO_ResetBits(GPIOF,GPIO_Pin_3|GPIO_Pin_5);
    				GPIO_SetBits(GPIOF,GPIO_Pin_4); break;//010
    			}
    			case 12:
    			{
    				GPIO_ResetBits(GPIOF,GPIO_Pin_5);
    				GPIO_SetBits(GPIOF,GPIO_Pin_3|GPIO_Pin_4);break;//011
    			}
    			case 13:
    			{
    				GPIO_ResetBits(GPIOF,GPIO_Pin_3|GPIO_Pin_4);
    				GPIO_SetBits(GPIOF,GPIO_Pin_5);break;//100
    			}
    			case 14:
    			{
    				GPIO_ResetBits(GPIOF,GPIO_Pin_4);
    				GPIO_SetBits(GPIOF,GPIO_Pin_5|GPIO_Pin_3);break;//101
    			}
    			case 15: 
    			{
    				GPIO_ResetBits(GPIOF,GPIO_Pin_3);
    				GPIO_SetBits(GPIOF,GPIO_Pin_4|GPIO_Pin_5);break;//110
    			}
    			case 16:
    			{
    				GPIO_SetBits(GPIOF,GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5);break;//111
    			}
    		}
    		
    	}
    	
    }
    	
    
    

    3.主函数main.c:

    #include "sys.h"
    #include "delay.h"
    #include "usart.h"
    #include "led.h"
    #include "MatrixButton.h"
    #include "lcd.h"
    extern u16 KeyValue;
    int main(void)
    {
    	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);		//设置系统中断优先级分组2
    	delay_init(168);   								    //初始化延时函数
    	uart_init(115200);									//初始化串口波特率为115200
    	LED_Init();											//初始化LED 
    	GPIOF_Int_Init();
    	LED0=0;
    	LCD_Init();         								//初始化LCD接口
    	LCD_Display_Dir(1);							    	//横屏显示	
    	POINT_COLOR=RED; 
    	
    	while(1)
    	{
    		if(KeyValue!=KeyValue)//按键值改变时才清屏
    			LCD_Clear(WHITE);
    		LCD_ShowString(30,150,200,16,16,"KeyValue_is:"); //这里显示了KeyValue_is:
    		KEY_Scan();		//行扫描矩阵按键
    		LCD_ShowxNum(134,150,KeyValue,2,16,0); 
    		Multiple_Control();			//矩阵按键控制IO口输出
    		LED0=!LED0;
    		delay_ms(50);
    		
    	}
    }
    
    
    
    
    
    展开全文
  • stm32矩阵键盘按键扫描程序亲测可用,PA0~PA7为矩阵键盘接口,PA9PA10为串口
  • STM32 矩阵键盘 程序 可以实现任意不连续引脚配置的完美设置 并且显示 显示采用JLX12864G-086-PC 引脚任意配置 完美显示
  • STM32f103矩阵按键驱动

    2018-06-18 11:45:38
    自己做的矩阵按键扫描驱动程序 这个程序有一定的亮点 仅用了一个输出循环 不用改变输出输入的引脚 靠标记就能知道行坐标 比较适应STM32这样稍微复杂的引脚配置。
  • STM32矩阵按键程序思路

    千次阅读 2020-01-30 18:31:39
    之前学52的时候学过矩阵按键的程序,但是当我第一次拿到32板子写程序的时候还是有一点懵,不过还来理理思路,感觉想一想还是可以写出来的,我这次是没有自己去焊矩阵按键,而是买了一个薄膜按键,省去了焊接的麻烦//...

    一:开个头

    之前学52的时候学过矩阵按键的程序,但是当我第一次拿到32板子写程序的时候还是有一点懵,不过还来理理思路,感觉想一想还是可以写出来的,我这次是没有自己去焊矩阵按键,而是买了一个薄膜按键,省去了焊接的麻烦//手动狗头//

    二:操作实物图

    就是这个啦!!!应该可以看出来黄色的线连着的是矩阵按键的行,橙色线连着的事矩阵按键的列,下面解释的时候我会用行和列来说

    三:程序思路

    1、首先一个大思路,我们用矩阵按键的时候,首先是先确定哪一行,接着是哪一列
    (1)我让行作输出,并输出低电平,列作输入,并读取电平,当有按键按下的时候就会有电平变化–>这个是用来判断是哪一行

    void KEY_L_Init(void)
    {
       GPIO_InitTypeDef GPIO_InitStructure;
       RCC_APB2PeriphClockCmd (RCC_APB2Periph_GPIOA,ENABLE);
    //	 RCC_APB2PeriphClockCmd (RCC_APB2Periph_GPIOB,ENABLE);
       //列
       GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;//输入上拉  
       GPIO_InitStructure.GPIO_Pin=KEY_L0_GPIO_PIN|KEY_L1_GPIO_PIN|KEY_L2_GPIO_PIN|KEY_L3_GPIO_PIN;
       GPIO_Init(GPIOA,&GPIO_InitStructure);
       //行
       GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;        //推挽输出
       GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;      
       GPIO_InitStructure.GPIO_Pin=KEY_R0_GPIO_PIN|KEY_R1_GPIO_PIN|KEY_R2_GPIO_PIN|KEY_R3_GPIO_PIN;
       GPIO_Init(GPIOA,&GPIO_InitStructure);       
       GPIO_ResetBits(GPIOA,KEY_R0_GPIO_PIN|KEY_R1_GPIO_PIN|KEY_R2_GPIO_PIN|KEY_R3_GPIO_PIN);
    }
    

    (2)下面确定哪一列,因为我们刚刚确定了哪一行,只要确定哪一列,就可以找出按下的位置,这次思路是让列输出并输出高电平,让行作输入并读取电平变化

    void KEY_R_Init(void)
    {
       GPIO_InitTypeDef GPIO_InitStructure;
       RCC_APB2PeriphClockCmd (RCC_APB2Periph_GPIOA,ENABLE);
    //	 RCC_APB2PeriphClockCmd (RCC_APB2Periph_GPIOB,ENABLE);	 //列
    	
       GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;        //推挽输出
       GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
       GPIO_InitStructure.GPIO_Pin=KEY_L0_GPIO_PIN|KEY_L1_GPIO_PIN|KEY_L2_GPIO_PIN|KEY_L3_GPIO_PIN;
       GPIO_Init(GPIOA,&GPIO_InitStructure);
    	 GPIO_SetBits(GPIOA,KEY_L0_GPIO_PIN|KEY_L1_GPIO_PIN|KEY_L2_GPIO_PIN|KEY_L3_GPIO_PIN);
       //行
       GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPD;   //浮空输入
       GPIO_InitStructure.GPIO_Pin=KEY_R0_GPIO_PIN|KEY_R1_GPIO_PIN|KEY_R2_GPIO_PIN|KEY_R3_GPIO_PIN;
       GPIO_Init(GPIOA,&GPIO_InitStructure);	 
    }
    

    (3)下面只需要作按键位置处理就可以了

    char KeyScan(void)
    {
    	u8 column=0;
    	char Key_Number=0;
        KEY_L_Init();    //行做输出低电平,列读取电平
    	while(1)
    	{
    		if(PAin(7)==0)
    		{
    			delay_ms(100);
    			if(PAin(7)==0)
    			{
    				column=1;        //如果第一列读到低电平
    			}
    		}
    		if(PAin(6)==0)
    		{
    			delay_ms(100);
    			if(PAin(6)==0)
    			{
    				column=2;        //如果第二列读到低电平
    			}
    		}
    		if(PAin(5)==0)
    		{
    			delay_ms(100);
    			if(PAin(5)==0)
    			{
    				column=3;        //如果第三列读到低电平
    			}
    		}
    		if(PAin(4)==0)
    		{
    			delay_ms(100);
    			if(PAin(4)==0)
    			{
    				column=4;        //如果第四列读到低电平
    			}
    		}
    
    		
    		if(column==1)
    		{
    			delay_ms(50);
    				KEY_R_Init();     //列做输出高电平,行读取电平  
    				if(column==1)
    				{
    				           
    					if(PAin(3)==1)
    					{
    						Key_Number='1';
    						break;   //第一行
    					}
    					if(PAin(2)==1)
    					{
    						Key_Number='2';
    						break;   //第二行
    					}
    					if(PAin(1)==1)
    					{
    						Key_Number='3';
    						break;   //第三行
    					}
    					if(PAin(0)==1)
    					{
    						Key_Number='A';
    						break;   //第四行
    					}
    				}
    		}
    		
    		
    		if(column==2)
    		{
    			delay_ms(50);
    				KEY_R_Init();     //列做输出高电平,行读取电平  
    				if(column==2)
    				{
    				           
    					if(PAin(3)==1)
    					{
    						Key_Number='4';
    						break;   //第一行
    					}
    					if(PAin(2)==1)
    					{
    						Key_Number='5';
    						break;   //第二行
    					}
    					if(PAin(1)==1)
    					{
    						Key_Number='6';
    						break;   //第三行
    					}
    					if(PAin(0)==1)
    					{
    						Key_Number='B';
    						break;   //第四行
    					}
    				}
    		}
    		
    		if(column==3)
    		{
    			delay_ms(50);
    				KEY_R_Init();     //列做输出高电平,行读取电平  
    				if(column==3)
    				{
    				           
    					if(PAin(3)==1)
    					{
    						Key_Number='7';
    						break;   //第一行
    					}
    					if(PAin(2)==1)
    					{
    						Key_Number='8';
    						break;   //第二行
    					}
    					if(PAin(1)==1)
    					{
    						Key_Number='9';
    						break;   //第三行
    					}
    					if(PAin(0)==1)
    					{
    						Key_Number='C';
    						break;   //第四行
    					}
    				}
    		}
    		
    		if(column==4)
    		{
    			delay_ms(50);
    				KEY_R_Init();     //列做输出高电平,行读取电平  
    				if(column==4)
    				{
    				           
    					if(PAin(3)==1)
    					{
    						Key_Number='*';
    						break;   //第一行
    					}
    					if(PAin(2)==1)
    					{
    						Key_Number='0';
    						break;   //第二行
    					}
    					if(PAin(1)==1)
    					{
    						Key_Number='#';
    						break;   //第三行
    					}
    					if(PAin(0)==1)
    					{
    						Key_Number='D';
    						break;   //第四行
    					}
    				}
    		}
    		
    	}
       return Key_Number;
    }
    

    总结

    虽然代码有点长,但是切实可行,对了,这里还有一个问题我当时也纠结了一下啊,就是按键延时消抖动,我这个延时时间还挺合适的,不过这个可以随自己的喜好去修改,如果你有更好的方法,可以分享给我学习一下,嘻嘻嘻~

    展开全文
  • STM32f1034乘4矩阵按键 STM32f1034乘4矩阵按键
  • --作者:肖肖肖本文为明德扬原创及录用文章,转载请注明出处!1.1 总体设计1.1.1 概述在键盘中按键数量较多时,为了减少I/O口的占用,通常将按键排列成矩阵形式。在矩阵式键盘...

    --作者:肖肖肖

    本文为明德扬原创及录用文章,转载请注明出处!

    1.1 总体设计

    1.1.1 概述

    在键盘中按键数量较多时,为了减少I/O口的占用,通常将按键排列成矩阵形式。在矩阵式键盘中,每条水平线和垂直线在交叉处不直接连通,而是通过一个按键加以连接。这样,一个端口(如P1口)就可以构成4*4=16个按键,比之直接将端口线用于键盘多出了一倍,而且线数越多,区别越明显,比如再多加一条线就可以构成20键的键盘,而直接用端口线则只能多出一键(9键)。由此可见,在需要的键数比较多时,采用矩阵法来做键盘是合理的。

    1.1.2 设计目标

    完成矩阵键盘的扫描检测程序,具体功能要求如下:

    1. 运用逐行扫描的方法进行按键监测;

    2. 每行扫描的时间不少于 20ms,滤除抖动;

    3. 检测到有按键按下之后,消抖时间 20ms;

    4. 输出信号 key_vld 持续一拍即可;

    5. 输出信号key_out表示16 个按键,并在数码管上显示对应数值;

    1.1.3 系统结构框图

    系统结构框图如下图一所示:

    45a793796e8de37084bbab9b2d477c11.png

    图一

    1.1.4 模块功能

    Ø 矩阵键盘模块实现功能

    1、将外来异步信号打两拍处理,将异步信号同步化。

    2、实现20ms按键消抖功能。

    3、实现矩阵键盘的按键检测功能,并输出有效按键信号。

    Ø 数码管显示模块实现功能

    1、 对接收到的按键数据进行译码并显示。

    1.1.5 顶层信号

    93bc50a7cb3ee6ada01481196f471aa7.png

    1.1.6 参考代码

    下面是使用工程的顶层代码:

    1. 

    1.2 矩阵键盘模块设计

    1.2.1 接口信号

    ae3eb184e97ef60ba8412123bad01d8b.png

    1.2.2 设计思路

    Ø 行扫描法原理

    开发板上为 4*4 矩阵键盘:默认 4 条列线上来高电平,4 条行线默认接高电平。列线 KEY_C1 ~ KEY_C4分别接有4个上拉电阻到正电源 +3.3 V,并把列线 KEY_C1~KEY_C4设置为输入线,行线 KEY_R1~KEY_R4设置为输出线。4根行线和4根列线形成16个相交点。

    如下图所示:

    e396edfdb6fb498da48d34284ce65e40.png

    确认矩阵键盘上哪个按键被按下有多同方法,其中行扫描法又称为逐行(或列)扫描查询法,是一种最常用的按键识别方法。

    1. 判断键盘中有无键按下:将全部行线 KEY_R1~KEY_R4 置低电平,然后检测列线 KEY_C1~KEY_C4 的状态。只要有一列的电平为低,则表示键盘中有键被按下,而且闭合的键位于低电平线与 4根行线相交叉的 4 个按键之中。若所有列线均为高电平,则键盘中无键按下。

    2. 判断闭合键所在的位置:在确认有键按下后,即可进入确定具体闭合键的过程。其方法是:依次将行线置为低电平,即在置某根行线为低电平时,其它线为高电平。在确定某根行线位置为低电平后,再逐行检测各列线的电平状态。若某列为低,则该列线与置为低电平的行线交叉处的按键就是闭合的按键。

    Ø 打拍操作

    输入的key_col是异步信号,所以要进行打两拍操作,将异步信号key_col同步化,并防止亚稳态。

    设计代码如下:

    1. 

    Ø 按键消抖

    对于按键和触摸屏等机械设备来说,都存在一个固有问题,那就是“抖动”,按键从最初接通到稳定接通要经过数毫秒,其间可能发生多次“接通-断开”这样的毛刺。如果不进行处理,会使系统识别到抖动信号而进行不必要的反应,导致模块功能不正常,为了避免这种现象的产生,需要进行按键消抖的操作。

    软件方法消抖,即检测出键闭合后执行一个延时程序,抖动时间的长短由按键的机械特性决定,一般为5ms~20ms,让前沿抖动消失后再一次检测键的状态,如果仍保持闭合状态电平,则确认按下按键操作有效。当检测到按键释放后,也要给5ms~20ms的延时,待后沿抖动消失后才能转入该键的处理程序。

    91aebd1fa4abb45c952f3215b3a24a4f.png

    由于按键按下去的时间一般都会大于20ms,为了达到不管按键按下多久,都视为按下一次的效果,提出以下计数器架构,如下图所示:

    ee03145f7a20131340e9f9f23daf9b0d.png

    消抖计数器shake_cnt:用于计算20ms的时间,加一条件为key_col_ff1 != 4'hf || key_row_check==1,表示当某个按键按下或者进行行扫描时就开始计数;数到1,000,000下,表示数到20ms就结束。

    行扫描计数器row_index:用于区分扫描的行,加一条件为key_row_check && end_shake_cnt,表示当处于行扫描状态并且每行消抖20ms后,开始扫描下一行;数到4下,表示4行按键扫描完了。

    按键:表示有无按键按下,没被按下时为高电平,按下后为低电平。

    行扫描指示信号key_row_check:该信号为高电平,指示当前处于行扫描状态。

    矩阵键盘列信号key_col_ff1:4bit位宽的矩阵键盘列信号,最高位表示矩阵键盘往右数第四列,默认信号为key_col_ff1 = 4'hf,否则表示该信号低电平对应位的列有按键按下。

    1.2.3 参考代码

    16. 

    1.3 数码管显示模块设计

    1.3.1 接口信号

    73478066af6fff45b2b17792697aefa1.png

    1.3.2 设计思路

    在前面的案例中已经有数码管显示的介绍,所以这里不在过多介绍。

    1.3.3 参考代码

    1. 

    1.4 效果和总结

    Ø 下图是该工程在db603开发板上的现象——按下按键s7

    46233a74d5120f7a73774c2140af1d29.png

    Ø 下图是该工程在ms980试验箱上的现象——按下按键s13

    2c4156610ba598b5449358e3c8fceb6c.png

    由于该项目的上板现象是按下矩阵按键,数码管显示对应的按键号,想观看完整现象的朋友可以看一下现象演示的视频。

    展开全文
  • 一、本章简介本章以core-G1【STM32F103C8T8】核心板 +Q1 cenozoic开发板 矩阵按键扫描实验 之入门系列4工程为例,介绍STM32关于GPIO的配置方法,将STM32的GPIO设置为输入模式,并使用此来发版上的4*3按键来做矩阵...
  • STM32矩阵键盘的实现

    2018-06-24 11:04:45
    STM32中断的方式实现矩阵按键。使用外部中断5_9,外部中断接口接PC8~PC5。
  • 据 IHS Market 数据,STM32出货量在2018年站在了中国通用“MCU市场“一号位”。凭借对应用市场的持续认知升级,成就了STM32产品能力十三年的不间断升维;紧耦合应用市场的变化,在万物互联时代不仅提供传统MCU的逻辑...
  • 使用STM32F103ZET6驱动矩阵 按键源码
  • STM32矩阵键盘实现方法收集, STM32用矩阵键盘,不带外部中断,可以多个按键同时按下 C代码: STM32用矩阵键盘,不带外部中断,可以多个按键同时按下
  • 1.1 总体设计1.1.1 概述在键盘中按键数量较多时,为了减少I/O口的占用,通常将按键排列成矩阵形式。在矩阵式键盘中,每条水平线和垂直线在交叉处不直接连通,而是通过一个按键加以连接。这样,一个端口(如P1口)就...
  • STM32矩阵键盘不带外部中断可以多个按键同时按下 C代码STM32矩阵键盘不带外部中断可以多个按键同时按下 /* 矩阵键盘 .h 文件 */ #ifndef _COMMON_H #define _COMMON_H #include " /* 4*4 矩阵键盘 */ void ...
  • STM32 矩阵键盘扫描实验

    热门讨论 2011-05-15 09:45:27
    STM32 矩阵键盘扫描实验,完整程序,高度的可移植性,可以接到任意IO口。 4*4 与4*3 扫描读按键程序
  • STM32 4*4矩阵按键

    千次阅读 2019-10-15 23:02:19
    本文章讲述了如何用STM32编写4*4矩阵按键程序,先简单介绍一下扫描的基本方法:1.反转法 2.行列扫描。本文主要介绍行列扫描 欢迎加入嵌入式学习群:559601187 (一)代码如下 /***********************************...
  • STM32矩阵键盘测试代码以及完整工程 使用的是正点原子的精英版测试的,可通过串口发送所按下的按键的键值 工程完整,注释清楚,可以直接使用 方便移植 此次的实验GPIO口链接图: C4------------>PC0 C3-...
  • 2017 电赛 滚球控制系统源代码(PIXY+ds3115舵机+stm32+矩阵按键+lcd12864) 特别实用,分享给大家!
  • //stm32矩阵键盘翻转扫描法(PB口的低8位) //将此矩阵键盘扫描程序放在定时器中断服务程序里 //每10ms进入一次中断服务程序 s8 scan_MatrixKey(void) { #define PORT GPIOB->IDR u8 column;//列 u8 row;//行 u8 ...

空空如也

空空如也

1 2 3 4 5 ... 10
收藏数 181
精华内容 72
关键字:

stm32矩阵按键