stm32矩阵按键状态机(可快速移植)

这篇具有很好参考价值的文章主要介绍了stm32矩阵按键状态机(可快速移植)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。


首先声明,所写内容是协会成员集体成果。其中过程艰难坎坷,寻找过大量资料,失败过无数次,最终成功运行。其中仍有不足,欢迎大佬批评指正!


目录

一、扫描按键思路

二、状态机思路

三、代码部分

四、小结

 


一、扫描按键思路

1.原理图

stm32状态机,stm32学习,单片机,stm32

 2.使用引脚的选择

IO口的选择很重要,一定要选没有被复用的空闲端口,以及最好是连在一起的GPIO口,首先被复用的话就直接无法正常输入输出,也就无法编程;

连在一起是因为4*4矩阵键盘需要8个引脚,用库函数操作太麻烦了,所以我们直接采用寄存器操作,连在一起的话寄存器比较容易控制(其实我们也尝试过不连在一起,但由于寄存器方面知识学的不太好,怎么也实现不了,希望有大佬指点)

3.原理讲解

stm32状态机,stm32学习,单片机,stm32 

我们使用的方法是逐行扫描,读取列的电平来判断键值

  1. 首先,将PB8到PB11全部输出为高电平,如果,PB12到PB15不为0,则,有键按下。
  2. 然后,进行逐行检测,即将P8到P11依次置高,读取PB12到PB15的值,判断具体为哪个键被按下

其中PB12到PB15一直为下拉输入模式,用于读取按键变化

二、状态机思路

状态机我们先配置一个定时器,如TIM2,用于每10ms进入中断扫描一次按键,正好跳过抖动

然后状态设为3个,分别是:

 状态一:KEY_Up ,空闲状态检测是否有按键按下

 状态二:KEY_Rowscan,逐行检测判断具体哪个键按下

 状态三:KEY_Wait,等待松手返回状态一

stm32状态机,stm32学习,单片机,stm32

 如果对状态机还有疑问,可参考这位大佬的:

https://blog.csdn.net/xdedmbb/article/details/129738797?app_version=5.15.0&code=app_1562916241&csdn_share_tail=%7B%22type%22%3A%22blog%22%2C%22rType%22%3A%22article%22%2C%22rId%22%3A%22129738797%22%2C%22source%22%3A%22xdedmbb%22%7D&uLinkId=usr1mkqgl919blen&utm_source=app

三、代码部分


定时器部分需自己配,这里只展示按键部分和main.c


1.Matrix_Key.h

/**
  ******************************************************************************
  * @file    Matrix_Key.h
  * @author  22级电子协会全体成员
  * @version V1.0
  * @date    18-March-2023
  * @brief   This file contains all the functions prototypes for the KEY 
  *          firmware library.
  ******************************************************************************
  * @attention
  *
  * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
  * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
  * TIME. AS A RESULT, XuQQ SHALL NOT BE HELD LIABLE FOR ANY DIRECT, INDIRECT
  * OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE CONTENT
  * OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING INFORMATION
  * CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
  *
  * <h2><center>&copy; COPYRIGHT 2022 XuQQ</center></h2>
  ******************************************************************************
  */

/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __MATRIX_KEY_H
#define __MATRIX_KEY_H

#ifdef __cplusplus
 extern "C" {
#endif

/* Includes ------------------------------------------------------------------*/
#include "stm32f10x.h"
#include "sys.h"



/** @defgroup KEY_Exported_Macros 宏定义
  * @{
  */
      #define KEY_Up         1  
      #define KEY_Rowscan    2
      #define KEY_Wait       3	 
      
      #define key_allput_High      GPIO_Write(GPIOB,(GPIOB_Out | 0x0f00))  //先让PB8到PB11全部输出高。 
      #define key_judge_have       (GPIOB_In) != 0x0000                      //如果,PB12到PB15不为0,则,有键按下
      
      #define First_rowscan        GPIO_Write(GPIOB,(GPIOB_Out | 0x0100))	//让PB11到PB8输出二进制的0001.
      #define Second_rowscan       GPIO_Write(GPIOB,(GPIOB_Out | 0x0200))	//让PB11到PB8输出二进制的0010.
      #define Third_rowscan        GPIO_Write(GPIOB,(GPIOB_Out | 0x0400))	//让PB11到PB8输出二进制的0100.
      #define Fourth_rowscan       GPIO_Write(GPIOB,(GPIOB_Out | 0x0800))	//让PB11到PB8输出二进制的1000.
      
      #define key_row_down         (GPIOB_In) > 0x0000                   //单行 有按键按下
      #define key_row_up           (GPIOB_In) == 0x0000                   //松手
      
      #define GPIOB_Out            GPIOB->ODR & 0xf0ff
      #define GPIOB_In             GPIOB->IDR & 0xf000

      #define FALSE 0
      #define TRUE 1 
/**
  * @}
  */
 

void Key_GPIO_Init(void);//IO初始化

void KEY_Scan(void);  //按键扫描函数		


#ifdef __cplusplus
}
#endif

