HALSTM32通用定时器+EXTI实现单击/双击/长按功能

news2024/12/26 2:39:36

HALSTM32通用定时器+EXTI实现单击/双击/长按功能


  • ✨在使用USB功率计的时候,发现上面的一个按键实现多画面功能切换,于是探索了一下是如何实现的,将其实现的基本思路以及综合网上收集的相关实现方法,粗陋的整理了一下,将其基本功能实现了一下,具体的功能没有做,只是做了一个简单的框架。
    在这里插入图片描述
  • 👉🏻功能实现,并不能保证每次处理的按键结果,都如预期效果,主要的影响因数是单击和双击,之间的间隔时间,每个人的手感或者每次按下的时间差异并不能像计算器那么准确和标准。

🛠HAL STM32CubeMX工程配置

  • 🌿基于STM32F103芯片。

  • 🌿主要配置一个外部中断按键引脚。
    在这里插入图片描述

  • 🔖GPIO引脚按键外部使用电路参考:
    在这里插入图片描述

  • 🌿配置一个定时器
    在这里插入图片描述

  • 🌿NVIC中断使能以及优先级配置。
    在这里插入图片描述

  • 🌿其他串口和I2C配置用于显示和调试输出。(这里根据个人需求配置,个人推荐还是使用软件I2C实现比较好,硬件I2C如果程序比较复杂,cpu处理各种中断,容易导致硬件I2C出错,导致显示画面异常的情况。)
    在这里插入图片描述
    在这里插入图片描述

  • 🌿其他时钟配置和工程生成就不展示了,根据个人情况配置。

⛳功能实现

  • 🌿完善按键中断回调内容
//重写回调函数
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{

    /*判断是中断引脚*/
    if(GPIO_Pin == KEY_Pin)
    {
        Trg++;
        HAL_GPIO_TogglePin(GPIOE, GPIO_PIN_5);//状态翻转
    }
}
  • 🌿定时器中断回调函数
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef* htim)
{

    static uint32_t click = 0;
    static char keyStatus = 0;
    static char LongPress = 0;
    if(htim ->Instance == TIM6)
    {
        if(++cnt_1ms >= 1000)
        {
            cnt_1ms = 0;
            HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_5);//状态翻转
        }
        if(Trg > 0)
        {
            keyStatus = HAL_GPIO_ReadPin(KEY_GPIO_Port, KEY_Pin);//读取按键状态
            click++;
            if((click > _debounce_ms) && (keyStatus == 1) && (LongPress == 0)) //1000
            {
                if((Trg == 1) || (Trg > 2)) //单击
                {
                    Trg = 0;
                    funIndex ++;
                    printf("_click_ms,%d\r\n", funIndex);
                    click = 0;//清零
                }
                if(Trg == 2) //双击
                {
                    Trg = 0;
                    funIndex += 2;
                    printf("_doubleClick %d\r\n", funIndex);
                    click = 0;//清零
                }
            }
            if((click > _press_ms) && (keyStatus == 0) && (LongPress == 0)) //1000
            {
                printf("_longPressStart\r\n");
                LongPress = 1;
            }
            if((LongPress == 1) && (keyStatus == 1))
            {
                LongPress = 0;
                Trg = 0;
                funIndex += 3;//松开才赋值
                click = 0;
                printf("_longPressStop %d\r\n", funIndex);
            }
        }
        if(funIndex > 8)funIndex = 0;

    }
}

  • 🌿oled驱动显示内容,可以根据个人使用的屏幕规格型号自行完善,个人使用的是SH1106 1.3“寸的OLED屏幕作为显示。
  • 🌿按键菜单显示内容参考网上的内容。
unsigned char funIndex = 0;//9和0->1-1
void menu11(void);
void menu12(void);
void menu21(void);
void menu22(void);
void menu23(void);
void menu31(void);
void menu32(void);
void menu33(void);
void menu34(void);
//定义按键操作数据
KEY_TABLE table[9] =
{
    {0, 0, 1, 0, 2, (*menu11)},
    {1, 0, 1, 1, 4, (*menu12)},
    {2, 2, 3, 0, 5, (*menu21)},
    {3, 2, 3, 0, 7, (*menu22)},
    {4, 4, 4, 1, 4, (*menu23)},
    {5, 5, 6, 2, 5, (*menu31)},
    {6, 5, 6, 2, 6, (*menu32)},
    {7, 7, 8, 3, 7, (*menu33)},
    {8, 7, 8, 3, 8, (*menu34)},
};

void ShowMenu(int16_t x, int16_t y,char *text)
{
    OLED_ShowString(x, y, text, 12);//x,y,字符串,字体大小
}

//一级菜单1
void menu11(void)
{

//    OLED_Clear();
    OLED_ShowString(36, 6, "menu1-1", 16);
}

//一级菜单2
void menu12(void)
{
//    OLED_Clear();
    OLED_ShowString(36, 6, "menu1-2", 16);
}

