接上文,当我们想要通过按键来控制单片机的时候,由于机械触点在活动时,弹片有可能存在几次连续的抖动,从而产生不必要的脉冲信号,这就可能造成单片机的误判。
为了减少这样的误判,我们要进行消抖,消抖就是要尽可能的减少这种误判的可能
按键的工作模式暂且为两种,轮询模式和中断模式
轮询模式 (Polling Pattern)是检查硬件是否有新数据或信号的最简单方式。轮询可以是 周期性 (periodic) 的,也可以是 伺机性 (opportunistic) 的。周期性轮询使用定时器来指示何时应该对硬件进行采样,而伺机性轮询则在系统方便的时候进行,例如在主要系统函数之间或在重复执行周期的某个时间点。
轮询也有两种策略,忙等待(独占式查询)和定时查询,前者是当用户程序发出设备命令和参数的时候,CPU开始不断的查询设备状态直至设备就绪,这个阶段CPU不能执行其他任务。
中断模式是一种强大且有效的机制,用于处理紧急和高频事件。与轮询模式相比,中断模式能够确保及时响应和处理这些事件,从而提高系统的实时性和可靠性。(因为是设备主动请求中断)在中断模式中,当紧急事件发生时,处理器会立即暂停当前任务,跳转到与该事件相关联的中断服务例程(ISR)进行处理。处理完成后,处理器会返回到被中断的任务继续执行。这种机制确保了紧急事件能够得到优先处理,而不会被其他低优先级的任务所阻塞。
用上课举个例子,轮询模式就是老师每隔一端时间来看一下外面有没有人来,中断模式则是老师听到声音出去看一下外面有没有人,之后再回去讲课
简单来说,中断分为这五步
识别中断,保存现场,判断中断,执行中断,返回现场
我们来详细说一说这些步骤
1.识别中断
识别是什么类型的中断(按键中断?定时器中断?)
2.保存现场与判断中断
执行到哪一步就停在哪一步,保存。
判断中断就是判断中断的优先级,看谁先执行。
这里是用栈进行保存。举个例子,老师听到敲门声(这里敲门声是一个中断),然后又听到了手机电话声(这也是一个中断),假设电话声比敲门声优先级高,老师应该先接电话,然后挂掉电话,再去开门。也就是先执行电话声这个中断,再执行敲门声这个中断,满足栈的特点,First In Last Out。
3.执行中断
也就是执行中断函数需要做的事情
4.返回现场
执行完中断后回到之前保存的现场。老师做完响应的事情继续讲课。
回到按键中断
按键的中断触发方式有两种,水平触发和沿触发
顾名思义,水平触发就是判断他电平是高电平还是低电平,根据原理图按下按键的时候是低电平,松开按键是高电平。但是你按下的时候不可能是一瞬间,会维持一段时间,也就是一直会进行中断,很明显不符合我们的预期。
沿触发就是看电平的上升沿和下降沿,从未按下时的高电平转换到按下的低电平,会有一个明显的下降,我们把这个作为中断触发的条件即可。
具体的CubeMX配置如下
1.开启中断
2.设置为下降沿触发和高电平
3.设置中断优先级(很重要)
代码如下
GPIO_InitStruct.Pin = GPIO_PIN_4;
GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING;//下降沿
GPIO_InitStruct.Pull = GPIO_PULLUP;//上拉电阻
HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);
中断
HAL_NVIC_SetPriority(EXTI4_IRQn, 1, 0);//这里的1是指中断优先级
HAL_NVIC_EnableIRQ(EXTI4_IRQn);
main文件中
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
if(KEY0_Pin==GPIO_Pin)
{
HAL_GPIO_TogglePin(GPIOF,GPIO_PIN_9);
}
}
按下亮,再按一下灭。