此实验是通过STM32CubeMX来配置stm32实现按键输入,以此来了解stm32I/O的输入操作及如何使用HAL库来实现I/O输入。本实验中的按键操作使用的是软件中断,并未用到stm32的中断组,关于stm32的中断配置会在之后的实验中讲解。
【软件】STM32CubeMX+True Studio
【开发板】正点原子STM32F103ZET6精英板
【硬件资源】指示灯DS0、DS1;蜂鸣器;按键KEY0、KEY1、KEY_UP。
//精英板连接方式
DS0------------>PB5
DS1------------>PE5
BEEP----------->PB8
KEY0----------->PE4
KEY1----------->PE3
KEY_UP--------->PA0
按键消抖通常的按键所用开关为机械弹性开关,当机械触点断开、闭合时,由于机械触点的弹性作用,一个按键开关在闭合时不会马上稳定地接通,在断开时也不会一下子断开。因而在闭合及断开的瞬间均伴随有一连串的抖动,为了不产生这种现象而作的措施就是按键消抖。在机械按键的触点闭合和断开时,都会产生抖动,为了保证系统能正确识别按键的开关,就必须对按键的抖动进行处理。按键的抖动对于人类来说是感觉不到的,但对单片机来说,则是完全可以感应到的,而且还是一个很“漫长”的过程,因为单片机处理的速度在“微秒”级,而按键抖动的时间至少在“毫秒”级。单片机如果在触点抖动期间检测按键的通断状态,则可能导致判断出错,即按键一次按下或释放被错误地认为是多次操作,从而引起误处理。因此,为了确保单片机对一次按键动作只作—次响应,就必须考虑如何消除按键抖动的影响。
消抖,就是要我们通过软件或者硬件来消除按键稳定前后的前沿抖动和后沿抖动,使CPU跳过抖动时间,获取按键稳定时的有效信号。
【消抖方法】
分为硬件消抖和软件消抖,一般采用软件消抖,然而软件消抖又分为多种,这里我们采用延时来进行按键消抖,大体思路就是在捕获按键信号前加一个延时,使CPU在前沿抖动的时间里空转,延时过后,CPU刚好能捕获按键稳定时的有效信号。具体的消抖方法还有很多,可参考下面这篇博文:
https://blog.csdn.net/elikang/article/details/77053845
新建一个STM32CubeMX工程文件,然后先进行系统配置:
时钟选择外部高速时钟,72MHz,APB1采用2分频
配置完成,保存生成工程文件,然后用编译器打开工程文件(笔者采用True Studio编译器)
/*
* key.h
*
* Created on: Apr 11, 2020
* Author: 13257
*/
#ifndef KEY_H_
#define KEY_H_
#include "main.h"
#define KEY0 HAL_GPIO_ReadPin(KEY0_GPIO_Port,KEY0_Pin) //读取按键0
#define KEY1 HAL_GPIO_ReadPin(KEY1_GPIO_Port,KEY1_Pin) //读取按键1
#define WK_UP HAL_GPIO_ReadPin(WK_UP_GPIO_Port,WK_UP_Pin) //读取按键WK_UP
#define KEY0_PRES 1 //KEY0按下
#define KEY1_PRES 2 //KEY1按下
#define WKUP_PRES 3 //WKUP按下
uint8_t KEY_Scan(uint8_t);//按键扫描
#endif /* KEY_H_ */
/*
* key.c
*
* Created on: Apr 11, 2020
* Author: 13257
*/
#include "key.h"
//按键处理函数
//软件方式实现按键中断
//返回按键值
//mode:0,不支持连续按;1,支持连续按;
//0,没有任何按键按下
//1,KEY0按下
//2,KEY1按下
//3,KEY3按下 WK_UP
//注意此函数有响应优先级,KEY0>KEY1>KEY_UP!!
uint8_t KEY_Scan(uint8_t mode)
{
static uint8_t key_up=1;//按键按松开标志
if(mode)key_up=1; //支持连按
if(key_up&&(KEY0==0||KEY1==0||WK_UP==1))
{
HAL_Delay(10);//去抖动
key_up=0;
if(KEY0==0)return KEY0_PRES;
else if(KEY1==0)return KEY1_PRES;
else if(WK_UP==1)return WKUP_PRES;
}else if(KEY0==1&&KEY1==1&&WK_UP==0)key_up=1;
return 0;// 无按键按下
}
int main(void)
{
/* USER CODE BEGIN 1 */
uint8_t key = 0;
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
/* USER CODE BEGIN 2 */
HAL_GPIO_WritePin(LED0_GPIO_Port, LED0_Pin, GPIO_PIN_RESET);//将LED0置0,点亮LED0
HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, GPIO_PIN_SET); //将LED1置1,熄灭LED1
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
key = KEY_Scan(0);
if(key)
{
//利用switch判断来实现类似中断的效果
switch(key)
{
case WKUP_PRES:
HAL_GPIO_TogglePin(BEEP_GPIO_Port, BEEP_Pin);
break;
case KEY1_PRES:
HAL_GPIO_TogglePin(LED1_GPIO_Port, LED1_Pin);
break;
case KEY0_PRES:
HAL_GPIO_TogglePin(LED0_GPIO_Port, LED0_Pin);
HAL_GPIO_TogglePin(LED1_GPIO_Port, LED1_Pin);
break;
}
}
else HAL_Delay(10);
}
/* USER CODE END 3 */
}
//调用的HAL库API
HAL_Delay(Delay);//HAL库自带的ms级延时
HAL_GPIO_ReadPin(GPIOx, GPIO_Pin);//读取IO
HAL_GPIO_TogglePin(GPIOx, GPIO_Pin);//翻转IO
HAL_GPIO_WritePin(GPIOx, GPIO_Pin, PinState);//写IO
本次实验未涉及外部中断,较为简单,重点就是介绍一下按键消抖,在今后的应用中一定要注意这个问题,以防没有进行按键消抖而获取不稳定的信号输入,影响预期效果。下次将介绍串口通信,走进通信方式应用的大门。