STM32高级篇—按键FIFO

news2024/11/15 3:58:57
想成问一名非常优秀的嵌入式软件工程师,是需要掌握很多知识的。
完成STM32的基础内容的学习后,我们也进入到学习STM32高级的内容上。
本人也是一名嵌入式的初级入坑人,写的内容可能会有错误,或者不正确的地方也请大家多多指教,我们一起努力。

文章目录

  • 一、FIFO(先进先出)
    • 1.1 按键FIFO的意义
    • 1.2 FIFO的实现
  • 二、按键FIFO的实现
    • 2.1 按键FIFO的初始化
    • 2.2 按键FIFO功能的实现
    • 2.3 按键扫描功能实现

一、FIFO(先进先出)

1.1 按键FIFO的意义

通常情况下,我们再判断按键是否按下的时候,是采用中断的方式进行设计的,过多的使用中断,会导致程序实现的不稳定,因此需要设计FIFO按键模式,设计按键FIFO主要有几方面的好处:
1)可以有效地记录按键事件的发生,尤其使对按键的按下,长按,弹起等事件的发生,使用FIFO的方式实现是一种非常好的思路。
2)系统是非阻塞的,这样系统在检测到按键按下的情况下,由于机械按键抖动的原因不需要再这里等待一段事件,然后再确定按键是否按下。

1.2 FIFO的实现

FIFO的基本思想,就是先进先出,还是比较好理解的,我们以几张图为代表,就可以轻松的搞定。我们以5个字节的FIFO空间为例子。Read和Write分别表示读和写指针。
在这里插入图片描述分别按下按键,K1,K2,K3按键被按下的事件将进入FIFO当中。如下所示。这个时候写指针会根据写入的事件从而发生改变。
在这里插入图片描述
通过读指针,实现对按键事件的读写操作。
在这里插入图片描述

二、按键FIFO的实现

2.1 按键FIFO的初始化

/* 
******************************************************************************************* 
* 函 数 名: KeyFifoVar_Init 
* 功能说明: 初始化每一个按键对应的结构体
* 形    参:  无 
* 返 回 值: 无 
*******************************************************************************************
*/
static void KeyFifoVar_Init(void)
{
	uint8_t i;
	
	// 初始化读写指针
	s_tKey.Read = 0;
	s_tKey.Write = 0;  
	
	// 给每个按键结构体成员变量赋一组值
	for(i = 0; i < KEY_NUM; i++)
	{
		s_tBtn[i].LongTime = KEY_LONG_TIME;
		s_tBtn[i].Count = KEY_FILTER_TIME;
		s_tBtn[i].State = 0;
		s_tBtn[i].RepeatCount = 0;
		s_tBtn[i].RepeatSpeed = 0;
		s_tBtn[i].LongTime = 0; 
	}
	 
  /* 如果需要单独更改某个按键的参数,可以在此单独重新赋值 */ 
  /* 比如,我们希望按键1按下超过1秒后,自动重发相同键值 */ 
  s_tBtn[1].LongTime = 100; 
  s_tBtn[1].RepeatSpeed = 5; /* 每隔50ms自动发送键值 */ 
	
	s_tBtn[0].IsKeyDownFunc = IsKeyDown1;
	s_tBtn[1].IsKeyDownFunc = IsKeyDown2;
	s_tBtn[2].IsKeyDownFunc = IsKeyDown3;
	s_tBtn[3].IsKeyDownFunc = IsKeyDown4;
}
// 定义键值代码,必须按如下的顺序设计每一个案件的按下, 弹起,和长按
typedef enum
{
	KEY_NONE = 0,   // 0 表示按键事件
	KEY_1_DOWN,
	KEY_1_UP,
	KEY_1_LONG,
	
	KEY_2_DOWN,
	KEY_2_UP,
	KEY_2_LONG,
	
	KEY_3_DOWN,
	KEY_3_UP,
	KEY_3_LONG,
	
	KEY_4_DOWN,
	KEY_4_UP,
	KEY_4_LONG,
}KEY_ENUM;

