GPIO学习是嵌入式系统应用的基础,本文将继续学习GPIO及其应用之按键输入,以及GPIO输入输出综合应用之由按键控制蜂鸣器发声。 | |
| GPIO_PinState HAL_GPIO_ReadPin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin) |
| |
| GPIOx:x可以是A-I中的一个,用来选择 GPIO 外设 |
| GPIO_Pin:指定读取的端口管脚,取值参阅表5-2 |
| |
| GPIO_PinState:管脚电平状态,取值GPIO_PIN_RESET或GPIO_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);
HAL库并没有提供访问GPIO端口输入数据寄存器的库函数,所以如果程序中需要批量读取端口管脚状态,可以采用直接访问端口输入数据寄存器GPIOx_IDR的方式来完成。/* Read the level status of all pins of GPIOA port */
uint16_t ReadValue;
ReadValue = GPIOA->IDR;
| |
| HAL_StatusTypeDef HAL_GPIO_LockPin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin) |
| |
| GPIOx:x可以是A-I中的一个,用来选择 GPIO 外设 |
| GPIO_Pin:指定读取的端口管脚,取值参阅表5-2 |
| |
| HAL_StatusTypeDef:枚举数据类型,返回函数执行状态 |
HAL_StatusTypeDef为枚举数据类型,定义于stm32f4xx_hal_def.h文件当中,表示函数执行的状态,取值见表3所示。需要注意的是HAL_GPIO_LockPin()函数用于锁存管脚的配置信息,而非引脚的电平状态,实际应用中该函数较少使用。已知开发板按键电路和蜂鸣器电路如图1所示,开发板设置了一个独立按键/矩阵键盘切换电路,由于本实验只需要使用两个按键,所以选择独立按键,即需要将P8的跳线开关的2、3引脚短接。图1(b)为蜂鸣器电路,蜂鸣器是单片机系统常用的声音输出器件,常用于报警信号输出。蜂鸣器存在有源和无源之分,有源蜂鸣器内置振荡电路,加电源就可以正常发声,通常频率固定。无源蜂鸣器则需要通过外部的正弦或方波信号驱动,控制稍微复杂一些,但是可以发出不同频率的声响,编写程序还可以演绎一些音乐曲目。开发板选择的是无源蜂鸣器,需要编写控制程序输出方波信号。通常按键所用的开关都是机械弹性开关,当机械触点断开、闭合时,由于机械触点的弹性作用,一个按键开关在闭合时不会马上就稳定接通,在断开时也不会一下子彻底断开,而是在闭合和断开的瞬间伴随了一连串的抖动,如图2所示。按键稳定闭合时间长短是由操作人员决定的,通常都会在100ms以上,刻意快速按能达到40~50ms,很难再低了。抖动时间是由按键的机械特性决定的,一般都会在10ms以内,为了确保程序对按键的一次闭合或者一次断开只响应一次,必须进行按键的消抖处理。当检测到按键状态变化时,不是立即去响应动作,而是先等待闭合或断开稳定后再进行处理。按键消抖可分为硬件消抖和软件消抖。硬件消抖就是在按键两端并联一个电容,利用电容的充放电特性对抖动过程中产生的电压毛刺进行平滑处理,从而实现消抖。但实际应用中,这种方式的效果往往不是很好,而且还增加了成本和电路复杂度,所以实际中的应用并不多。在绝大多数情况下是用软件即程序来实现消抖的。最简单的消抖原理就是当检测到按键状态变化后,先等待10ms左右,让抖动消失后再进行一次按键状态检测,如果与刚才检测到的状态相同,则可以确认按键已经稳定动作,并转到相应响应程序执行。后续给出的项目实例就是采用软件延时方式实现按键消抖处理的。本节设计一个输入输出的综合项目实例,使用输入按键选择蜂鸣器发出不同报警声,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步:打开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文件,在程序沙箱4(USER 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程序沙箱内编写程序循环检测按键,根据键值调用函数发出相应报警声音。程序实现原理较为简单,依次读取K1和K2按键电平状态,低电平则软件延时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步:编译工程,直到没有错误为止,下载程序到开发板,复位运行,检查实验效果。STM32项目实例:按键输入与蜂鸣器.docx