单片机的按键消抖/开关量监测函数(附源码,可移植)

方案一:纯软件延时

sbit KEY = P1^3;
///按键读取函数
uint8_t GetKey(void)
{if(KEY == 1){DelayMs(20);        //延时消抖if(KEY == 1){return 1;}else {return 0;}}else {return 0;}
}

致命缺点:在延时的时候一直占用cpu的资源,如果在延时的时候,有其他外部中断或者抢占事件,系统完全没有响应的

方案二:中断消抖

此处不在贴出代码:感兴趣的同学可到文章中查看:按键消抖常用的软硬件方法
致命缺点:多占用中断资源。操作复杂。在资源就是成本的产品中(多占用一个中断可能会导致需要选择价格更高的MCU),这种方案的缺点更加明显。

推荐方案

图片
本文推荐一种更高效、合适,已在产品中使用过的软件设计方案。直接上代码。

#include <stdbool.h>// 定义开关信号结构体
typedef struct {bool lastState;       // 上次开关信号状态bool currentState;    // 当前开关信号状态bool validState;      // 有效的开关信号状态int debounceDelayCounter;  // 开关信号消抖计数器
} DebouncedSwitch;// 初始化开关信号结构体
void initializeSwitch(DebouncedSwitch* switchObj) {switchObj->lastState = false;switchObj->currentState = false;switchObj->validState = false;switchObj->debounceDelayCounter = 0;
}// 模拟读取开关信号状态的函数
bool readSwitchState() {// 在这里替换为实际的开关信号读取代码// 返回开关信号的当前状态(true表示开,false表示关)return false;
}// 处理开关信号消抖的函数
void debounceSwitch(DebouncedSwitch* switchObj, int debounceTime) {// 读取当前开关信号状态switchObj->currentState = readSwitchState();// 如果当前状态与上次状态不同,重置计数器并更新上次状态if (switchObj->currentState != switchObj->lastState) {switchObj->debounceDelayCounter = 0;} else {// 如果状态相同,增加计数器值switchObj->debounceDelayCounter++;}// 如果计数器达到指定的消抖时间,表示开关信号状态稳定if (switchObj->debounceDelayCounter >= (debounceTime / 10)) {// 如果当前状态与 validState 不同,表示发生了有效的状态变化if (switchObj->currentState != switchObj->validState) {switchObj->validState = switchObj->currentState;}}// 更新上次状态switchObj->lastState = switchObj->currentState;
}int main() {// 创建一个开关信号的DebouncedSwitch结构体DebouncedSwitch switchObj;initializeSwitch(&switchObj);while (1) {debounceSwitch(&switchObj, 100); // 设置消抖时间为100毫秒if (switchObj.validState) {if (switchObj.validState) {// 执行开关信号为开的操作printf("开关信号为开\n");} else {// 执行开关信号为关的操作printf("开关信号为关\n");}}// 在这里可以添加其他需要执行的代码// 模拟延时或等待开关信号状态变化// 这里使用usleep函数来模拟10毫秒的延时// 实际上,你需要根据你的硬件和操作系统来等待开关信号状态变化usleep(10000); // 10毫秒}return 0;
}

1、函数详解:
debounceSwitch函数该函数用于处理开关信号的消抖,以确保稳定的开关状态。
它接受一个指向 DebouncedSwitch 结构体的指针, 该结构体包含了上次状态、当前状态、有效状态等信息,以及消抖时间的设置。
该函数的被调用周期为10ms(可以与产品程序中其他任务并行执行)。
2、函数的工作流程如下:
1)读取当前开关信号状态。
2)如果当前状态与上次状态不同,重置计数器并更新上次状态。
3)如果当前状态与上次状态相同,增加计数器值。
4)如果计数器达到指定的消抖时间,表示开关信号状态稳定。
5)如果当前状态与 validState 不同,表示发生了有效的状态变化,更新有效状态。
6)更新上次状态以便下一次比较
3、优点介绍:
1)扩展性:debounceSwitch该函数使用结构体指针的形式,提供了开关量检测的框架,需要多个开关量/按键检测时,实例化对应的按键变量即可。例如:main函数的示例中实例化了switchObj,多有多个按键可以多定义不同的switchObj即可。如下:代码所展示:
DebouncedSwitch switchObj_key1;
DebouncedSwitch switchObj_key2;

//其他代码

debounceSwitch(&switchObj_key1, 100);
debounceSwitch(&switchObj_key2, 50);