//二级菜单1
void menu21(void)
{
//    OLED_Clear();
    OLED_ShowString(36, 6, "menu2-1", 16);
}

//二级菜单2
void menu22(void)
{
//    OLED_Clear();
    OLED_ShowString(36, 6, "menu2-2", 16);
}

//二级菜单3
void menu23(void)
{
//    OLED_Clear();
    OLED_ShowString(36, 6, "menu2-3", 16);

}

//三级菜单1
void menu31(void)
{
//    OLED_Clear();
    OLED_ShowString(36, 6, "menu3-1", 16);
}

//三级菜单2
void menu32(void)
{
//    OLED_Clear();
    OLED_ShowString(36, 6, "menu3-2", 16);
}

//三级菜单3
void menu33(void)
{
//    OLED_Clear();
    OLED_ShowString(36, 6, "menu3-3", 16);
}

//三级菜单4
void menu34(void)
{
//    OLED_Clear();
    OLED_ShowString(36, 6, "menu3-4", 16);

}
  • 📝main主函数
int main(void)
{
    /* USER CODE BEGIN 1 */

    /* USER CODE END 1 */

    /* MCU Configuration--------------------------------------------------------*/

    /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
    HAL_Init();

    /* USER CODE BEGIN Init */

    /* USER CODE END Init */

    /* Configure the system clock */
    SystemClock_Config();

    /* USER CODE BEGIN SysInit */

    /* USER CODE END SysInit */

    /* Initialize all configured peripherals */
    MX_GPIO_Init();
    MX_I2C1_Init();
    MX_USART1_UART_Init();
    MX_I2C2_Init();
    MX_TIM6_Init();
    /* USER CODE BEGIN 2 */
    OLED_Init();
    HAL_TIM_Base_Start_IT(&htim6);
    ShowMenu(2, 0, "OneKey Mul-Menu");
    /* USER CODE END 2 */

    /* Infinite loop */
    /* USER CODE BEGIN WHILE */
    while(1)
    {
        /* USER CODE END WHILE */

        /* USER CODE BEGIN 3 */
        current = table[funIndex].operation;//根据需要获取对应需要执行的函数
        (*current)();//执行获取到的函数

    }
    /* USER CODE END 3 */
}

📚工程源码

链接:https://pan.baidu.com/s/1eR14Lpfjqm7nA0lvwbv5xg 
提取码:vs7f

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

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

相关文章

MIT6.5830 Lab1-GoDB实验记录(六)

MIT6.5830 Lab1-GoDB实验记录(六) – WhiteNights Site 标签:Golang 赛博坐牢之旅第一章第六节:接着上一节,补全heap_page剩下的函数。 开始坐牢 删除tuple 这个看起来…难度还没那么高,写一下试试吧。那…

一个易用的消息订阅发布系统-Pubsub.js

本文作者系360奇舞团前端开发工程师 简介 随着软件架构越来越复杂,如何有效地解决各个模块之间的通信问题变得尤为重要。一种常见的解决方案就是采用消息订阅发布机制。在这种模式下,每个模块只需要关注自己要发送或接收的消息,而不必关心其他…

Clickhouse表引擎

前言: 有关Clickhouse的前置知识详见: 1.ClickHouse的安装启动_clickhouse后台启动_THE WHY的博客-CSDN博客 2.ClickHouse目录结构_clickhouse 目录结构-CSDN博客 Cickhouse创建表时必须指定表引擎 表引擎(即表的类型)决定了&…

SpringBoot 使用EasyExcel 导出Excel报表(单元格合并)

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、导入依赖二、代码1. 导出简单的Excel2. 代码控制导出报表的格式 总结 前言 SpringBoot 使用Alibaba提供的EasyExcel导出Excel报表。 本文中涉及的业务逻辑…

C/C++内存管理——“C++”

各位CSDN的uu们你们好呀,好久没有更新小雅兰的C专栏啦,下面,小雅兰继续开始更新C专栏的内容!!!今天,小雅兰的内容是C和C的内存管理,下面,让我们进入C的世界吧&#xff01…

【Nginx40】Nginx学习:动静分离与日志分割

Nginx学习:动静分离与日志分割 放轻松放轻松,最后两篇文章学习的内容是比较轻松的。首先,我们来看看 Nginx 动静分离的概念,然后再看看怎么为 Nginx 做日志分割。内容都很简单,完全不需要有任何的压力。 动静分离 动静…

FPGA高端项目:图像缩放+GTX+UDP架构,高速接口以太网视频传输,提供2套工程源码加QT上位机源码和技术支持

目录 1、前言免责声明本项目特点 2、相关方案推荐我这里已有的 GT 高速接口解决方案我这里已有的以太网方案我这里已有的图像处理方案 3、设计思路框架设计框图视频源选择IT6802解码芯片配置及采集动态彩条跨时钟FIFO图像缩放模块详解设计框图代码框图2种插值算法的整合与选择 …