#endif /* __KEY_H */

/******************* (C) COPYRIGHT 2022 XuQQ *****END OF FILE****/

2.Matrix_Key.c

/**
  ******************************************************************************
  * @file    Matrix_Key.c
  * @author  22级电子协会全体成员
  * @version V1.0
  * @date    18-March-2023
  * @brief   This file provides all the KEY firmware functions.
  ******************************************************************************
  * @attention
  *
  * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
  * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
  * TIME. AS A RESULT, XuQQ SHALL NOT BE HELD LIABLE FOR ANY DIRECT, INDIRECT
  * OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE CONTENT
  * OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING INFORMATION
  * CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
  *
  * <h2><center>&copy; COPYRIGHT 2022 XuQQ/center></h2>
  ******************************************************************************
  */

/* Includes ------------------------------------------------------------------*/
#include "Matrix_Key.h"
#include "delay.h"

/**
  * @brief  void KEY_Init(void);  // 初始化程序
	* @note   初始化程序 
  * @param  None
  * @retval None
  */


//4*4矩阵键盘 已经在STM32F103测试通过。
//2013-08-02 BY hjlmgc
///
//GPIO的硬件分配:
//第0行:PB8  ----|------|------|------|
//第1行:PB9  ----|------|------|------|
//第2行:PB10 ----|------|------|------|
//第3行:PB11 ----|------|------|------|
//              PB12   PB13   PB14   PB15
//             第0列   第1列  第2列  第3列  
/
//键值:
//1----2----3----C
//4----5----6----D
//7----8----9----E
//A----0----B----F 
/
#define KEY_WAY_1 //第一种方法
//
//KEY_WAY_1的GPIO初始化
//
void Key_GPIO_Init(void)
{
#ifdef KEY_WAY_1
	GPIO_InitTypeDef  GPIO_InitStructure;
 	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);	 //使能PB端口时钟
		
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11;	
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 		 //PB8-PB11推挽输出
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;		 //IO口速度为50MHz
	GPIO_Init(GPIOB, &GPIO_InitStructure);					 //根据设定参数初始化GPIOB
	
	GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;              
  	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;	//PB12-15 下拉输入
  	GPIO_Init(GPIOB, &GPIO_InitStructure);
#endif	
}

//初始状态4列全部置0,逐行检测
///

u8 key_return=10;

