首页 > 其他分享 >HAL库教程3:引脚输入检测

HAL库教程3:引脚输入检测

时间:2023-01-11 12:34:01浏览次数:36  
标签:教程 HAL PIN 引脚 KEY GPIO PRES define


使用CubeMX配置输入引脚

  本章我们要把按键作为输入源,使用单片机来检测引脚的电平状态。首先要查看原理图,按键与那些引脚相连。

HAL库教程3:引脚输入检测_STM32


  我使用的板子,按键K2 -K5分别对应PA4-PA7,且按键按下去以后,引脚接地。因此,我们要将单片机的PA4-PA7设置为上拉输入。

HAL库教程3:引脚输入检测_STM32_02

HAL库教程3:引脚输入检测_STM32_03

  点击生成代码并打开工程,可以看到STM32CubeMX配置好的引脚输入初始化代码如下(已省略部分无关代码):

//main.c
static void MX_GPIO_Init(void)
{
/*Configure GPIO pins : PA4 PA5 PA6 PA7 */
GPIO_InitStruct.Pin = GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_PULLUP;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}

按键的输入、消抖与松手检测

  按键检测可以调用库函数HAL_GPIO_ReadPin,也可以使用位带操作PAin(n)。其实,只需要一步跳转,就可以发现HAL_GPIO_ReadPin其实也是在调用IDR寄存器而已。

GPIO_PinState HAL_GPIO_ReadPin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
{
GPIO_PinState bitstatus;
/* Check the parameters */
assert_param(IS_GPIO_PIN(GPIO_Pin));
if((GPIOx->IDR & GPIO_Pin) != (uint32_t)GPIO_PIN_RESET)
{
bitstatus = GPIO_PIN_SET;
}
else
{
bitstatus = GPIO_PIN_RESET;
}
return bitstatus;
}

  为了提高程序的可读性,使用宏定义将按键与引脚关联起来。注意,代码只允许填写在USER CODE包含的区域,否则使用STM32CubeMX时,会删除区域外的代码。

//main.h
/* USER CODE BEGIN EM */
#define LED1 PCout(10)
#define LED2 PCout(11)
#define KEY_D HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_4)
#define KEY_C HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_5)
#define KEY_B HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_6)
#define KEY_A HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_7)
/* USER CODE END EM */

  在主函数的死循环中,可以编写代码来获取引脚的电平状态,并且用LED作为状态指示。注意要带松手检测。

//main.c main()
while (1)
{
if(0 == KEY_A)
{
HAL_Delay(10);
while(!KEY_A)
;
LED1 = !LED1;
}
if(0 == KEY_B)
{
HAL_Delay(10);
while(!KEY_B)
;
LED2 = !LED2;
}
}

新增c文件与按键扫描函数

  我们接下来尝试编写一个按键扫描函数。然而,如果新增的函数都放在main.c,那么main.c会变得很臃肿,既不方便代码阅读,又不方便理清程序的分层与架构。一般情况下,不同的函数要放在不同的c文件中。

  接下来按照CubeMX生成的工程的架构,新建IO.c与IO.h文件。

HAL库教程3:引脚输入检测_HAL库_04


  将IO.c文件添加到工程中。

HAL库教程3:引脚输入检测_引脚_05


  头文件无需手动添加,只需在c文件中包含即可。我参照了正点原子的按键扫描函数,把按键扫描函数剪贴到IO.c中,并添加一些函数说明信息。

//IO.c
#include "IO.h"

/**
* @brief 按键扫描函数
* @param 模式,是否支持连按(长按)
* @retval 按下的键值
*/
u8 KEY_Scan(u8 mode)
{
static u8 key_up=1;//按键按松开标志
if(mode)key_up=1; //支持连按
if(key_up&&(KEY_A==0||KEY_B==0||KEY_C==0||KEY_D==0))
{
HAL_Delay(10);//去抖动
key_up=0;
if(KEY_A==0)return KEY_A_PRES;
else if(KEY_B==0)return KEY_B_PRES;
else if(KEY_C==0)return KEY_C_PRES;
else if(KEY_D==0)return KEY_D_PRES;
}else if(KEY_A==1&&KEY_B==1&&KEY_C==1&&KEY_D==1)key_up=1;
return 0;// 无按键按下
}