SSL证书申请安全审核失败?

随着HTTPS普及,申请安装使用SSL证书成为了我们的必备项。但这个SSL证书申请过程中,遇到问题也是不少。今天我们来浅了解一下SSL证书为什么会出现安全审核失败? SSL证书申请会出现安全审核失败的情况可能是以下原因: 域名验证不通…

docker-compose安装es以及ik分词同义词插件

目录 1 前言 2 集成利器Docker 2.1 Docker环境安装 2.1.1 环境检查 2.1.2 在线安装 2.1.3 离线安装 2.2 Docker-Compose的安装 2.2.1 概念简介 2.2.2 安装步骤 2.2.2.1 二进制文件安装 2.2.2.2 离线安装 2.2.2.3 yum安装 3 一键安装ES及Kibana 3.1 yml文件的编写…

多组学整合,快速定位关键代谢通路,解析分子机制

生物学是一种复杂的学科,往往单一组学无法探究想要了解的生物学问题,这时就要运用到多组学联合分析。近年来,多组学研究的不断发展和持续火热,越来越多的研究者开始将微生物组学和代谢组学联合起来。16s全长扩增子测序可提供细菌构…

JAVA集合学习和源码分析

一、结构 List和Set继承了Collection接口,Collection继承了Iterable Object类是所有类的根类,包括集合类,集合类中的元素通常是对象,继承了Object类中的一些基本方法,例如toString()、equals()、hashCode()。 Collect…

Mysql数据备份 —Navicat

一 Navicat 对于表的备份 根据自己的需求来选择 可以直接备份数据表 操作简单明了 二 Navicat 对于库的备份 对于数据库 直接通过转储SQL文件 保存结构和数据 需要新创建数据库 字符集和编码格式要对应 否则容易乱码 运行刚才生成的文件即可

【Git】GUI图形化界面的使用SSH协议IDEA集成Git

🥳🥳Welcome Huihuis Code World ! !🥳🥳 接下来看看由辉辉所写的关于Git的相关操作吧 目录 🥳🥳Welcome Huihuis Code World ! !🥳🥳 一. GUI图形化界面的使用 1.使用Gui​ 2.常…

Linux - 基础IO(Linux 当中的文件,文件系统调用接口,文件描述符)- 上篇

前言 首先,关于文件我们最先要理解的是,文件不仅仅存储的是数据,一个文件包括 内容 数据。内容好理解,就是我们先要这文件存储哪一些数据,这些数据就是文件的内容。 但是,在计算机当中,有两种…

【Maven教程】(十):使用 Hudson 进行持续集成—— 从Hudson的安装到任务创建 ~

Maven 使用 Hudson 进行持续集成 1️⃣ 持续集成的作用、过程和优势2️⃣ Hudson 简介与安装3️⃣ 准备 Subversion 仓库4️⃣ Hudson 的基本系统设置5️⃣ 创建 Hudson 任务5.1 Hudson 任务的基本配置5.2 Hudson 任务的源码仓库配置5.3 Hudson 任务的构建触发配置5.4 Hudson …

Linux:权限篇 (彻底理清权限逻辑!)

shell命令以及运行原理: Linux严格意义上说的是一个操作系统,我们称之为“核心(kernel)“ ,但我们一般用户,不能直接使用kernel。而是通过kernel的“外壳”程序,也就是所谓的shell,来…

Ubuntu18.04.6安装qt5.7.1(超级详细教程)

目录 1、下载对应Linux版本的qt 2、安装完qt,可能也要安装下对应的编译工具 1、下载对应Linux版本的qt (1)准备安装的是qt5.7.1:qt-opensource-linux-x64-5.7.1.run (2)在虚拟机进入存放qt安装包的目录…

jQuery HTML/CSS 参考文档

jQuery HTML/CSS 参考文档 文章目录 应用样式 示例属性方法示例 jQuery HTML/CSS 参考文档 应用样式 addClass( classes ) 方法可用于将定义好的样式表应用于所有匹配的元素上。可以通过空格分隔指定多个类。 示例 以下是一个简单示例&#xff0c;设置了para标签 <p&g…

CVE-2023-25194 Kafka JNDI 注入分析

Apache Kafka Clients Jndi Injection 漏洞描述 Apache Kafka 是一个分布式数据流处理平台&#xff0c;可以实时发布、订阅、存储和处理数据流。Kafka Connect 是一种用于在 kafka 和其他系统之间可扩展、可靠的流式传输数据的工具。攻击者可以利用基于 SASL JAAS 配置和 SASL …

django|报错SQLite 3.8.3 or later is required的解决方案

迁移原同事写的程序&#xff0c;到新服务器上边。运行报错。解决方案有三种 降低django版本升级sqlite3&#xff0c;不低于3.8.3版本修改django源码 方案一、降低django版本 卸载高版本django pip uninstall django安装低版本&#xff0c;如 pip install django2.1.7注意&…