void KEY_Scan(void)
{
#ifdef KEY_WAY_1
  
  static u8 key_state=KEY_Up;
  static u8 KEY_flag=FALSE;
  int KeyVal=-1;	 //keyVal为按键数值 
  
  switch(key_state)
  {
/********************状态1:KEY_Up*********************/ 
	  case KEY_Up:
    { 
      key_allput_High;//先让PB8到PB11全部输出高。
      if(key_judge_have)//如果,PB12到PB15不为0,则,有键按下
        key_state = KEY_Rowscan;//判断是否抖动
    }
    break;
    
/********************状态2:KEY_Rowscan*********************/
    case KEY_Rowscan:
    {
      if(KEY_flag==FALSE)
      {
        //扫描第一行
        First_rowscan;
        if(key_row_down)
        {
          switch(GPIOB_In)	 //对PB15到PB12的值进行判断,以输出不同的键值。
          {
            case 0x1000: KeyVal=1;KEY_flag=TRUE;	break;
            case 0x2000: KeyVal=2;KEY_flag=TRUE;	break;
            case 0x4000: KeyVal=3;KEY_flag=TRUE;	break;
            case 0x8000: KeyVal='C';KEY_flag=TRUE;	break;
            default: break;
          }
//          key_state = KEY_Wait;
          
        }
      } 
      
      if(KEY_flag==FALSE)
      {
        //扫描第二行
        Second_rowscan;
        if(key_row_down)
        {
          switch(GPIOB_In)	 //对PB15到PB12的值进行判断,以输出不同的键值。
          {
            case 0x1000: KeyVal=4;KEY_flag=TRUE;	break;
            case 0x2000: KeyVal=5;KEY_flag=TRUE;	break;
            case 0x4000: KeyVal=6;KEY_flag=TRUE;	break;
            case 0x8000: KeyVal='D';KEY_flag=TRUE;	break;
            default: break;
          }
//          key_state = KEY_Wait;
          
        } 
      }
      
      if(KEY_flag==FALSE)
      {  
        //扫描第三行
        Third_rowscan;
        if(key_row_down)
        {
          switch(GPIOB->IDR & 0xf000)	  //对PB15到PB12的值进行判断,以输出不同的键值。
          {
            case 0x1000: KeyVal=7;KEY_flag=TRUE;	break;
            case 0x2000: KeyVal=8;KEY_flag=TRUE;	break;
            case 0x4000: KeyVal=9;KEY_flag=TRUE;	break;
            case 0x8000: KeyVal='E';KEY_flag=TRUE;	break;
            default: break;
          }
//          key_state = KEY_Wait;
          
        } 
      }
      
      if(KEY_flag==FALSE)
      {
        //扫描第四行
        Fourth_rowscan;
        if(key_row_down)
        {
          switch(GPIOB->IDR & 0xf000)	  //对PB15到PB12的值进行判断,以输出不同的键值。
          {
            case 0x1000: KeyVal='A';KEY_flag=TRUE;	break;
            case 0x2000: KeyVal=0;KEY_flag=TRUE;	break;
            case 0x4000: KeyVal='B';KEY_flag=TRUE;	break;
            case 0x8000: KeyVal='F';KEY_flag=TRUE;	break;
            default: break;
          }
//          key_state = KEY_Wait;
          
        } 
      }
      
      if(KEY_flag==TRUE)
        key_state = KEY_Wait;
    }
	  break;
  
/********************状态3:KEY_Wait*********************/
    case KEY_Wait:
    {
      if(key_row_up)
      {
        key_state = KEY_Up;//完成一次按键动作,切换到状态1
      }
 
    }
    break;
    
  }
  
  if(KEY_flag == TRUE)
  {
     key_return = KeyVal;
     
     KEY_flag = FALSE;
  }

#endif
}


/******************* (C) COPYRIGHT 2022 XUQQ *****END OF FILE****/

3.main.c

/**
  ******************************************************************************
  * @file    main.c 
  * @author  22级电子协会全体成员
  * @version V3.5.0
  * @date    18-March-2023
  * @brief   Main program body.
  *              (01)初始化按键;
  *              (02)按下按键控制相应的LED灯亮
  *              
  ******************************************************************************
  * @attention
  *
  * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
  * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
  * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
  * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
  * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
  * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
  *
  * <h2><center>&copy; COPYRIGHT 2011 XuQQ</center></h2>
  ******************************************************************************
  */ 

/* Includes ----------------------------------库文件--------------------------*/
#include "stm32f10x.h"
#include "bmp.h"

/** @addtogroup STM32F10x_StdPeriph_Examples
  * @{
  */


/* Private typedef --------------------------变量类型重新定义-----------------*/
/* Private define ---------------------------私有定义-------------------------*/
/* Private macro ----------------------------私有宏定义-----------------------*/
/* Private variables ------------------------私有变量-------------------------*/
/* Private function prototypes --------------私有函数属性---------------------*/
#ifdef __GNUC__
/* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf
   set to 'Yes') calls __io_putchar() */
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif /* __GNUC__ */

/* Private functions ------------------------私有函数-------------------------*/

/**
  * @brief  Main program.
  * @note   
  * @param  None
  * @retval None
  */
int main(void)
{
  LED_Init();
  Key_GPIO_Init();
  KEY_Scan();
  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
  TIM2_Int_Init(19, 7199);//定时2ms进一次中断
	while(1)
	{
    if(key_return==1)
    {
      PAout(0)=!PAout(0);//LED0取反
      key_return=10;
    }
    if(key_return==2)
    {
      PAout(1)=!PAout(1);//LED1取反
      key_return=10;
    }
    if(key_return==4)
    {
      PAout(0)=!PAout(0);//LED0取反
      key_return=10;
    }
    if(key_return==7)
    {
      PAout(1)=!PAout(1);//LED1取反
      key_return=10;
    }
    if(key_return==0)
    {
      PAout(0)=!PAout(0);//LED0取反
      key_return=10;
    }
	}

}

#ifdef  USE_FULL_ASSERT

/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t* file, uint32_t line)
{ 
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */

  /* Infinite loop */
  while (1)
  {
		
  }
}


#endif

/**
  * @}
  */

/**
  * @}
  */


/******************* (C) COPYRIGHT 2011 XuQQ *****END OF FILE****/

四、小结

 写完了,还是有一些瑕疵,但还是希望能对你有所帮助,欢迎大佬批评指正!

