精华内容
下载资源
问答
  • stm32矩阵键盘按键扫描程序亲测可用,PA0~PA7为矩阵键盘接口,PA9PA10为串口
  • STM32 矩阵键盘扫描实验

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

    2020-06-16 13:19:05
    键盘扫描
  • STM32 4X4矩阵按键扫描 使用中断扫描

    千次阅读 2019-12-14 21:13:58
    //stm32矩阵键盘翻转扫描法(PB口的低8位) //将此矩阵键盘扫描程序放在定时器中断服务程序里 //每10ms进入一次中断服务程序 s8 scan_MatrixKey(void) { #define PORT GPIOB->IDR u8 column;//列 u8 row;//行 u8 ...

    //stm32矩阵键盘翻转扫描法(PB口的低8位)
    //将此矩阵键盘扫描程序放在定时器中断服务程序里
    //每10ms进入一次中断服务程序
    s8 scan_MatrixKey(void)
    {
        #define PORT GPIOB->IDR
        u8 column;//列
        u8 row;//行
        u8 tmp;//临时变量
        s8 MatrixKey_value = 20;//初始值不能为0~15 
        static u8 key_count = 0;//按键被中断扫描的次数
        
        ///IO口的配置/
        //低8位为推挽输出
        GPIOB->CRL &= 0X00000000;
        GPIOB->CRL |= 0X33333333;
        //初值:低4位为低,次低4位为高
        GPIOB->ODR &= 0XFF00;
        GPIOB->ODR |= 0X00F0;
        //次低4位为上拉输入
        GPIOB->CRL &= 0X0000FFFF;
        GPIOB->CRL |= 0X88880000;
      

        tmp = PORT;//必须要
        if (tmp != 0XF0)//如果有键按下
        {   
            //防止长按时,持续自增导致变量溢出
            if (key_count <= 2)
            {
                key_count++;
            }
        }
        //若产生抖动按键被抬起则计数清0 
        else
        {
            key_count = 0;
        }
        //若按键连续2次扫描均处于按下状态
        //则认为按键确实被按下了
        if (key_count == 2)
        {          
            column = tmp & 0X00F0;//获取列号 
            
            ///IO口的配置/
            //低8位为推挽输出
            GPIOB->CRL &= 0X00000000;
            GPIOB->CRL |= 0X33333333;
            //翻转:低4位为高,次低4位为低
            GPIOB->ODR &= 0XFF00;
            GPIOB->ODR |= 0X000F;//低4位为高,次低4位为低
            //低4位为上拉输入
            GPIOB->CRL &= 0XFFFF0000;
            GPIOB->CRL |= 0X00008888; 
                                
            row = PORT & 0X000F;//获取行号                                         
            switch (column | row)//column|row为按键被按下对应端口的编码
            {   
                //按键对应的码表(可以根据需求调整欲返回的键值) 
                case 0XEE: MatrixKey_value = 12; break;
                case 0XDE: MatrixKey_value = 10; break;
                case 0XBE: MatrixKey_value = 11; break;                
                case 0X7E: MatrixKey_value = 0; break;                                              
                case 0XED: MatrixKey_value = 13; break;
                case 0XDD: MatrixKey_value = 3; break;
                case 0XBD: MatrixKey_value = 2; break;
                case 0X7D: MatrixKey_value = 1; break;                                  
                case 0XEB: MatrixKey_value = 14; break;
                case 0XDB: MatrixKey_value = 6; break;
                case 0XBB: MatrixKey_value = 5; break;
                case 0X7B: MatrixKey_value = 4; break;                                    
                case 0XE7: MatrixKey_value = 15; break;
                case 0XD7: MatrixKey_value = 9; break;
                case 0XB7: MatrixKey_value = 8; break;
                case 0X77: MatrixKey_value = 7; break;
                default:   break;     
            }                    
        } 
        //若没有按键被按下(已松手)则扫描次数清0
        //方便下次按下扫描计数
        if ((PORT & 0X00FF) == 0x00F0)
        {
            key_count = 0;  
        }

        return MatrixKey_value;
    }
     

    展开全文
  • 矩阵按键有两种扫描方式: 方法一: 逐行扫描:我们可以通过低四位轮流输出低电平来对矩阵键盘进行逐行扫描,当高四位接收到的数据不全为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按键扫描测试程序(学习记录): 目录: 源码; 4x4按键原理; Tips: 粘贴代码时,粘贴在源文件存放的位置中(如:HARDWARE中的.c和.h文件),用C++编译器打开,而不是kei;最后keil会正常显示中文...

    基于STM32的按键扫描测试程序(学习记录):

    目录:

    1. 源码;
    2. 4x4按键原理;
    3. 按键扫描逻辑;

    Tips:

    1. 粘贴代码时,粘贴在源文件存放的位置中(如:HARDWARE中的.c和.h文件),用C++编译器打开,而不是kei;最后keil会正常显示中文字符;
    2. 程序使用嵌套循环实现4x4按键扫描,如果IO口设置过乱时,将循环拆分即可;

    key4x4.h源文件

    #ifndef __KEY4x4_H
    #define __KEY4x4_H	 
    #include "sys.h"
     
    #define KEY_X(X)	PEin(X)				// 尽量避免使用PD以上GPIO,便于移植;
    #define KEY_Y(Y)	PEout(Y)
    
    #define ALL_DOWN_KEY_Y	{	KEY_Y(11) = 0; KEY_Y(12) = 0; KEY_Y(13) = 0; KEY_Y(14) = 0;}
     
    void KEY4x4_Init(void);		// IO口初始化
    u8 KEY4x4_Scan(void);  		// 矩阵按键反馈函数	// 可配置任意矩阵按键使用!!
    u8 KEY16_Scan(void);
    
    /**************
    按键扫描方案二:
    按键使用8个输入IO口, 且所有IO口一端接VCC/VSS;
    
    程序框架:	
    	扫描检测哪两个IO口输入高/低电平;VCC/VSS
    	根据对应坐标,return对应编号;
    **************/
    
    #endif
    

    key4x4.c源文件

    #include "stm32f10x.h"
    #include "key4x4.h"
    #include "sys.h" 
    #include "delay.h"
    #include "usart.h"
    
    
    /*************************
    X:
    	PEin	7-10
    Y:
    	PEout	11-14
    *************************/
    
    
    // 矩阵按键初始化函数
    void KEY4x4_Init(void)
    {
    		GPIO_InitTypeDef GPIO_InitStructure;
    
    		RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE,ENABLE);
    
    		GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_7|GPIO_Pin_8|GPIO_Pin_9|GPIO_Pin_10;//KEY0-KEY1
    		GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; //设置成下拉输入
    		GPIO_Init(GPIOE, &GPIO_InitStructure);//初始化GPIOE
    
    		GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_11|GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_14;				 //LED0-->PB.5 端口配置
    		GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 		 //推挽输出
    		GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;		 //IO口速度为50MHz
    		GPIO_Init(GPIOE, &GPIO_InitStructure);					 		//根据设定参数初始化GPIOE
    }
    
    // 使所有输出拉低;初始化;		// 可以使用define宏定义,执行速度更快,不用跳转函数!!
    static void KEY_ALL_Pull_Down(void)
    {
    	KEY_Y(11) = 0;
    	KEY_Y(12) = 0;
    	KEY_Y(13) = 0;
    	KEY_Y(14) = 0;
    }
    
    // 4x4按键扫描函数
    // 使用一个嵌套循环,完成扫描X和Y;
    // 原理: 通过Y 依次输出高电平,
    //				扫描X 那个IO口输入高电平;
    // X轴:输入检查、扫描;
    // Y轴:设置输出状态;
    // 该函数适合任意排列矩阵按键,只需修改循环中对应编号!!
    // 注意: 1. 改变IO口时,该函数还需要改变循环中IO口编号;(可以定义好IO口编号,便于修改)
    //				2. 该函数同样有优先级问题! 即同时按下时,只反馈先被扫描到的(0-15标号最小的)
    //				3. 函数同一坐标轴的IO口编号必须相邻或能有 规律递增可寻;(否则无法用循环判断)
    //				4. 暂时未添加功能(模式):	按键复用 和 长按;
    // 2020-11-13		返回值调整为:1-16
    // 11/14 不支持连按;解决重复反馈的问题;
    u8 KEY4x4_Scan(void)
    {
    	int i,j;
    	u8 IO_Sign = 0;				// 很简便的一个IO反馈方式标签!!!  且嵌套循环特有!!  // 能返回0-15,适合任意排列矩阵按键
    	static key_up = 1;
    	
    	//KEY_ALL_Pull_Down();										// 初始化所有按键输出拉低;
    	
    	for (i = 11; i <= 14; i++)							// Y输出IO口编号;
    		for (j = 7; j <= 10; j++,IO_Sign++)		// X输出IO口编号;  // 递增IO_Sign,反馈对应值(0-15);
    		{
    			KEY_Y(i) = 1;			// 使PEout(i)输出高电平;
    			
    			if (KEY_Y(i))			// 扫描Y输出高电平, 可以取消此判断; 因为必须输出高电平时,才能正常判断!!
    			{
    				if (KEY_X(j) && key_up)		// 当输入检查到高电平时;
    				{
    					key_up = 0;
    					printf("按键扫描反馈: %d  \r\n",IO_Sign);
    					return IO_Sign;
    				}
    				else if (!KEY_X(7)&&!KEY_X(8)&&!KEY_X(9)&&!KEY_X(10))			// 当所有输入检测到低电平时,再次使能按键; 防止重复反馈
    				{
    					key_up = 1;
    					KEY_ALL_Pull_Down();										// 初始化所有按键输出拉低(低电平);必须在此位置;
    				}
    			}
    			else
    				printf("PEout:IO口%d输出异常!  \r\n ", i);
    		}
    		
    	delay_ms(10);					// 按键防抖;
    }
    
    
    /******************************************标准扫描函数*********************************************/
    // 支持连按
    u8 KEY16_Scan(void)
    {
    	int i,j;
    	u8 IO_Sign = 0;				// 很简便的一个IO反馈方式标签!!!  且嵌套循环特有!!  // 能返回0-15,适合任意排列矩阵按键
    	
    	ALL_DOWN_KEY_Y													// 初始化所有按键输出拉低;
    	
    	for (i = 11; i <= 14; i++)							// Y输出IO口编号;
    		for (j = 7; j <= 10; j++,IO_Sign++)		// X输出IO口编号;  // 递增IO_Sign,反馈对应值(0-15);
    		{
    			KEY_Y(i) = 1;			// 使PEout(i)输出高电平;
    
    			if (KEY_X(j))			// 当输入检查到高电平时;
    				return IO_Sign;
    		}
    		
    	delay_ms(20);					// 按键防抖;		// 连按延时;
    }
    
    

    *4x4按键原理图
    在这里插入图片描述

    1. 按键工作原理:
      当按键被按下时,相连的电路导通;即S1按下时,位于0行0列的线短路,使标号4和5对应的IO口相连(导通);
      最后通过扫描检测输入输出状态即可判断出对应按键被按下;

    2. 程序设计思路:
      程序通过依次使标号1、2、3、4(列0-3)输出高电平,判断5/6/7/8(行0-3)状态;完成按键扫描;

    展开全文
  • STM32f103矩阵按键驱动

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

    千次阅读 多人点赞 2020-10-04 11:04:48
    STM32矩阵键盘扫描及处理 前言 由于最近帮做一个毕业设计需要用到直接输入目标值去控制输出,所以才写这么一个按键处理的程序。对于一个才接触单片机没多久的大学生菜鸟来说,实现毕设里的每一项功能都有一定的...

    STM32的矩阵键盘扫描及处理

    前言

    由于最近帮做一个毕业设计需要用到直接输入目标值去控制输出,所以才写这么一个按键处理的程序。对于一个才接触单片机没多久的大学生菜鸟来说,实现毕设里的每一项功能都有一定的挑战。接下来就分享一下我在写这按键扫描及处理中的一些经验吧。
    整个工程所需要的输出值可通过键盘任意控制,有一位小数。

    一、按键扫描

    1.矩阵按键的原理图

    矩阵键盘原理图示意图,具体键值根据自己需求设置

    这里只是键盘示意图,具体键值需根据自己需求设置

    2、按键扫描代码

    总体思路:先设置两个初始化函数,KeyPad_Init1()是高四位初始化为下拉输入、低四位为上拉输入(相当于就是给高四位低电平,低四位为高电平);KeyPad_Init2()是高四位初始化为上拉输入、低四位为下拉输入(相当于就是给高四位高电平,低四位为高电平)。程序首先使用KeyPad_Init1(),如果读取低8位引脚不是0x0f,就说明有按键被按下,然后短暂延时消抖后再次检测到低8位引脚不是0x0f,就储存高四位的的值然后进行初始化KeyPad_Init2(),然后又读取低8位引脚不是0x0f,储存其中的低四位的值,然后将高低四位值加起来就对应了一个键值。
    在这段扫描程序里面,由于扫描出的键值后面还需要处理,所以只有当有键按下后才返回才是有效的键值,没有按键按下就返回的是个无效值-1,目的是为了对每一次按键按下值进行处理,没有按下就不去处理。

    //函数名:扫描函数
    //返回值:有效键值或-1
    //功能:矩阵按键扫描,返回一个值
    short KeyPad_Scan(void)
    {
    	short num = -1; //保持按键值返回
    	
    	u16 readvalue = 0;
    	u16 re=0;
    	u16 re1=0;
    	u16 re2=0;
    	KeyPad_Init1();					//低4位引脚上拉输入,高4位引脚下拉输入
    	readvalue = GPIO_ReadInputData(GPIOA);	//读GPIOA引脚电平
    	readvalue &= 0x00ff;				//保留低8位的值(PA7-PA0)
    	if(readvalue != 0x000f) 				//高4位引脚有一个被按下
    	{
    		delay_ms(10);//消抖10ms
    		readvalue = GPIO_ReadInputData(GPIOA);	//读GPIOA引脚电平
    		if(readvalue != 0x000f)
    		{
    			re1 = GPIO_ReadInputData(GPIOA);	//再次读取状态
    			re1 &= 0x00f0;  				//保留PA4-PA7的值
    
    			KeyPad_Init2();  				//低4位引脚下拉输入,高4位引脚上拉输入
    			delay_ms(50);//经我测试,这里延迟50ms反应最快而很少出现不反应的状况
    			re2 = GPIO_ReadInputData(GPIOA);	//再次读取状态
    			re2 &= 0x000f;				//保留PA0-PA3的值
    			
    			re=re1|re2;					//相与,就知道哪一行哪一列被按下啦
    			
    			switch(re)
    			{
    			case 0x0011: num = 12;break;  
    			case 0x0012: num = 8;break;  
    			case 0x0014: num = 4;break; 
    			case 0x0018: num = 0;break;  
    			case 0x0021: num = 13;break;  
    			case 0x0022: num = 9;break; 
    			case 0x0024: num = 5;break;  
    			case 0x0028: num = 1;break;  
    			case 0x0041: num = 14;break;  
    			case 0x0042: num = 10;break;  
    			case 0x0044: num = 6;break;  
    			case 0x0048: num = 2;break;  
    			case 0x0081: num = 15;break;  
    			case 0x0082: num = 11;break;  
    			case 0x0084: num = 7;break;  
    			case 0x0088: num = 3;break;  
    			}
    			return num;
    		}
    	}
    	return -1;
    }
    
    

    二、键值处理

    1、键值处理代码

    在这段程序中我要的是按下【确定】键按下后返回确定键按下前所输入的键值(0-99.9),返回更高的值也行,不过小数点后面只能有一位数。

    /****************
    //按键值处理函数,返回最后需要的目标值,
    返回-1,按键没有按下
    返回-2或0,有按键按下,无效可适当延时
    返回其他,键值处理后的值
    *******************/
    float Key_value_processing(void)		
    {
    	
    	float key=0.0;	
    	int key_flag = -1;
    	static int key2 = 0;		//按键扫描返回值暂存处		
    	static u8		key1 = 0;
    
    	static int		Point_flag=0;		//判断‘.’是否按下标志,(Point_flag=2表示按下,Point_flag=1表示按下后进行了一次小数后一位赋值)
    	static int		key1_temp = 0;				//缓存key1值
    	
    
    				key_flag=KEYPAD_Scan();		//
    		 
    		 if(-1 == key_flag)			//如果按键没有按下
    			{
    			 return -1;
    			}
    		 else if(0 <= key_flag && key_flag <= 9)		//返回数字键,根据小数点是否按下,对数字进行
    			{
    					key1 = key_flag+key1*10;	//如有多位值,进行累加
    					key1_temp = key1;		
    				if(2 == Point_flag)
    				{
    					printf("xiaoshudianhou:%d \r\n",key1);
    					OLED_ShowNum(103,16,key1,1,16);
    					OLED_Refresh();
    					Point_flag	=	1;
    				}
    				else if(1 == Point_flag)		//点按下
    				{
    					key1=key_flag;
    				}
    				else
    				{
    					printf("shuqian:%d \r\n",key1);
    					OLED_ShowNum(63,16,key1,2,16);
    					OLED_Refresh();
    				}
    				return -2;
    			}
    			/***无效按键**/	
    			else if(10 <= key_flag && key_flag <= 13)		//暂时没有用的值,不处理
    			{
    				printf("无效值::%d \r\n",key_flag);
    				return -2;
    			}
    		 else if(Point == key_flag)		//
    			{
    			 key2 = key1_temp;
    			 Point_flag=2;
    			 key1=0;
    			 printf("float-----\r\n");
    			 OLED_ShowString(83,16,":",16); 
    				OLED_Refresh();
    				return -2;
    			}
    		 else if(Sure == key_flag)		//确定键按下后,返回处理好的值
    			{
    				if(1==Point_flag)
    				{
    					key = key2 + (float)key1/10.0;
    					Point_flag=0;
    				}
    			 else 
    			 {
    				 key=key1;
    			 }
    			 printf(":%f \r\n",key);
    			 key_flag = -1,key1 = 0,key2 = 0;
    			 return key;
    			}	
    			return -1;
    }	
    
    

    三、总结

    学习这个专业来第一次对自己所学的知识进行总结,虽然是一个做完后看起来很简单的一个知识点,在键值处理的过程中还是遇到了很多的问题。多亏了学长的帮忙才算比较轻松的完成了。这其中发现了自己以前很多的盲点,比如对于数据类型把握得不是很清楚,还有就是if else语句与if if语句的使用,在这之前写有关单片机的代码都是只用if语句,没考虑到当有多个条件时可以用if else语句可以有更快地执行效率。

    展开全文
  • scan_1/SYSTEM/usart/usart.h key_scan_1/USER/JLink Regs CM3.txt key_scan_1/USER/JLinkSettings.ini key_scan_1/USER/STM32F10x.s key_scan_1/USER/ZK_状态机_1.c key_scan_1/USER/ZK_状态机_1.hex key_scan_1/...
  • STM32 4*4矩阵按键

    千次阅读 2019-10-15 23:02:19
    本文章讲述了如何用STM32编写4*4矩阵按键程序,先简单介绍一下扫描的基本方法:1.反转法 2.行列扫描。本文主要介绍行列扫描 欢迎加入嵌入式学习群:559601187 (一)代码如下 /***********************************...
  • 比如数码管显示不正常,按键响应问题。 定时器时间消隐效果还不错,根据实验室另一个光伏项目的朋友用stc15代码改过来的。 数码管 #ifndef __LED_H #define __LED_H #include "sys.h" #define DX0 PAout(0) #...
  • 单片机STM32入门——(3)矩阵按键1.理论分析1.1键盘扫描方式1.2行扫描逻辑1.3列扫描逻辑2.程序编写2.1按键扫描程序2.1.1按键初始化2.1.2按键扫描程序头文件2.1.3行扫描函数2.1.3列扫描函数2.2主程序 1.理论分析 1.1...
  • 矩阵键盘矩阵键盘简介矩阵键盘扫描原理端口的配置相关函数的编写主函数与其他串口的接线与矩阵键盘的接线load与运行调试 矩阵键盘简介 什么是矩阵键盘 矩阵键盘是单片机外部设备中所使用的排布类似于矩阵的键盘组,...
  • 矩阵按键扫描原理: 先是把列置0,行是输入上拉,扫描行得到行的键值;再是把行置0,列是输入上拉,扫描列得到列的键值;最后把行列的键值相加得到最后的总的键值。 行扫描返回的键值为:0xe0,0xd0,0xb0,0x70 列扫描...
  • STM32矩阵键盘 一、实现效果   同时可实现 按键消抖 松手 二、使用方法  ① 包含正点原子的sys.h  ② 制作.h .c文件 -源码见 “二”  ③ 把 key_scan 函数 放入 5ms 的定时器中断,可自实现 按键消抖  ④ 按...
  • 基于STM32F1的定时器按键矩阵扫描,效率非常高;可添加判断状态程序;用户可借鉴参考学习,希望能够对您提供一定的帮助
  • 使用G070RB编了一个矩阵键盘扫描程序. 如下图, 1-4轮流拉低, 5-8检测输入确定是哪个键按下. 然后用1602液晶显示. 写完后在主函数中调用, 正常运行没有问题. 做完后想试试用外部中断调用是否可以. 于是用J25的引脚接...
  • 直接上干货,废话不多说。 下面是驱动程序 #include “gpio.h” ...//读出行扫描状态 Key_row[0] = HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_12)<<3; Key_row[0] = Key_row[0] | (HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1
  • STM32F103的4*4矩阵按键,调试通过

    千次阅读 2016-04-09 00:55:13
    STM32F103的4*4矩阵按键,调试通过。多个按键同时触发的时候,以最后一个释放的按键值为准。 4*4表盘的显示数据可以由大家自己修订。 矩阵按键扫描原理不再详述了。 下面附上代码,大家一同进步。
  • 软件:Keil5 功能:利用扫描法识别四乘四按键矩阵,当检测到有效按键时通过串口输出按键值 note:具有软件消抖以及长按无效功能(可取消)
  • STM32】4*4矩阵键盘扫描程序(扫描方式)

    千次阅读 热门讨论 2020-06-16 13:35:48
    能力有限,参照之前学的51单片机例程写了份简单粗暴型的按键扫描程序,如需在大项目中使用还是得用中断来处理比较好~ 矩阵键盘实物和原理图 图中厂家给的图应该标错了序号,从左到右是S1-S4、S5-S8、S9-S12、S13-...
  • STM32】4*4矩阵键盘扫描程序(中断方式)

    千次阅读 热门讨论 2020-08-12 21:49:55
    总体思路:中断线为4行连接的GPIO口,先初始化矩阵的4行输出低电平4列输出高电平,当有按键按下时的上升沿触发中断;然后在相应的中断处理函数里面采取查询的方式(参考上篇)获得键值。 部分程序 void EXTI9_5_...
  • 本文实现的代码是基于STM32HAL库的基础上的,不过标准库也可以用,只是调用的库函数不同,逻辑跟配置是一样的,按我这里的逻辑来配置即可。 1、键盘原理图: 原理举例:先把 F0-F7 内部拉高,这样这个8个引脚都是高...
  • 功能:12个按键输入 矩阵扫描 使用阿波罗F429开发板 亲测可用 --------------------------------------------------------分割线,第一次发帖----------------------------------------------------------- 以下...
  • STM32学习——矩阵键盘

    万次阅读 多人点赞 2018-11-11 17:26:48
    逐行扫描:通过高四位轮流输出低电平来对矩阵键盘进行逐行扫描,当低四位接收到的数据不全为1的时候,说明有按键按下,然后通过接收到的数据是哪一位为0来判断是哪一个按键被按下。 方法二: 行列扫描:通过高四位...
  • 基于STM32 4x4键盘扫描 小白接触ARM快两周了,开发板上4个按键已经不能满足学习需要。开发板上按键都是一个按键对应一个IO口,大量浪费IO口资源,那需要很多很多按键怎么办呢,难道没有什么方法解决吗??有,当然...
  • 矩阵键盘 在其中3列加上低电平,第x列加上高电平,当检测到第y行出现低电平,说明x行y列有按键按下 执行上述步骤四次,就可以准确知道那个键位按下 中断原理 行的GPIO设置输入,上拉(不输入时默认高电平) ...
  • 矩阵按键的两种扫描方法

    千次阅读 2018-07-28 19:37:11
    掌握两种按键扫描方法:行扫描,行列扫描(高低电平翻转)。 2.实验流程图 3.代码分析 (1)行扫描   #include "stm32f10x.h" u16 keyz=0; u8 a[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,...

空空如也

空空如也

1 2 3
收藏数 44
精华内容 17
关键字:

stm32矩阵按键扫描