2、高度可定制:
debounceSwitch函数中的消抖时间是作为参数传递的,这使得消抖时间可以根据不同的开关信号或应用场景进行定制。这种可定制性允许您在不同情况下使用不同的消抖时间,以满足特定需求。
3、适用于实时系统
相对于纯软件延时消抖,debounceSwitch函数是更可靠的,因为它不依赖于软件的延时,而是基于实际的状态变化来判断开关信号的稳定性。这使得它适用于实时系统和对时间精度要求较高的应用。
图片## 总结

当然,作为一个产品中使用的函数还有很多可优化的空间,比如:函数内判断指针不为空。进行参数的有效性检查等等。
如果发现有更好的可优化空间,欢迎共同交流。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/810354.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

探索点云与KD-Tree配对的方法

比较点云是处理和分析点云数据的关键步骤。然而,由于各个扫描之间固有的差异,无法进行逐点比较。因此,点云分析的第一步也是主要步骤是将点配对以进行有意义的比较。 配对点是区分表面变形和运动分析的关键任务。这个过程不仅为变形分析提供了见解,还使我们能够通过比较不…

华为海思数字芯片设计笔试第五套

声明 下面的题目作答都是自己认为正确的答案&#xff0c;并非官方答案&#xff0c;如果有不同的意见&#xff0c;可以评论区交流。 这些题目也是笔者从各个地方收集的&#xff0c;感觉有些题目答案并不正确&#xff0c;所以在个别题目会给出自己的见解&#xff0c;欢迎大家讨论…

鼠标灵敏度怎么调,鼠标灵敏度怎么调最稳

鼠标和键盘是操作计算机过程中使用最频繁的设备之一&#xff0c;用电脑的时&#xff0c;我敢说你一定离不开鼠标。有些用户发现鼠标不太好用&#xff0c;尤其是在游戏时&#xff0c;总觉得鼠标移动太慢了。另外&#xff0c;如果你感觉鼠标按键失灵、鼠标单击变双击以及反应迟钝…

武汉军工保密认证保密资格认证有什么意义?

其一&#xff0c;适应新体制的需要。由于国防科技工业管理体制的变化&#xff0c;保密管理实际上已置身于更加开放的国际国内大环境中&#xff0c;保密管理体制必须做出相应的改革&#xff0c;建立起与市场经济相适应的新的保密机制。而在军工行业实行认证制度&#xff0c;则是…

pandas习题 029:用 Series 构造 DataFrame

参考答案 用 Series 构造一个 DataFrame&#xff0c;它有 a、b 两列&#xff0c;三行数据。其中 a 列值为 1、4、7&#xff0c;b 列值为 2、5、8&#xff0c;索引为 x、y、z。即&#xff1a;a b x 1 2 y 4 5 z 7 8 参考答案Python 代码如下&#xff1a;import pandas a…

装机指导。

everything winrar snipaste cmake git tortoisegit tortoisesvn inno setup vs2022 安装的时候注意sdk路径一定要默认&#xff01;&#xff01; 否则你会发现在你的sdk安装路径的根盘符下会多出一个Windows Kits&#xff0c;强迫症接受不了 默认的会跟已有的装在一起…

C语言面试指针辨析

1. const int *p int const *p p可以改变&#xff0c;*p不可以改变 p可以指向任意空间&#xff0c;但无法利用p修改指针空间的值 2. int *const p p不能改变&#xff0c;*p可以改变 3. const int *const p int const *const p p和*p都不能改变 4. 面试问题 将内存地址为0x2…

69787987

c语言中的小小白-CSDN博客c语言中的小小白关注算法,c,c语言,贪心算法,链表,mysql,动态规划,后端,线性回归,数据结构,排序算法领域.https://blog.csdn.net/bhbcdxb123?spm1001.2014.3001.5343 给大家分享一句我很喜欢我话&#xff1a; 知不足而奋进&#xff0c;望远山而前行&am…

Matlab|基于蒙特卡洛的风电功率/光伏功率场景生成方法

目录 主要内容 部分代码 结果一览 下载链接 主要内容 该模型主要用于风电功率和光伏功率场景生成与缩减&#xff0c;利用多元高斯分布构建时间相关性&#xff0c;并采用蒙特卡洛方法进行仿真&#xff0c;风电功率采用Weibull分布&#xff0c;光伏功率采用Beta分布…

Linux使用Linpack测试

安装HPL之前需要配置好&#xff1a; 1.GCC/Fortran77 编译器 2.BLAS/CBLAS/ATLAS 库 3.MPICH 并行环境 1.GCC/Fortran77 编译器 gfortran -v gcc -v #检查环境&#xff0c;若没有安装 yum install gcc yum install gcc-gfortran2.安装向量和矩阵运算库函数 BLAS/CBLAS/ATLAS…

