网课:b站西风&爱上半导体

key模块和Easy_Button库

关于上拉电阻/下拉电阻——爱上半导体

硬件部分:按键原理图

其中的电容有什么用?电阻有什么用?

电容:主要作用是硬件消抖 。机械按键在按下或释放瞬间,因触点弹性会产生抖动,表现为电压信号在短时间内不稳定地跳变。

  • 充电放电过程:按键闭合瞬间,电源通过电阻给电容充电,因电容两端电压不能突变,电压缓慢上升;按键断开瞬间,电容通过电阻放电,电压缓慢下降。这个过程将抖动的尖峰电压信号平滑掉,使单片机检测到的按键信号更稳定。

  • 与电阻构成 RC 电路:电容和串联的电阻构成 RC 电路,其时间常数τ=RC 决定了消抖效果。合适的R(如本图中 10KΩ )和C(如本图中 100nF )取值,能让电压变化在按键抖动持续时间内趋于稳定,一般让τ在几毫秒到几十毫秒范围,匹配按键抖动时长。

 电阻

限流

在按键闭合时,若没有电阻,电源(3V3 )与地(DGND )之间近似短路,会产生较大电流,可能损坏按键触点或相关电路元件。电阻能限制电流大小,根据欧姆定律\(I = U/R\) ,电源电压 3.3V ,电阻 10KΩ ,则电流约为 \(I = 3.3V÷10000Ω = 0.33mA\) ,这样的小电流可避免上述风险。

配合电容构成 RC 电路

与并联的 100nF 电容组成 RC 电路实现硬件消抖。在按键状态改变瞬间,电阻影响电容的充放电速度。通过调整电阻阻值可改变 RC 电路的时间常数\(\tau = RC\) ,从而调整消抖效果,让按键信号更稳定,避免抖动干扰。

上拉作用

将按键引脚的电平拉高。按键未按下时,按键引脚通过电阻连接到 3V3 电源,处于高电平状态;按键按下时,引脚电平被拉低到接近地电位。这样单片机等主控设备能方便地通过检测引脚电平高低来判断按键是否按下。

 RC电路的作用

硬件消抖

机械按键在按下或释放瞬间,因触点弹性会产生抖动,使电压信号短时间内不稳定跳变。单片机等主控设备处理速度快,可能将抖动误判为多次按键操作。并联电容利用自身特性,能对这种抖动起到抑制作用:

  • 充电放电过程:按键闭合瞬间,电源通过电阻给电容充电,因电容两端电压不能突变,电压缓慢上升;按键断开瞬间,电容通过电阻放电,电压缓慢下降。这个过程将抖动的尖峰电压信号平滑掉,使单片机检测到的按键信号更稳定。

  • 与电阻构成 RC 电路:电容和串联的电阻构成 RC 电路,其时间常数\(\tau = RC\) 决定消抖效果。合适的R(如 10KΩ )和C(如 100nF )取值,能让电压变化在按键抖动持续时间内趋于稳定,一般让\(\tau\)在几毫秒到几十毫秒范围,匹配按键抖动时长。

滤波和抗干扰

可削弱电源噪声、外界电磁干扰等对按键信号的影响 ,让按键输入信号更纯净,使按键状态的检测更准确可靠

软件部分

选择引脚(input),配置上拉,写注释标符

 程序部分

extern关键字是什么意思:声明

  • 作用:告诉编译器,该变量/函数在其他文件或模块中已定义,当前文件只是声明,不分配内存空间 。比如在一个源文件file1.c中定义了全局变量int globalVar = 10; ,若在另一个源文件file2.c中想使用这个变量,就可用extern int globalVar;声明 ,这样file2.c就能访问file1.c中定义的globalVar 。
  • 注意事项:变量在整个程序中只能定义一次,可在多个文件中用extern声明。声明时数据类型、变量名要与定义时一致,否则会导致运行时错误 。

在APP文件夹中创建key底层(底层和处理函数一起写),在mydefine.H文件引用key.H文件以及LED变量 

(复制粘贴,改)

创建经典key四个变量old,val,down,up

写key_read()函数,仿照蓝桥杯来写。

写按键处理函数key_proc(),完全照抄

将key_proc函数放入调度器中


接着学习,如何使用Easy_button库

作用:

Easy_button库使你只需关注按键"事件"本身,而把底层的抖动处理、状态判断、时间计算等繁琐细节交给它来完成。

事件驱动 (Event-Driven) 🛎️ —— 像按门铃

想象一下你家的门铃。你不需要每隔几秒就跑去门口问:"有人吗?"。你只需要待在屋里,当有人按下门铃时(这就是一个"事件"),铃声会响起,你再根据是谁(什么事件)决定开门(执行相应的操作)。

ebtn 就是这样工作的。它不会让你一直去检查按键状态,而是当按键发生了有意义的动作(比如按下、释放、单击、长按)时,它会主动"通知"你发生了什么"事件"。这种方式比你不停地去问"按键按下了吗?"(这叫轮询 Polling)要高效得多,也更符合人类的直觉。