视频效果:stm32矩阵按键状态机效果_哔哩哔哩_bilibili文章来源地址https://www.toymoban.com/news/detail-671254.html

到了这里,关于stm32矩阵按键状态机(可快速移植)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • FreeRTOS_Stm32F103系列单片机标准库移植

    链接:FreeRTOS 下面的教程是基于从github下载压缩包进行的,最好下载这个或者直接看3.1,从我百度网盘下载。如果是别的下载源也问题不大,大同小异。 此时我们需要下载以下两个仓库, 点进去按下面的步骤下载就行了,另一个也是这样下。 链接: FreeRTOS官网 打开链接我们

    2024年01月22日
    浏览(53)
  • POWERLINK协议在stm32单片机+w5500移植成功经验分享

    连续折腾了多个晚上,又趁周末又花了一天时间,终于把powerlink协议移植成功到单片机上啦。本想放弃,但想了下不管我能不能用上,结个尾吧,分享给有需要的人。放弃并不难,但坚持一定很酷。为了移植测试这个协议花了不少血本。stm32开发板就买了两套,其中第一套板

    2024年02月09日
    浏览(60)
  • STM32--按键矩阵--扫描法

    按键矩阵其实是通过八根引脚来检测按下按键,常规按键一个按键对应一个引脚口的输入,而按键矩阵通过8根引脚,4根为输入模块,4根为输出模式,输出模块式依次输出,输入模式依次扫描,从而确定按键矩阵按下的按键所处位置,从而节省引脚资源的使用,理论上来说按

    2024年02月11日
    浏览(45)
  • 蓝桥杯单片机比赛学习:3、独立按键与矩阵按键的基本原理

    首先我们看一下按键的原理图,如图1,当J5中的2,3接在一起的时候,红线标注就是一个完整的电路图,此时只有s4、s5、s6、s7按键可以使用,也就是独立按键。例如:当我们按下s4时, 电路导通,P33引脚被拉为低电平0 ,此时我们读取P33引脚电平的高低就能判断出哪个按键被按

    2024年02月06日
    浏览(52)
  • 51单片机——矩阵按键实验,小白讲解,相互学习

    矩阵按键介绍:         独立按键与单片机连接时,每一个按键都需要单片机的一个I/O 口,若某单片机系统需较多按键,如果用独立按键便会占用过多的I/O 口资源.单片机系统中I/O 口资源往往比较宝贵,当用到多个按键时为了减少I/O 口引脚,引入了矩阵按键。       

    2024年02月12日
    浏览(50)
  • STM32矩形(矩阵)按键(键盘)输入控制LED灯 ——4*4矩阵按键源码解析

    本文基于标准函数库的工程实现stm32F103C8T6使用4*4的矩阵按键控制LED灯的亮灭及闪烁等功能。 程序源码:链接:https://pan.baidu.com/s/1_MPhvMduKCTP0MPG-Gtw3A?pwd=2syk  提取码:2syk 文章目录 一、矩形键盘介绍 1、硬件电路基本原理 2、两种识别方法介绍 3、硬件接线即使用 二、程序源码

    2024年02月04日
    浏览(47)
  • 【快速入门 LVGL】-- 1、STM32 工程移植 LVGL

    目录 一、LVGL 简述 二、复制一个STM32工程 三、下载 LVGL 四、裁剪 源文件 五、工程添加 LVGL 文件  六、注册 显示 七、注册 触摸屏 八、LVGL 心跳、任务刷新 九、开跑 LVGL  十、控件的事件添加、响应处理 十 一、几个好玩小事情 十 二、显示中文 丰富且强大的模块化图形组

    2024年04月27日
    浏览(35)
  • 单片机学习-使用矩阵按键来显示数码管0-F

    1、行列扫码 //数码管字摸 u8 gsmg_code[17] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,                         0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};      //共阴 显示0-F 2、线翻转扫描

    2024年02月04日
    浏览(75)
  • STM32控制矩阵按键,HAL库,cubeMX配置

    我使用的是STM32F103RCT6这款单片机,HAL库,使用cubeMX配置。 使用矩阵按键实现功能的方法为轮询法 1.首先矩阵键盘原理图如下: 2.实物图 按照矩阵键盘接法,16个按键需要8个io口,我选择了PC口的0~7号引脚,前四个依次接矩阵键盘的行,后四个依次接矩阵键盘的列;矩阵键盘的

    2023年04月17日
    浏览(63)
  • 学习C51单片机——矩阵按键控制数码管显示数字(学习笔记Keil5)

    单片机检测矩阵按键是否被按下的依据是检测与该按键对应的 I/O 口是否为低电平

    2024年04月17日
    浏览(49)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包