说明:上一篇做了LED点亮实验,本篇实验做按键控制LED亮灭。
一、原理图分析
本次实验用到的开发板是野火的指南者STM32F103VET6。按键原理图如下:
由上图可知,按键K1,K2按下时,接3.3V,引脚为高电平,按键未按下时,引脚接地,为低电平;且硬件加了电容,所有不用软件消抖。
二、STM32CubeMX配置
(一)芯片选型及调试模式
同样的选芯片步骤,不做过多赘述,直接上图:
(二)时钟配置
使能HSE,配置系统时钟为72Mhz(配置频率越高,能耗越高,可自行查阅数据手册配置)。
后续实验延用以上配置,将不再重复。
(三)GPIO配置
此时将PA0配置为输入模式GPIO_Input,将PB5配置为输出模式GPIO_Output。
在GPIO中配置详细设置。
GPIO mode:GPIO为输入模式Input mode,目的是读取引脚高低电平。
GPIO Pull-up/Pull-down:上拉、下拉或浮空(即无上下拉),对于按键检测,一般选用浮空输入(no pull-up and no pull-down)。
浮空输入:此时在没有外部电路接入的时候IO浮空,电平是一个不确定的浮动值,外部给高电平则引脚读到的为高电平,外部给低电平则引脚读到的为低电平。
上拉输入:外部无信号输入时,VDD开关闭合,引脚读到的是一个固定的高电平值。当外部给低电平时,读到的是低电平;外部是高电平读到的也是高电平的值,故无法区分外部是否有高电平输入信号。
上拉输入:同理,外部无信号输入时,VSS开关闭合,引脚读到的是一个固定的低电平值。当外部给高电平时,读到的是高电平;外部是低电平读到的也是低电平的值,故无法区分外部是否有低电平输入信号。
User Label:用户标签,我们将按键命名为K1。
对于PB5的配置上一篇已经讲过,不再赘述,直接生成代码。
三、代码解析
(一)GPIO初始化函数
这里配置了GPIO的属性,该函数会在主函数中优先执行,值得一提的是HAL_GPIO_WritePin()函数,该函数用于配置引脚的高低电平,HAL_GPIO_WritePin(LED_R_GPIO_Port, LED_R_Pin, GPIO_PIN_SET)的意思是将LED_R(PB5)初始化为高电平。
void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(LED_R_GPIO_Port, LED_R_Pin, GPIO_PIN_SET);
/*Configure GPIO pin : PtPin */
GPIO_InitStruct.Pin = K1_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(K1_GPIO_Port, &GPIO_InitStruct);
/*Configure GPIO pin : PtPin */
GPIO_InitStruct.Pin = LED_R_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(LED_R_GPIO_Port, &GPIO_InitStruct);
}
我们还可以在gpio.h中定义一些宏用来增加程序可读性。HAL_GPIO_TogglePin()函数用于翻转引脚高低电平,此处用来控制LED的亮灭。
/* USER CODE BEGIN Private defines */
#define RED_ON HAL_GPIO_WritePin(GPIOB, LED_R_Pin, GPIO_PIN_RESET)
#define RED_OFF HAL_GPIO_WritePin(GPIOB, LED_R_Pin, GPIO_PIN_SET)
#define RED_TOGGLE HAL_GPIO_TogglePin(GPIOB,LED_R_Pin)
#define KEY_ON 1 //按键按下时为高电平
#define KEY_OFF 0 //按键未按下时为低电平
/* USER CODE END Private defines */
(二)主函数
我们在main.c的while循环中实现代码,在该代码中,我们用HAL_GPIO_ReadPin()函数来读取引脚的高低电平,如果为高电平则进入检测,直到按键抬起时翻转LED,以达到按键控制LED亮灭的目的。
while (1)
{
/* USER CODE END WHILE */
if(HAL_GPIO_ReadPin(K1_GPIO_Port,K1_Pin)==KEY_ON) //检测到按键被按下
{
while(HAL_GPIO_ReadPin(K1_GPIO_Port,K1_Pin)==KEY_ON); //按键未抬起时一直循环,直到松开才翻转LED
RED_TOGGLE; //翻转LED_R
}
/* USER CODE BEGIN 3 */
}
该实验中,硬件加了电容消抖,若没有硬件消抖,则需要软件消抖,用HAL_Delay函数待键稳定后再检测即可。
while (1)
{
/* USER CODE END WHILE */
if(HAL_GPIO_ReadPin(K1_GPIO_Port,K1_Pin)==KEY_ON) //检测到按键被按下
{
HAL_Delay(20); //延时检测
while(HAL_GPIO_ReadPin(K1_GPIO_Port,K1_Pin)==KEY_ON); //按键未抬起时一直循环,直到松开才翻转LED
RED_TOGGLE; //翻转LED_R
}
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}