2.2 按键FIFO功能的实现

/* 
******************************************************************************************* 
* 函 数 名: Fifo_PutKey 
* 功能说明: 将1个键值压入按键FIFO缓冲区。可用于模拟一个按键。
* 形    参:  _KeyCode:按键代码 
* 返 回 值: 无 
*******************************************************************************************
*/
void Fifo_PutKey(uint8_t _KeyCode)
{
	s_tKey.Buff[s_tKey.Write] = _KeyCode;
	
	if(++s_tKey.Write >= KEY_FIFO_SIZE)
	{
		s_tKey.Write = 0;
	}
}
/* 
******************************************************************************************* 
* 函 数 名: Fifo_GetKey 
* 功能说明: 从按键FIFO缓冲区读取一个键值。
* 形    参: 无
* 返 回 值: 按键代码 
*******************************************************************************************
*/
uint8_t Fifo_GetKey(void)
{
	uint8_t ret;
	
	if(s_tKey.Read == s_tKey.Write)
	{
		return KEY_NONE;
	}
	else
	{
		ret = s_tKey.Buff[s_tKey.Read];
		if(++s_tKey.Read >= KEY_FIFO_SIZE)
		{
			s_tKey.Read = 0;
		}
		return ret;
	}
}

2.3 按键扫描功能实现

/* 
******************************************************************************************* 
* 函 数 名: DetectKey 
* 功能说明: 按键检测
* 形    参:  无 
* 返 回 值: 无 
*******************************************************************************************
*/
static void DetectKey(uint8_t i)
{
	KEY_T *pBtn;
	pBtn = &s_tBtn[i];
	
	if(pBtn->IsKeyDownFunc()) 
	{
		if(pBtn->Count < KEY_FILTER_TIME)
		{
			pBtn->Count = KEY_FILTER_TIME;
		}
		else if(pBtn->Count < 2 * KEY_FILTER_TIME)
		{
			pBtn->Count++;
		}
		else
		{
			if(pBtn->State == 0)
			{
				pBtn->State = 1;
				
				// 如FIFO
				Fifo_PutKey((uint8_t)(3*i + 1)); 
			}
			// 判断按键是否长按
			if(pBtn->LongTime >0)
			{
				if(pBtn->LongCount < pBtn->LongTime)
				{
					if(++pBtn->LongCount == pBtn->LongTime)
					{
						Fifo_PutKey((uint8_t)(3*i + 3));
					}
				}
				else
				{
					if(pBtn->RepeatSpeed > 0)
					{
						if(pBtn->RepeatCount >= pBtn->RepeatSpeed)
						{
							pBtn->RepeatCount = 0;
							// 常安按键,每隔10ms发送1个按键
							Fifo_PutKey((uint8_t)(3*i + 1));
						}
					}
				}
			}
		}
	}
	else
	{
		if(pBtn->Count > KEY_FILTER_TIME)
		{
			pBtn->Count = KEY_FILTER_TIME;
		}
		else if(pBtn->Count != 0)
		{
			pBtn->Count--;
		}
		else
		{
			if(pBtn->State == 1)
			{
				pBtn->State = 0;
				
				// 发送按键弹起的消息
				Fifo_PutKey((uint8_t)(3*i + 2));
			}
		}
		pBtn->LongCount = 0;
		pBtn->RepeatCount = 0;
	}
}
/* 
******************************************************************************************* 
* 函 数 名: KeyScan 
* 功能说明: 按键扫描
* 形    参: 无
* 返 回 值: 按键代码 
*******************************************************************************************
*/
void KeyScan_Task(void)
{
	uint8_t i;
	for(i = 0 ; i < KEY_NUM; i++)
	{
		DetectKey(i);
	}
}

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

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

相关文章

1.0 Android中Activity的基础知识

一&#xff1a;Activity的定义 Activity是一个应用组件&#xff0c;它提供了一个用户界面&#xff0c;允许用户执行一个单一的、明确的操作&#xff0c;用户看的见的操作都是在activity中执行的。Activity的实现需要在manifest中进行定义&#xff0c;不让会造成程序报错。 1.…

