STM32项目实例:按键输入与蜂鸣器

文摘   2024-09-13 07:03   河北  

GPIO学习是嵌入式系统应用的基础,本文将继续学习GPIO及其应用之按键输入,以及GPIO输入输出综合应用之由按键控制蜂鸣器发声。

1 GPIO输入库函数

1.1 函数HAL_GPIO_ReadPin

1描述了函数HAL_GPIO_ReadPin

1 HAL_GPIO_ReadPin

函数名

HAL_GPIO_ReadPin

函数原型

GPIO_PinState HAL_GPIO_ReadPin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)

功能描述

读取指定端口管脚的输入电平状态

输入参数1

GPIOxx可以是A-I中的一个,用来选择 GPIO 外设

输入参数2

GPIO_Pin:指定读取的端口管脚,取值参阅表5-2

输出参数

返回值

GPIO_PinState:管脚电平状态,取值GPIO_PIN_RESETGPIO_PIN_SET

例:

/* Reads the seventh pin of the GPIOB and store it in ReadValue variable */

uint8_t ReadValue;

ReadValue = HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_7);

1.2 入数据寄存器访问

HAL库并没有提供访问GPIO端口输入数据寄存器的库函数,所以如果程序中需要批量读取端口管脚状态,可以采用直接访问端口输入数据寄存器GPIOx_IDR的方式来完成。

例:

/* Read the level status of all pins of GPIOA port */

uint16_t ReadValue;

ReadValue = GPIOA->IDR;

1.3 函数HAL_GPIO_LockPin

2描述了函数HAL_GPIO_LockPin

2 HAL_GPIO_LockPin

函数名

HAL_GPIO_LockPin

函数原型

HAL_StatusTypeDef HAL_GPIO_LockPin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)

功能描述

锁定指定端口管脚的配置信息

输入参数1

GPIOxx可以是A-I中的一个,用来选择 GPIO 外设

输入参数2

GPIO_Pin:指定读取的端口管脚,取值参阅表5-2

输出参数

返回值

HAL_StatusTypeDef:枚举数据类型,返回函数执行状态

HAL_StatusTypeDef为枚举数据类型,定义于stm32f4xx_hal_def.h文件当中,表示函数执行的状态,取值见表3所示。

3 HAL_StatusTypeDef

名称

数值

名称

数值

HAL_OK

0x00U

HAL_BUSY

0x02U

HAL_ERROR

0x01U

HAL_TIMEOUT

0x03U

需要注意的是HAL_GPIO_LockPin()函数用于锁存管脚的配置信息,而非引脚的电平状态,实际应用中该函数较少使用。

2 独立按键控制蜂鸣器

2.1 电路原理

已知开发板按键电路和蜂鸣器电路如图1所示,开发板设置了一个独立按键/矩阵键盘切换电路,由于本实验只需要使用两个按键,所以选择独立按键,即需要将P8的跳线开关的23引脚短接。
 (a) 按键电路                          (b) 蜂鸣器电路

1 按键和蜂鸣器电路

1b)为蜂鸣器电路,蜂鸣器是单片机系统常用的声音输出器件,常用于报警信号输出。蜂鸣器存在有源和无源之分,有源蜂鸣器内置振荡电路,加电源就可以正常发声,通常频率固定。无源蜂鸣器则需要通过外部的正弦或方波信号驱动,控制稍微复杂一些,但是可以发出不同频率的声响,编写程序还可以演绎一些音乐曲目。开发板选择的是无源蜂鸣器,需要编写控制程序输出方波信号。

2.2 按键消抖

通常按键所用的开关都是机械弹性开关,当机械触点断开、闭合时,由于机械触点的弹性作用,一个按键开关在闭合时不会马上就稳定接通,在断开时也不会一下子彻底断开,而是在闭合和断开的瞬间伴随了一连串的抖动,如图2所示。

2 按键抖动状态图

按键稳定闭合时间长短是由操作人员决定的,通常都会在100ms以上,刻意快速按能达到40~50ms,很难再低了。抖动时间是由按键的机械特性决定的,一般都会在10ms以内,为了确保程序对按键的一次闭合或者一次断开只响应一次,必须进行按键的消抖处理。当检测到按键状态变化时,不是立即去响应动作,而是先等待闭合或断开稳定后再进行处理。按键消抖可分为硬件消抖和软件消抖。

硬件消抖就是在按键两端并联一个电容,利用电容的充放电特性对抖动过程中产生的电压毛刺进行平滑处理,从而实现消抖。但实际应用中,这种方式的效果往往不是很好,而且还增加了成本和电路复杂度,所以实际中的应用并不多。

在绝大多数情况下是用软件即程序来实现消抖的。最简单的消抖原理就是当检测到按键状态变化后,先等待10ms左右,让抖动消失后再进行一次按键状态检测,如果与刚才检测到的状态相同,则可以确认按键已经稳定动作,并转到相应响应程序执行。后续给出的项目实例就是采用软件延时方式实现按键消抖处理的。

2.3 项目实施

本节设计一个输入输出的综合项目实例,使用输入按键选择蜂鸣器发出不同报警声,K1键按下发出救护车报警声,K2键按下发出电动车报警声。项目具体实施步骤为:

1步:复制第3章创建的工程模板文件夹到桌面,并将文件夹重命名为0601 BeepKey