在IO.h中定义一些IO操作的宏定义

#ifndef __IO_H
#define __IO_H

#ifdef __cplusplus
extern "C" {
#endif
#include "main.h"

#define LED1 PCout(10)
#define LED2 PCout(11)
#define KEY_D HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_4)
#define KEY_C HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_5)
#define KEY_B HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_6)
#define KEY_A HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_7)

#define KEY_A_PRES 5
#define KEY_B_PRES 4
#define KEY_C_PRES 3
#define KEY_D_PRES 2

u8 KEY_Scan(u8 mode);

#ifdef __cplusplus
}
#endif

#endif

  在主函数死循环中,可以使用switch-case语法,把函数的返回值作为判断条件。

//main.c main()
while (1)
{
switch(KEY_Scan(0))
{
case KEY_A_PRES: LED1 = !LED1; break;
case KEY_B_PRES: LED2 = !LED2; break;
case KEY_C_PRES: LED1 = !LED2; break;
case KEY_D_PRES: LED2 = !LED1; break;
default: break;
}
}


标签:教程,HAL,PIN,引脚,KEY,GPIO,PRES,define
From: https://blog.51cto.com/u_12001544/6002128

相关文章

  • HAL库教程1:STM32Cube的介绍
      使用STM32HAL库已经有了一段时间,觉得相比于标准库,好用了不少。加上STM32CubeMX图形化配置工具的加持,个人认为可以极大提升开发效率。其实关于HAL库的教程已经很多了,关于......
  • HAL库教程7:STM32的时钟系统
      STM32的时钟系统比较复杂,不像51单片机,可能只有一个时钟。原因:1、外设多,不同的外设有不同的时钟要求;2、功耗原因,速度越快,功耗越大,抗电磁干扰能力越弱。此处以STM32F405......
  • HAL库教程4:外部中断
    外部中断机制  本章我们仍然是通过按键来控制LED,只不过实现方式由轮询变为了外部中断。为什么需要外部中断?为了给CPU减轻负担。  举个例子  比如你今天有个快递,快递......
  • HAL库教程8:通用定时器的使用
    定时器溢出时间的计算  关于定时器溢出的时间计算,有个公式:  定时器本质上是一个不断自加的计数器,只不过在自加的时候,能够自动比较计数值跟某个设定值而已。定时器+1用......
  • HAL库教程9:串口接收不定长数据
      串口收到的两组数据之间,往往会有一定的时间间隔。可以判断这个间隔,来实现无需结束符,无需指定长度,串口可接收不定长数据的功能。如果串口在一定的时间内没有收到新的数据......
  • HAL库教程11:定时器的缓冲功能与影子寄存器
      在STM32的定时器中,TIMx_PSC、TIM_ARR两个寄存器加上捕捉比较模块中TIMX_CCR寄存器,它们都可以动态修改。不过他们的修改和生效可能不在同一个时刻,或者说,修改过后立即生......
  • HAL库教程10:定时器的PWM模式应用
      本节通过定时器的PWM模式驱动无源蜂鸣器,来演奏一段音乐。本博客在掌机的系列教程中介绍过蜂鸣器的驱动原理,感兴趣的可以参考​​电子琴​​无源蜂鸣器驱动电路  蜂鸣......
  • 电子设计教程20:晶体管负反馈放大电路的参数设计
    放大倍数的推导  我们假设的电路在没有负反馈的时候,电路增益为A(也称为开环增益,或者裸增益,等于各极增益的乘积)。实际放大倍数A_v可以表示为:  这个公式可以推导出来,但推......
  • 电子设计教程18:射极跟随电路的参数设计
      射极跟随电路的原理图在上一节我们已经通过理论分析大致画了出来。接下来求从“设计的角度”出发,思考射极跟随电路的原理。不但需要计算各器件的参数,还要进行参数调试。......
  • 电子设计教程22:虚短与虚断
      “虚短”与“虚断”是非常重要的两个概念。在分析运放的输入信号与输出信号的关系时,这是两个基本的出发点。  当运放引入负反馈的时候,或者说工作在“线性区”的时候,......