文章目录
- 前言
- 一、原理图查看
- 二、cubeMX配置
- 三、代码讲解(使用按键控制LED灯的开关)
- 四、HAL_Delay的内部实现
- 五.遗留的问题
- 总结
前言
点完灯后接下来我们就开始按键的学习了,这也是很简单的,大家不用担心。
一、原理图查看
可以看到板子上面是有4个按键的,分别是PB0-PB3还有一个PA0。
从原理图我们可以得知按键没有按下时这些引脚都是高电平状态,当我们按下按键时电路导通,这些引脚就都输出低电平了。
二、cubeMX配置
基础配置在这里我就不多讲了,这里直接配置一下按键。
下面配置板子上面的4个按键,这里直接默认设置即可,通过上面的原理图可以看见按键是接了一个上拉的10K电阻,所以当按键没有按下的时候为高电平,当按键按下的时候为低电平。
三、代码讲解(使用按键控制LED灯的开关)
前面的文章我们已经实现了LED的点亮了,这篇文章就带大家实现一下按键点亮LED的功能。
按键程序注意事项:
当机械触点断开、闭合时,由于机械触点的弹性作用,一个按键开关在闭合时不会马上稳定地接通,在断开时也不会一下子断开。因而在闭合及断开的瞬间均伴随有一连串的抖动,为了不产生这种现象而作的措施就是按键消抖。
由下面的图片可以知道按键抖动会持续一段时间,一般按键抖动的时间都在5ms-10ms之间,我们只需要在按下后延时一段时间再去读取按键值即可消除抖动。
读取GPIO电平函数
HAL_GPIO_ReadPin();
按键控制LED实现:
if(0 == HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0))
{
HAL_Delay(10);
if(0 == HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0))
{
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_8,GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET);//打开锁存器
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);//关闭锁存器
}
}
else if(0 == HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1))
{
HAL_Delay(10);
if(0 == HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1))
{
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_8,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET);//打开锁存器
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);//关闭锁存器
}
}
四、HAL_Delay的内部实现
跳转到HAL_Delay函数查看实现
核心部分就在这个while循环,当时间没有到达就一直执行while循环里面的空语句达到延时的效果。
__weak void HAL_Delay(uint32_t Delay)
{
uint32_t tickstart = HAL_GetTick();
uint32_t wait = Delay;
/* Add a freq to guarantee minimum wait */
if (wait < HAL_MAX_DELAY)
{
wait += (uint32_t)(uwTickFreq);
}
while ((HAL_GetTick() - tickstart) < wait)
{
}
}
HAL_GetTick()实现
HAL_GetTick()这个函数返回uwTick这个值,uwTick是由systick计数的,systick会让uwTick每ms加1,uwTick的类型是uint32_t 的所以他的计数时间是非常长的,理论上是2的32次方ms。
__weak uint32_t HAL_GetTick(void)
{
return uwTick;
}
五.遗留的问题
1.为什么不建议使用延时函数消抖,延时函数的本质就是程序一直停在这里不会继续向下执行,假如当延时的时间很长那么程序将会变得很卡顿。
2.上面的代码看起来太过于复杂了,假如我们要多次点亮LED那么我们每次都要写那么多代码吗,这太浪费时间了,我们必须对这些代码进行优化。
总结
按键也是非常简单就可以操作的,希望大家可以思考一下如何替换延时函数进行按键的消抖。希望大家能够好好思考留下来的几个问题,后面进阶篇我们再进行解决。