【动态规划】| 路径问题之不同路径 力扣62

&#x1f397;️ 主页&#xff1a;小夜时雨 &#x1f397;️ 专栏&#xff1a;动态规划 &#x1f397;️ 如何活着&#xff0c;是我找寻的方向 目录 1. 题目解析2. 代码 1. 题目解析 题目链接: https://leetcode.cn/problems/unique-paths/description/ 通常动态规划的题目有…

【Linux】解决由于 network和 NetworkManager不兼容,导致的网络服务错误

今天尝试启动在虚拟机中启动一些中间件环境&#xff08;用docker管理&#xff09;&#xff0c;使用ssh连接虚拟机&#xff0c;却始终无法连接 我怀疑是不是虚拟机的ip地址改变了&#xff0c;但是之前我的虚拟机ip已经在 /etc/sysconfig/network-scripts 目录下&#xff0c;创…

PCA与LDA

共同点 降维方法&#xff1a; PCA和LDA都是数据降维的方式&#xff0c;它们都能通过某种变换将原始高维数据投影到低维空间。 数学原理&#xff1a; 两者在降维过程中都使用了矩阵特征分解的思想&#xff0c;通过对数据的协方差矩阵或类间、类内散度矩阵进行特征分解&#xff…

Vue项目实践:使用滚动下拉分页优化大数据展示页面【通过防抖加标志位进行方案优化】

Vue项目实践&#xff1a;使用滚动下拉分页优化大数据展示页面 前言 传统的分页机制通过点击页码来加载更多内容&#xff0c;虽然直观&#xff0c;但在处理大量数据时可能会导致用户体验不佳。相比之下&#xff0c;滚动下拉分页能够在用户滚动到页面底部时自动加载更多内容&…

实现JWT认证与授权的Spring Boot项目详解

我们将详细介绍如何使用JWT&#xff08;JSON Web Tokens&#xff09;结合Spring Boot框架实现用户认证和授权系统。此方案将包括用户注册、登录以及通过JWT令牌进行后续请求的身份验证过程。我们将从引入必要的依赖开始&#xff0c;然后逐步构建项目的各个部分&#xff0c;包括…

如何查看当前的gruop_id 的kafka 消费情况 这个可以查看到是否存在消费阻塞问题

如何查看当前的gruop_id 的kafka 消费情况 这个可以查看到是否存在消费阻塞问题 命令如下: /kafka/bin/kafka-consumer-groups.sh --bootstrap-server 127.0.0.1:9092 --group GWW --describe 其中 127.0.0.1 为zookeeper 服务器ip GWW 为对应要查看的group_id 如下…

从零到一建设数据中台(番外篇)- 数据中台UI欣赏

番外篇 - 数据中台 UI 欣赏 话不多说&#xff0c;直接上图。 数据目录的重要性&#xff1a; 数据目录是一种关键的信息管理工具&#xff0c;它为组织提供了一个全面的、集中化的数据资产视图。 它不仅记录了数据的存储位置&#xff0c;还详细描述了数据的结构、内容、来源、使…

800W-2300W-4500W-7000W线绕电阻器的选型参考

EAK线绕电阻器将普通电阻器材料的高脉冲稳定性与优化的导热和高度保护相结合。安装在导热表面上可进一步改善散热并提高稳定性。 EAK提供各种外壳设计和材料&#xff08;如铝和钢&#xff09;的导线电阻器。它们符合 UL508 的要求&#xff0c;在用作制动、充电、放电或加热电阻…

Java面试八股之静态变量和实例变量的区别有哪些

Java静态变量和实例变量的区别有哪些 存储位置和生命周期&#xff1a; 静态变量&#xff1a;静态变量属于类级别&#xff0c;存储在Java的方法区&#xff08;或称为类区&#xff0c;随JVM实现而异&#xff0c;现代JVM中通常在元数据区内&#xff09;&#xff0c;并且在类首次…