「seata」分布式事务seata部署及应用

「seata」分布式事务seata部署及应用 seata 版本一、部署seata服务1、配置config.txt文件中的属性值2、为seata服务单独创建一个nacos命名空间3、利用脚本上传配置文件到nacos4、配置seata服务的application.yml6、执行数据库脚本5、使用脚本启动seata服务 二、配置并启动微服务…

LCA 祖孙询问

树上倍增 1. 链式前向星建树 2. bfs 预处理倍增数据,fa[i][k]&#xff0c;向上走$2^{k-1}$步所到达的位置&#xff08;设置哨兵&#xff0c;放置越界&#xff09; 3. lca两步&#xff1a;&#xff08;1&#xff09;跳到同一层 &#xff08;&#xff09;一起向上跳&#xff0…

SCI一区 | Matlab实现INFO-TCN-BiGRU-Attention向量加权算法优化时间卷积双向门控循环单元注意力机制多变量时间序列预测

SCI一区 | Matlab实现INFO-TCN-BiGRU-Attention向量加权算法优化时间卷积双向门控循环单元注意力机制多变量时间序列预测 目录 SCI一区 | Matlab实现INFO-TCN-BiGRU-Attention向量加权算法优化时间卷积双向门控循环单元注意力机制多变量时间序列预测预测效果基本介绍模型描述程…

【提纲挈领】学会提问题,你就是那个年薪百万元的提示词工程师!LLM时代,如何提问题成为关键技能!多图说明!

【提纲挈领】学会提问题&#xff0c;你就是那个年薪百万元的提示词工程师&#xff01;LLM时代&#xff0c;如何提问题成为关键技能&#xff01;多图说明&#xff01; 一、会提问题的重要性二、提示词工程师三、如何提问3.1 提示词框架——BROKE原则3.1.1 打个比方3.1.2 举个实例…

品牌发言稿怎么写?媒介盒子分享

品牌发言稿的重要性不言而喻&#xff0c;它不仅代表着品牌形象&#xff0c;更是沟通品牌与消费者、合作伙伴的桥梁。如何撰写一篇高质量的品牌发言稿&#xff0c;成为许多品牌关注的焦点。今天媒介盒子来和大家聊聊&#xff1a;品牌发言稿怎么写。 一、 发言稿写作技巧 1.结构…

静音检测电路芯片D3703F——工 作 电 压 范 围 宽 : 3.2V ~ 16.0V,可以用于汽 车 音 响 系 统

概 述 &#xff1a; D3703F 是 一 块 汽 车 音 响 静 音 检 测 电 路 。 用 于 音 响 系 统 检 测 在 放 音 或 快 进 / 退 时 进 行 静 音 检 测 。 D3703F 的 的 电 压 范 围 &#xff1a; 3.2V &#xff5e; 16V &#xff0c; 信 号 检 测 和 静 音 时 间 可 通 过 外 围…

机器学习——模型融合:Boosting算法

机器学习——模型融合&#xff1a;Boosting算法 1. Boosting核心思想 Boosting算法是一种集成学习方法&#xff0c;其核心思想是通过组合多个弱学习器&#xff08;即准确率略高于随机猜测的学习器&#xff09;来构建一个强学习器&#xff08;即准确率较高的学习器&#xff09…

URI和URL的区别与联系

URI&#xff08;Uniform Resource Identifier&#xff09;和URL&#xff08;Uniform Resource Locator&#xff09;在Web技术中都有着重要的应用&#xff0c;它们都是用于标识和定位互联网上的资源&#xff0c;但存在一些关键的区别。 URL&#xff0c;即统一资源定位符&#x…

【JAVA基础篇教学】第五篇:Java面向对象编程:类、对象、继承、多态

博主打算从0-1讲解下java基础教学&#xff0c;今天教学第五篇&#xff1a;Java面向对象编程&#xff1a;类、对象、继承、多态。 在Java中&#xff0c;面向对象编程是一种常用的编程范式&#xff0c;它以类和对象为核心&#xff0c;通过继承和多态等机制实现代码的复用和灵活…

万字长文!全网最详细的HarmonyOSNext星河版快速上手教程,小白看这个就够了!(下载安装DevEco Studio)

本节课将学习HarmonyOS应用开发领域&#xff0c;我们将逐步学习通过DeEco Studio开发工具创建并运行一个Hello World的工程。&#xff08;并在文末给出章节练习题供大家巩固掌握&#xff09; 阅读完本文&#xff0c;你将掌握以下内容。 01.下载与安装DevEco Studio/02.配置环…