状态机 (State Machine) 🚦 —— 像红绿灯

红绿灯有几种状态:红灯、绿灯、黄灯。它不会一下子从红灯跳到黄灯,必须先变成绿灯。状态之间的切换是有固定规则和顺序的。

ebtn 内部也为每个按键维护了一个"状态机"。这个状态机记录了按键当前处于哪个阶段,比如:

  • 空闲状态: 按键没被按下。
  • 抖动检测状态: 刚检测到按下信号,需要等待一小段时间(去抖时间)确认不是干扰。
  • 按下状态 (Pressed): 确认是有效按下,并且持续按着。
  • 单击判断状态: 按下后很快松开了,正在等待看是否会有下一次点击(用于判断连击)。
  • 释放状态 (Released): 确认有效松开。

ebtn 根据你按下的时间长短、松开的时间、以及连续点击的间隔,自动地在这些状态之间切换。你不需要关心这些复杂的状态转换,只需要等待 `ebtn` 告诉你最终的结果(事件)。

回调函数 (Callback Function) 📞 —— 留下你的电话

想象你去餐厅点餐,服务员告诉你菜好了会叫你。你留下你的桌号(这就是"回调信息"),然后就可以做自己的事了。当菜准备好时,服务员会根据桌号找到你并通知你(这就是"回调")。

在 ebtn 中,你需要提供两个重要的"联系方式":

  • `get_state_fn` (获取状态函数): 你需要告诉 ebtn 如何读取按键的物理状态(高电平还是低电平)。ebtn 在需要的时候会"打电话"给这个函数来获取信息。就像服务员问你:"你现在饿了吗?"。
  • `evt_fn` (事件通知函数): 你需要告诉 ebtn,当有按键事件发生时,应该去执行哪个函数来处理。就像你告诉服务员:"菜好了,请到这个桌号通知我。"。当 `ebtn` 检测到单击、长按等事件时,就会"打电话"给你提供的这个函数,并告诉你哪个按键发生了什么事件。

通过这种方式,ebtn 负责检测和判断,而你只需要在 `evt_fn` 这个函数里编写处理逻辑(比如开关灯、发送消息等)。

怎么用:

在GIthub上挑选合适的框架

创建Components文件夹,将框架放文件夹

应用层引用——组件库

创建应用层

底层的抖动处理、状态判断、时间计算等繁琐细节交给它来完成。

引用头文件/预定义

第一步:包含头文件

创建事件驱动 状态机  回调函数(状态获取,事件通知)

 第二步:定义参数与按键列表

核心流程为

  1. 定义按键参数 (ebtn_btn_param_t): 使用 EBTN_PARAMS_INIT 宏设定按键的各种时间阈值和行为。这些参数可以被多个按键共用。
  2. 定义按键实例 (ebtn_btn_t): 使用 EBTN_BUTTON_INIT 宏创建每个物理按键的实例,并指定它的唯一 key_id 和使用的参数。
  3. 定义组合按键实例 (ebtn_btn_combo_t, 可选): 使用 EBTN_BUTTON_COMBO_INIT 创建组合键实例,同样指定 key_id 和参数。

其他使用方法见所选框架的说明

/* 1. 定义按键参数实例 */
// 参数宏: EBTN_PARAMS_INIT(
//     按下消抖时间ms, 释放消抖时间ms,
//     单击有效最短按下时间ms, 单击有效最长按下时间ms,
//     多次单击最大间隔时间ms,
//     长按(KeepAlive)事件周期ms (0禁用),
//     最大连续有效点击次数 (e.g., 1=单击, 2=双击, ...)
// )
const ebtn_btn_param_t key_param_normal = EBTN_PARAMS_INIT(
    20,     // time_debounce: 按下稳定 20ms
    20,     // time_debounce_release: 释放稳定 20ms
    50,     // time_click_pressed_min: 最短单击按下 50ms
    500,    // time_click_pressed_max: 最长单击按下 500ms (超过则不算单击)
    300,    // time_click_multi_max: 多次单击最大间隔 300ms (两次点击间隔超过则重新计数)
    500,    // time_keepalive_period: 长按事件周期 500ms (按下超过 500ms 后,每 500ms 触发一次)
    5       // max_consecutive: 最多支持 5 连击
);

第三步:编写回调函数  

1.配置参数 

2.按键给ID值,绑定参数。 

3.ID值绑定回调——读取函数

4.通过ID值判断事件

第四步:初始化 ebtn 库

app初始化

第五步:周期性调用处理函数

MD听不懂,从LeD就不懂了,挫败感太强了。陷入自我怀疑了

Logo

openvela 操作系统专为 AIoT 领域量身定制,以轻量化、标准兼容、安全性和高度可扩展性为核心特点。openvela 以其卓越的技术优势,已成为众多物联网设备和 AI 硬件的技术首选,涵盖了智能手表、运动手环、智能音箱、耳机、智能家居设备以及机器人等多个领域。

更多推荐