2步:打开工程模板文件夹里面的Template.ioc文件,启动CubeMX配置软件,首先在引脚视图下面将PE0~PE3设置为GPIO_Input模式,PC8设置为GPIO_Output模式,然后选择System Core类别下的GPIO子项,按键输入引脚PE0~PE3设置为上拉输入工作模式,并添加标签K1~K4;蜂鸣器控制引脚PC8设置为推挽、低速、无上拉/下拉、初始输出高电平,添加用户标签BP,配置结果如图3所示。时钟配置和工程配置选项无须修改,单击GENERATE CODE按钮生成初始化工程。
3 项目初始化配置

3步:打开MDK-RAM文件夹下面的工程文件Template.uvprojx,将生成工程编译一下,没有错误和警告,则开始用户程序编写。此时会发现工程创建了一个gpio.c文件,并将其添加到Application/User/Core项目组下面,生成的初始化程序就存放在该文件当中,部分代码如下

void MX_GPIO_Init(void)

{

GPIO_InitTypeDef GPIO_InitStruct = {0};

/* GPIO Ports Clock Enable */

__HAL_RCC_GPIOE_CLK_ENABLE();

__HAL_RCC_GPIOC_CLK_ENABLE();

__HAL_RCC_GPIOH_CLK_ENABLE();

__HAL_RCC_GPIOA_CLK_ENABLE();

/*Configure GPIO pin Output Level */

HAL_GPIO_WritePin(BP_GPIO_Port, BP_Pin, GPIO_PIN_RESET);

/*Configure GPIO pins : PEPin PEPin PEPin PEPin */

GPIO_InitStruct.Pin = K3_Pin|K4_Pin|K1_Pin|K2_Pin;

GPIO_InitStruct.Mode = GPIO_MODE_INPUT;

GPIO_InitStruct.Pull = GPIO_PULLUP;

HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);

/*Configure GPIO pin : PtPin */

GPIO_InitStruct.Pin = BP_Pin;

GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;

GPIO_InitStruct.Pull = GPIO_NOPULL;

GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;

HAL_GPIO_Init(BP_GPIO_Port, &GPIO_InitStruct);

}

上述代码和CubeMX配置选项是一一对应的,由于在CubeMX初始化配置时使用了标签,所以代码使用了宏定义K1_Pin替换GPIO_PIN_0,其他引脚对应关系依次类推,而相应的宏定义存放在main.h当中的,读者可以使用右键跟踪查看。

4步:打开main.c文件,在程序沙箱4USER CODE 4)内分别编写延时程序,救护车报警程序,电动报警程序,其参考代码如下:

/* USER CODE BEGIN 4 */

void delay(uint32_t i)    //软件延时

{

while(i--) ;

}

void sound1(void)      //救护车报警

{

uint32_t i=30000;

while(i)    //产生一段时间的PWM波,使蜂鸣器发声

{

HAL_GPIO_WritePin(GPIOC,BP_Pin,GPIO_PIN_RESET);  //IO口输出低电平

delay(i);

HAL_GPIO_WritePin(GPIOC,BP_Pin,GPIO_PIN_SET);    //IO口输出高电平

delay(i);

i=i-6;

}

}

void sound2(void)         //电动车报警

{

uint32_t i=6000;

while(i)    //产生一段时间的PWM波,使蜂鸣器发声

{

HAL_GPIO_WritePin(GPIOC,BP_Pin,GPIO_PIN_RESET);   //IO口输出低电平

delay(i);

HAL_GPIO_WritePin(GPIOC,BP_Pin,GPIO_PIN_SET);     //IO口输出高电平

delay(i);

i=i-6;

}  

}

/* USER CODE END 4 */

编写完上述3个函数之后,还需要将其声明在文件上方的私有函数声明程序沙箱内,参考代码如下:

/* USER CODE BEGIN PFP */

void delay(uint32_t i);

void sound1(void);

void sound2(void);

/* USER CODE END PFP */

在主程序的while程序沙箱内编写程序循环检测按键,根据键值调用函数发出相应报警声音。程序实现原理较为简单,依次读取K1K2按键电平状态,低电平则软件延时10ms,再次检测引脚电平,依然为低电平则认为按键已稳定按下,调用发声程序输出报警信息,发声完成再次检测按键,如此往复。参考代码如下:

/* USER CODE BEGIN WHILE */

while (1)

{

if(HAL_GPIO_ReadPin(GPIOE,K1_Pin)==GPIO_PIN_RESET)

{

HAL_Delay(10);   //延时消抖

if(HAL_GPIO_ReadPin(GPIOE,K1_Pin)==GPIO_PIN_RESET)

sound1();     //救护车报警声音

}

if(HAL_GPIO_ReadPin(GPIOE,K2_Pin)==GPIO_PIN_RESET)

{

HAL_Delay(10);   //延时消抖

if(HAL_GPIO_ReadPin(GPIOE,K2_Pin)==GPIO_PIN_RESET)

sound2();     //救护车报警声音

}

/* USER CODE END WHILE */

}

5步:编译工程,直到没有错误为止,下载程序到开发板,复位运行,检查实验效果。

3 使用教材
4 教程可复制文件下载

STM32项目实例:按键输入与蜂鸣器.docx


人工智能科学与技术
分享教学成果 | 传播前沿科技| 推荐优秀图书
 最新文章