Rocky Linux 9.4 部署Zabbix 7.0

文章目录 Zabbix基本概念zabbix介绍zabbix特性zabbix结构 安装Zabbix主机名配置配置Zabbix-Server(1)禁用EPEL提供的Zabbix软件包(2)安装Zabbix Server、Web前端、Agent(3)创建初始数据库(4)Zabbix server配置数据库(5)为Zabbix前端配置PHP(6)启动Zabbix server和agent进程(7)放…

Windows电脑清理C盘内存空间

ps&#xff1a;过程截图放在篇末 一、%tmp%文件 win R键呼出运行窗口&#xff0c;输入 %tmp% 自动进入tmp文件夹&#xff0c;ctrl A全选删除 遇到权限不足&#xff0c;正在运行&#xff0c;丢失的文件直接跳过即可 二、AppData文件夹 1、pipcache 在下列路径下面&…

Amortized bootstrapping via Automorphisms

参考文献&#xff1a; [MS18] Micciancio D, Sorrell J. Ring packing and amortized FHEW bootstrapping. ICALP 2018: 100:1-100:14.[GPV23] Guimares A, Pereira H V L, Van Leeuwen B. Amortized bootstrapping revisited: Simpler, asymptotically-faster, implemented. …

代理设计模式之JDK动态代理CGLIB动态代理原理与源码剖析

代理设计模式 代理模式(Proxy),为其它对象提供一种代理以控制对这个对象的访问。如下图 从上面的类图可以看出,通过代理模式,客户端访问接口时的实例实际上是Proxy对象,Proxy对象持有RealSubject的引用,这样一来Proxy在可以在实际执行RealSubject前后做一些操作,相当于…

MTK烧录USB驱动下载

下载链接 https://www.catalog.update.microsoft.com/Search.aspx?qMediaTek%20USB%20Port 驱动安装教程 https://miuiver.com/install-official-mediatek-driver/

中科数安 |-公司办公透明加密系统,数据防泄漏软件

#数据防泄漏软件# 中科数安是一家专注于提供企业级数据防泄漏解决方案的公司&#xff0c;其办公透明加密系统是专为保护企业内部核心数据资料设计的。 PC地址&#xff1a;——www.weaem.com 该系统通过以下主要功能模块实现高效的安全防护&#xff1a; 文档透明加密&#xff1…

惠州惠城:可燃气体报警器定期校准检测,安全更放心

在惠州惠城这片繁华的土地上&#xff0c;工业发展日新月异&#xff0c;安全问题愈发受到重视。其中&#xff0c;可燃气体报警器作为预防火灾和爆炸事故的重要设备&#xff0c;正在越来越多的场所得到应用。 今天&#xff0c;佰德就来探讨一下可燃气体报警器在惠州惠城的重要性…

PV 操作

PV 操作是一种实现进程 互斥 与 同步 的有效方法。PV 操作与信号量的处理相关&#xff0c;P 表示 passeren 通过的意思&#xff0c;V 表示 vrijgeven 释放的意思. 包含在 1965 年, 由荷兰人 Dijkstra 提出的信号量机制; (同是 银行家算法 和 最短路径算法 的提出者) 术语: sema…

Pytorch 实现简单的 线性回归 算法

Pytorch实现简单的线性回归算法 简单 tensor的运算 Pytorch涉及的基本数据类型是tensor&#xff08;张量&#xff09;和Autograd&#xff08;自动微分变量&#xff09; import torch x torch.rand(5, 3) #产生一个5*3的tensor&#xff0c;在 [0,1) 之间随机取值 y torch.o…

ATFX汇市:非农数据超预期靓丽,美指重新站上105关口

ATFX汇市&#xff1a;6月7日&#xff0c;美国劳工统计局公布5月份非农就业报告&#xff0c;其中提到&#xff1a;5月份增加了27.2万个岗位&#xff0c;大幅高于前值16.5万人&#xff0c;数据超预期靓丽&#xff1b;几个行业的就业人数继续呈上升趋势&#xff0c;其中医疗领域增…