【致敬未来的攻城狮计划】连续打卡第9天+RA2E1读取按键

开启攻城狮的成长之旅!这是我参与的由 CSDN博客专家 架构师李肯(http://yyds.recan-li.cn)和 瑞萨MCU (瑞萨电子 (Renesas Electronics Corporation) ) 联合发起的「 致敬未来的攻城狮计划 」的第 9 天,点击查看活动计划详情 (https://bbs.csdn.net/topics/613916237)!


寻找按钮

在原理图中寻找按钮。

如图,USER PUSH-BUTTON在原理图上的位置在LED旁边,对应的端口为P004,按钮名称为S1。

S1没有被按下时,P004VCC相连,输出高电平。当按钮按下时,1与2串联,VCC接地短路,P004输出低电平。

【致敬未来的攻城狮计划】连续打卡第9天+RA2E1读取按键_第1张图片

S1在开发板上也做了标注。

【致敬未来的攻城狮计划】连续打卡第9天+RA2E1读取按键_第2张图片

通常,开发板多以低电平为按键输入,高电平为平时状态。

消抖原因

按键所用的开关为机械弹性开关,当机械触点断开、闭合时,由于机械触点的弹性作用,一个按键开关在闭合时不会马上稳定地接通,在断开时也不会一下子断开。因而在闭合及断开的瞬间均伴随有一连串的抖动。

【致敬未来的攻城狮计划】连续打卡第9天+RA2E1读取按键_第3张图片

如果只按下了一下按键,由于单片机程序执行速度很快,所以可能会识别到抖动的高电平,导致单片机以为我们按下了很多次按键。因此,我们需要进行按键消抖。

为确保CPU对键的一次闭合仅作一次处理,必须去除键抖动。在键闭合稳定时读取键的状态,并且必须判别到键释放稳定后再作处理。

消抖方法

按键稳定闭合时间长短是由操作人员决定的,通常都会在 100 ms 以上,刻意快速按的话能达到 40-50 ms 左右,很难再低了。抖动时间是由按键的机械特性决定的,一般都会在 10 ms 以内,为了确保程序对按键的一次闭合或者一次断开只响应一次,必须进行按键的消抖处理。当检测到按键状态变化时,不是立即去响应动作,而是先等待闭合或断开稳定后再进行处理。

按键消抖可分为硬件消抖和软件消抖。

硬件消抖

硬件消抖就是在按键上并联一个电容,如图所示,利用电容的充放电特性来对抖动过程中产生的电压毛刺进行平滑处理,从而实现消抖。但实际应用中,这种方式的效果往往不是很好,而且还增加了成本和电路复杂度,所以实际中使用的并不多。

【致敬未来的攻城狮计划】连续打卡第9天+RA2E1读取按键_第4张图片

软件消抖

软件消抖分为堵塞式消抖和非堵塞式消抖。

堵塞式消抖:

  • 缺点:阻塞式消抖会让程序堵死在while,对CPU的资源浪费,而且会让我们无法执行 其他程序。
  • 优点:如果我们按键按下需要执行的程序是记录按键按下次数,这样就不会导致我们误判明明只按下1次长时间不松手,而造成cpu认为按下多次。
//判断是否为低电平(按键按下为低电平)
//延时20ms
//while判断是否为低电平(按键按下为低电平,等待松手)
//判断是否为低电平(按键按下为低电平)
    //执行程序
//其他程序

非堵塞式消抖:

优点:这种方法不会阻塞程序,如果我们按下按键不松手, 其他程序依旧可以跑。

缺点:如何我们需要的是记录按键按下的次数。因为人不可能将按键按下的时间精准控制在20ms之内。那么就会造成,我明明只按下了一次,而 执行程序部分却会执行多次。

//判断是否为低电平(按键按下为低电平)
//延时20ms
//判断是否为低电平(按键按下为低电平)
    //执行程序
//其他程序

注释来自大佬风正豪,对比这两种情况的注释,可以看到,堵塞式消抖能够对长按按钮进行判断。

程序编写

Pin Configuration中配置需要用到的三个端口。

我们要从P004中读取输入信号,设置为输入模式。

我们要点亮P501和P502,设置为输出模式。

【致敬未来的攻城狮计划】连续打卡第9天+RA2E1读取按键_第5张图片

学习将会用到的函数

写入端口R_IOPORT_PinWrite()和读取端口R_IOPORT_PinRead()

写入端口R_IOPORT_PinWrite()

/*R_IOPORT_PinWrite()用于设置IO高低电平
 *传入参数有三个
 *参数一:
    *固定为&g_ioport_ctrl
 *参数二:
    *指定IO口,比如我们需要控制P502,就输入BSP_IO_PORT_05_PIN_02。如果是控制P411,就输入BSP_IO_PORT_04_PIN_11
 *参数三:
    *指定输出的电平,BSP_IO_LEVEL_LOW输出低电平,BSP_IO_LEVEL_HIGH输出高电平
 */

读取端口R_IOPORT_PinRead()

与写入不同的是,第三个参数需要填一个变量,用来存储读取到的电平。

/*R_IOPORT_PinRead()用于读取引脚电平
 *函数原型
    *fsp_err_t R_IOPORT_PinRead (ioport_ctrl_t * const p_ctrl, bsp_io_port_pin_t pin, bsp_io_level_t * p_pin_value);
 *参数1:
    *固定为g_ioport_ctrl
 *参数2:
    *指定IO口,比如我们需要查看P004电平,就输入BSP_IO_PORT_00_PIN_04。如果是查看P411,就输入BSP_IO_PORT_04_PIN_11
 *参数3:
    返回的电平数值,这个需要自己定义。
*/

为了能在检测按键的时候保持闪烁,我选择非堵塞式按键消抖。

写一个堵塞式消抖

打开上一次的项目。

创建一个S1变量来存储从按钮S1接收到的信息。

(图中变量名是小写s1,到后来我又改成了大写S1)

【致敬未来的攻城狮计划】连续打卡第9天+RA2E1读取按键_第6张图片

创建一个变量来标记当前状态。

int i = 0;

在循环内部,检测按键状态,当检测到按键按下时,使用while循环持续监听,直到按键松开。

松开之后调整i。

根据i值,控制LED输出。

由于BSP_IO_LEVEL_LOW只是官方写好的一个枚举常量,本质就是0和1,因此可以直接输入int,不会报错。

这个程序的功能是按下按钮,交替设置灯泡常亮

while (1)
{
    R_IOPORT_PinRead (&g_ioport_ctrl, BSP_IO_PORT_00_PIN_04, &S1);
    if (S1 == BSP_IO_LEVEL_LOW)
    {
        R_BSP_SoftwareDelay (20, BSP_DELAY_UNITS_MILLISECONDS);
        R_IOPORT_PinRead (&g_ioport_ctrl, BSP_IO_PORT_00_PIN_04, &S1);
        while (S1 == BSP_IO_LEVEL_LOW)
        {
            R_BSP_SoftwareDelay (10, BSP_DELAY_UNITS_MILLISECONDS);
            R_IOPORT_PinRead (&g_ioport_ctrl, BSP_IO_PORT_00_PIN_04, &S1);
        }
        i = !i;
    }
    R_IOPORT_PinWrite (&g_ioport_ctrl, BSP_IO_PORT_05_PIN_01, i);
    R_IOPORT_PinWrite (&g_ioport_ctrl, BSP_IO_PORT_05_PIN_02, !i);
}

你可能感兴趣的:(单片机,stm32,嵌入式硬件)