旋转编码器SIQ-02FVS3驱动(AuroraFOC)

一. 简介

本次将基于AuroraFOC开发板,来教大家如何将旋转编码器按键优雅地使用起来,为大家开发多功能按键提供一种思路。请添加图片描述

开发环境

  1. STM32CubeMX HAL库
  2. Clion

作者: FPGA之旅(ValentineHP)

二. 原理(图)介绍

旋转编码器按键原理图如下,它有左旋转、右旋转和按下这三种状态。在默认情况下,EC_AR和EC_BR均为高电平,旋转的时候,它们会依次变为低电平,并且持续一小段时间后变为高电平,不同方向旋转的时候,它们电平的变化会有一个相位差,根据这个方向就可以来判断旋转的方向了。

EC_KEYR默认情况应该是悬空的,在按键按下的时候会拉低,使用的时候需要注意,单片机内部需要将IO口设置为上拉模式,否则读到的值一直为0。
请添加图片描述
请添加图片描述

作者: FPGA之旅(ValentineHP)

三. 编程实现

  1. 定义旋转编码器的状态类型。状态的扩展上主要是在按键上,多了长按和双击,多的两种状态的实现是设计的难点。
//EncoderKey 状态
typedef enum EncoderKeyState{
    EncoderKey_None = 0,
    EncoderKey_Click,       //单击
    EncoderKey_LClick,      //长按
    EncoderKey_DClick,      //双击
    EncoderKey_Left,        //左边
    EncoderKey_Right        //右边
}EncoderKeyState;
  1. 先挑简单的实现: 左右旋转检测(在FPGA驱动电机的文章中已经介绍过了,原理一样)。设置旋转编码器的A相为电平中断,中断类型为上下边沿,那么第一次进入中断一定是下降沿,第二次进入中断一定是上升沿,通过这两次进入中断来判断B相的电平,结合上图,就可以判断出编码器的方向了。
 else if( GPIO_Pin == EC_AR_Pin){ //旋转检测
        if( ec_flag == 0){
            if( HAL_GPIO_ReadPin(EC_AR_GPIO_Port,EC_AR_Pin) == 1)   //消除误差,防止误判
                ec_flag = 0;
            else  if( HAL_GPIO_ReadPin(EC_BR_GPIO_Port,EC_BR_Pin) == 1)
                ec_flag = 1;
            else
                ec_flag = 2;
        }
        else{
            if( HAL_GPIO_ReadPin(EC_AR_GPIO_Port,EC_AR_Pin) == 0) //消除误差,防止误判
                ;//ec_flag = 0;
            else if( ec_flag == 1 && HAL_GPIO_ReadPin(EC_BR_GPIO_Port,EC_BR_Pin) == 0)
                key_state = EncoderKey_Right;
            else if(ec_flag == 2 && HAL_GPIO_ReadPin(EC_BR_GPIO_Port,EC_BR_Pin) == 1)
                key_state = EncoderKey_Left;
            ec_flag = 0;
        }
      //  usb_printf("%d %d %d \r\n",ec_flag,HAL_GPIO_ReadPin(EC_AR_GPIO_Port,EC_AR_Pin),HAL_GPIO_ReadPin(EC_BR_GPIO_Port,EC_BR_Pin));
    }
  1. 终于到了按键检测。需要检测三种不同的按键状态,就需要使用到定时器了,CubeMX默认是使用了SysTick滴答定时器作为了基本的时钟源,所以就不需要使用额外的定时器了。我们可以通过HAL_GetTick这个函数获取当前系统运行的时间戳,这个函数至关重要,也是检测三种不同按键状态的关键

    同样在CubeMX设置按键为电平中断,中断类型为下降上升沿中断(按键默认电平为高电平)。

    1. 第一次按键按下,这个时候会进入中断,我们获取当前系统运行的时间戳,第一次按键释放,也会进入中断,通过两次获取的时间戳差值判断这次按键是否有效(进行消抖处理),这就是检测单击。
    2. 第一次按键释放,通过两次获取的时间戳差值,是否达到了长按的时间的标准,来判断是否为长按。
    3. **双击啦!!!**第二次按键按下,进入中断后,将第一次按键释放时的时间戳 ,与当前时间戳进行比较,两个差小于设置值,说明这次是双击。双击中包含了单击的这一操作,这就会有个冲突,要解决这个冲突其实非常简单,那就是在获取按键状态的时候,如果按键的状态为单击,就来判断当前的时间戳和第一次按键释放时的时间戳的差值是否大于了双击的标准 ,是的话,就返回单击,否则的话就返回没有动作发生。
    /* 获取按键状态 如果按键按下 则会清除按键状态 */
    EncoderKeyState EncoderKey_Driver::get_key_state(){
        EncoderKeyState state;
    
        if( key_state == EncoderKey_Click){
            if((int32_t)HAL_GetTick() - (int32_t)key_tick < 400 || (int32_t)key_tick - (int32_t)HAL_GetTick() > 400)
                return EncoderKey_None;
        }
    #ifdef DEBUG_PRINTF
        if( key_state != EncoderKey_None){
            usb_printf("%d\r\n",key_state);
        }
    #endif
        state = key_state;
        key_state = EncoderKey_None;
        return state;
    }
    void EncoderKey_Driver::EncoderKey_EXTI_Callback(uint16_t GPIO_Pin) {
        //按键
        if( GPIO_Pin == EC_KEY_Pin){
            if(HAL_GPIO_ReadPin(EC_KEY_GPIO_Port,EC_KEY_Pin) == 0) {
                if (HAL_GetTick() - key_tick < 400)
                    dclick_flag = 1;
                else
                    dclick_flag = 0;
                key_tick = HAL_GetTick();
            }
            else{
                if( HAL_GetTick() - key_tick > 800)   //长按
                    key_state = EncoderKey_LClick;
                else if(HAL_GetTick() - key_tick  > 5){
                    key_state = (dclick_flag == 0)? EncoderKey_Click : EncoderKey_DClick;
                }
                dclick_flag = 0;
            }
        }
    }
    

是不是总体是还是比较简单的,如果大家有更好的实现方法,可以一起交流交流哦!!

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

《动手学深度学习(PyTorch版)》笔记3.1

Chapter3 Linear Neural Networks 3.1 Linear Regression 3.1.1 Basic Concepts 我们通常使用 n n n来表示数据集中的样本数。对索引为 i i i的样本&#xff0c;其输入表示为 x ( i ) [ x 1 ( i ) , x 2 ( i ) , . . . , x n ( i ) ] ⊤ \mathbf{x}^{(i)} [x_1^{(i)}, x_2…

【cdh】hive执行SQL提示缺少3.0.0-cdh6.3.2-mr-framework.tar.gz文件

问题&#xff1a;执行SQL报错提示缺少文件 异常信息如下 在hdfs上查看的时候连文件夹都没有&#xff0c;所以这个异常会抛出&#xff0c;但是我是基于CDH搭建的&#xff0c;可以直接基于下面操作 执行完成之后查看HDFS文件 重新执行SQL发现可以正常执行了

ad18学习笔记十六:v割

所谓“V割”是印刷电路板&#xff08;PCB&#xff09;厂商依据客户的图纸要求&#xff0c;事先在PCB的特定位置用转盘刀具切割好的一条条分割线&#xff0c;其目的是为了方便后续SMT电路板组装完成后的分板之用&#xff0c;因为其切割后的外型看起来就像个英文的“V”字型&…

【机器学习】强化学习(六)-DQN(Deep Q-Learning)训练月球着陆器示例

概述 Deep Q-Learning&#xff08;深度 Q 学习&#xff09;是一种强化学习算法&#xff0c;用于解决决策问题&#xff0c;其中代理&#xff08;agent&#xff09;通过学习在不同环境中采取行动来最大化累积奖励。Lunar Lander 是一个经典的强化学习问题&#xff0c;其中代理的任…

教学质量常态监控与评价平台

教学质量常态监控与评价平台&#xff0c;以提高教学质量为目标导向&#xff0c;利用Al、大数据等新型技术手段作为技术支撑&#xff0c;服务于教学质量科、督导、教师、学生等角色&#xff0c;基于教学过程数据&#xff0c;关注教师的教学内涵&#xff0c;覆盖了对教师、课堂、…

【刷题】 leetcode 面试题 08.05.递归乘法

递归乘法 1 题目描述2 思路一&#xff08;返璞归真版&#xff09;3 思路二&#xff08;二进制乘法器版&#xff09;4 思路三&#xff08;变态版&#xff09;Thanks♪(&#xff65;ω&#xff65;)&#xff89;谢谢阅读下一篇文章见&#xff01;&#xff01;&#xff01; 1 题目…

数据结构.双链表循环链表

一、1.双链表的初始化 void InitLNode(LinkList& L)//双链表的初始化 {L (LNode*)malloc(sizeof(LNode));L->prior NULL;L->next NULL;} 2.双链表的插入 void DInsert(LNode* p,LNode*s)//在p结点后面插入s结点 {s->next p->next;s->next->prior s;…

使用dockers-compose搭建开源监控和可视化工具

简介 Prometheus 和 Grafana 是两个常用的开源监控和可视化工具。 Prometheus 是一个用于存储和查询时间序列数据的系统。它提供了用于监控和报警的数据收集、存储、查询和图形化展示能力。Prometheus 使用拉模型&#xff08;pull model&#xff09;&#xff0c;通过 HTTP 协议…

微信小程序(十九)组件通信(子传父)

注释很详细&#xff0c;直接上代码 上一篇 新增内容&#xff1a; 1.定义触发事件向父组件传输数据 2.父组件绑定绑定触发事件并获取数据 源码&#xff1a; myNav.wxml <view class"navigationBar custom-class" style"padding-top: {{test}}px;">&l…

【GitHub项目推荐--不错的 React 开源项目】【转载】

用 React Flow 连接你的想法 用 React Flow 连接你的想法&#xff0c;这是一个高度可定制的库&#xff0c;基于 React 用于构建基于节点的 交互式 UI、编辑器、流程图和图表。 开源地址&#xff1a;https://github.com/wbkd/react-flow Bulletproof React 一个简单、可扩展且…

什么时跨域问题和如何解决跨域问题

什么是跨域问题&#xff1f;解决跨域的方案都有哪些&#xff1f;日常工作中会使用哪种解决方案&#xff1f; 跨域问题指的是不同站点之间&#xff0c;使用ajax无法互相调用的问题。跨域问题本质是浏览器的一种保护机制&#xff0c;它的初衷是为了保证用户的安全&#xff0c;防…

一道CTF签到题

点击题目的签到&#xff0c;提示&#xff1a; 看来需要修改请求的源地址&#xff1a; 上来我先尝试了我最常用的xff&#xff0c;结果不行&#xff0c;于是尝试了其他的几个常用请求头&#xff1a; 1.host头 如果后端从host取值来判断是否是本地就可以通过此方法进行绕过&…

【语录】岁月

中年 写中年&#xff0c;应该是年少励志三千里 踌躇百步无寸功&#xff0c;转眼高堂已白发 儿女蹒跚学堂中&#xff0c;不如意事常八九&#xff0c;可与人言无二三 可是诸位&#xff0c;不用悲伤&#xff0c;稻盛和夫说&#xff0c; 人生并不是一场物质的盛宴&#xff0c;而是…

面经基础版案例(路由,请求渲染,传参,组件缓存)

文章目录 1.案例效果分析2.配置一级路由&#xff08;首页&#xff0c;详情&#xff09;3.配置二级路由4.导航高亮效果5.首页的请求渲染6.传参&#xff08;查询参数 $ 动态路由&#xff09;7.详情页渲染8.组件缓存kepp-alive9.总结 1.案例效果分析 2.配置一级路由&#xff08;首…

MGRE综合实验

一&#xff1a;实验要求 二&#xff1a;实验过程 1、配置IP [r1]int g0/0/0 [r1-GigabitEthernet0/0/0]ip add 192.168.1.1 24 [r1-GigabitEthernet0/0/0]q [r1]int s4/0/0 [r1-Serial4/0/0]ip add 15.0.0.1 8 [r2]int g0/0/0 [r2-GigabitEthernet0/0/0]ip add 192.168.2.1 2…

【高效开发工具系列】Java读取Html

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

STM32 SDIO接口传输中的错误处理和中断优化技巧

在 STM32 的 SDIO 接口传输中&#xff0c;错误处理和中断优化是确保传输稳定和可靠性的重要方面。下面将介绍一些常用的错误处理和中断优化技巧&#xff0c;并给出相应的代码示例。 ✅作者简介&#xff1a;热爱科研的嵌入式开发者&#xff0c;修心和技术同步精进 ❤欢迎关注我的…

Redis 持久化详解:RDB 与 AOF 的配置、触发机制和实际测试

什么是持久化&#xff1f; 就是 Redis 将内存数据持久化到硬盘&#xff0c;避免从数据库恢复数据。之所以避免从数据库恢复数据是因为后端数据通常有性能瓶颈&#xff0c;大量数据从数据库恢复可能会给数据库造成巨大压力。 Redis 持久化通常有 RDB 和 AOF 两种方式&#xff…

VMware虚拟机部署Linux Ubuntu系统

本文介绍基于VMware Workstation Pro虚拟机软件&#xff0c;配置Linux Ubuntu操作系统环境的方法。 首先&#xff0c;我们需要进行VMware Workstation Pro虚拟机软件的下载与安装。需要注意的是&#xff0c;VMware Workstation Pro软件是一个收费软件&#xff0c;而互联网中有很…

一道CTFsql注入的问题

打开页面一个登录框&#xff0c;我甚至都没先弱口令登录&#xff0c;直接开始sql测试&#xff0c;结果测到最后发现没有&#xff0c;直接admin/admin就就去了&#xff0c;下次遇到登录框请先测试弱口令&#xff0c;ok&#xff1f; 登录成功后&#xff1a; 这句话提示中提到了…