关于旋转编码器(EC11)的使用(判断旋转方向,按键处理)

关于旋转编码器(EC11)的使用(判断旋转方向,按键处理)

文章目录

  • 关于旋转编码器(EC11)的使用(判断旋转方向,按键处理)
    • 零. 前言
    • 一. 注意事项
    • 二. 本文所述旋转编码器的旋转控制逻辑
    • 三. 旋转编码器判断代码(旋转方向,按键)
  • 四.最后提醒
    • 要是觉得对你有帮助的话,点个赞收个藏吧,我会开心一整天的😀

零. 前言

  本文对新手友好,代码可用,请放心食用
  在自己工作的时候使用到了类似EC11旋转编码器,理论上应该是在大学就用透了,但是我还是第一次使用,仅此记录下自己对于旋转编码器的使用与理解,并且我对旋转编码器的代码编写存在一些疑问,如果能够解答一下,欢迎在评论区留言,先谢谢各位小伙伴!
  编码器按键处理程序跟一般按键处理程序相同,因此在此不进行解释,仅贴代码
  程序考虑情况比较多,写的相对繁琐,如果不需要异常处理,请自行修改,因为我也不知道需要不需要
  

一. 注意事项

  请根据旋转编码器具体的电路连接,选择对应单片机对应端口GPIO的输入模式,分清楚旋转编码器不动作的时候给予单片机是高电平还是低电平
  旋转编码器一般有效的线是3根线,一根按键,两根用于输出信号判断顺时针和逆时针
  

二. 本文所述旋转编码器的旋转控制逻辑

  1. 该旋转编码器具有5线,分别是2xGND、K1、K2、K3,其中K1、K2用于旋转编码器正反转信号输出,K3为旋转编码器按键的信号输出
  2. 该旋转编码器不作动的时候均为高电平
  3. 旋转编码器旋转的时候K1和K2会相互输出不同相位的脉冲,以此区分顺逆时针旋转,如图所示:

在这里插入图片描述

图中清晰可见,想要判断出旋转编码器的CW和CCW旋转只需要关注第1和第3过程,只需要进行两次判断即可,顺时针为例:

1. (首次判断,过程1)K1低,K2高 ,给出第一次判断完成标志位
2. (等待,过程2)
3. (二次判断,过程3)K1低,K2高 ,判断结束
4. 清除所有标志位,等待下一次判断

但是否过程2的等待过程是没有用的呢,我认为不然,按照上面的逻辑,某一条线出现异常的时候则会误判(虽然我不清楚是否会出现这种异常,但是波形上是这样),如图所示:

在这里插入图片描述
以顺时针为例,按照上述判断流程,则1、2、3会被判断为cw逻辑,接下来的4、5、6会被判断为CCW逻辑,发生误判
因此,在我的程序会在过程2进行异常判断,判断逻辑以CW为例(结合图1):

1. (首次判断,过程1)K1低,K2高
2. (异常1判断,过程2)如果等待出现了第二次判断完成标志位,判断为异常,跳最后一步
3. (二次判断,过程3)K1低,K2高 ,给出第二次判断完成标志位
4. (最终判断,异常2判断,图1过程4)等待K1、K2高电平,判断是否经过了第二次判断,如果有,判断顺时针还是逆时针,判断结束,如果无,异常
5. 清除所有标志位,等待下一次判断

图CW异常
该判断逻辑下,第二判断会在过程3完成,给出二次判断结束标志位,但一直还没有进入最终判断(过程4),此时中途出现了异常(图2CW过程5),此过程即过程2,此时顺序为1->2->3->2,因此判断异常,直接跳到第5步
图CCW异常
同样的逻辑请套用到CCW逆时针异常的情况进行考虑,因为无法进行第二次判断(过程3),因此当出现K1、K2高电平,最终判断(图2CCW过程5),此时无法检测到第二次判断完成标志位,因此判断异常,直接跳到第5步
  

三. 旋转编码器判断代码(旋转方向,按键)

1. 命名规则
  单片机端口:类型_器件
  p->pin(引脚端口),pc->pin controller(引脚对应的控制寄存器)
  变量/标志位:类型_器件_特性_阶段
  f->flag(标志位),ecd->encoder(编码器),cw/ccw(顺/逆时针),s1/s2->首次、二次判断
  函数:器件_功能_特性
  encoder->编码器,rotate->旋转

2. 单片机端口声明
  请根据自己的单片机的型号以及定义方式进行定义,此处以芯圣的HC89F30xC 的单片机为例

#define		pc_edc_k1		P0M7
#define		pc_edc_k2		P0M5
#define		pc_edc_k3		P0M4

2. 单片机标志位以及函数声明
  请根据自己的单片机的型号以及定义方式进行定义,此处以芯圣的HC89F30xC 的单片机为例

volatile 	MakeBitsType 	 	flag_encoder;
#define		f_ecd_key			flag_encoder.bits.Bit0	//编码器中间按键,0:未按下,1:按下
#define		f_ecd_cw			flag_encoder.bits.Bit1	//编码器顺时针旋转标志位
#define		f_ecd_ccw			flag_encoder.bits.Bit2	//编码器逆时针旋转标志位
#define		f_ecd_cw_s1			flag_encoder.bits.Bit3	//编码器顺时针旋转第一次判断
#define		f_ecd_ccw_s1		flag_encoder.bits.Bit4	//编码器逆时针旋转第一次判断
#define		f_ecd_cw_s2			flag_encoder.bits.Bit5	//编码器顺时针旋转第二次判断
#define		f_ecd_ccw_s2		flag_encoder.bits.Bit6	//编码器逆时针旋转第二次判断
#define		f_ecd_ccw_s2		flag_encoder.bits.Bit6	//编码器逆时针旋转第二次判断
unsigned char cnt_edc_key;		//编码器按键消抖计数器
void Encoder_Keypress();	//编码器按键处理程序
void Encoder_Rotate();		//编码器旋转处理函数

3. 旋转编码判断程序
  程序最后的结果是出现顺逆时针的判断标志位f_ecd_cw 和f_ecd_ccw,然后该程序不会清除该标志位,因为该程序只是判断用,最后应该在其他功能函数使用过后,再进行清除

void Encoder_Rotate() 
{    	 
	if(b_dspall || !bbusysts || block || btemplock)		return;		
 	
	//旋转编码器端口初始化为上拉输入状态
	pc_edc_k1 = GPIO_In_PU;
	pc_edc_k2 = GPIO_In_PU;	
	
	if(!p_ecd_k1){					//k1低电平
		if(p_ecd_k2){				//k1低,k2高
			if(f_ecd_ccw_s1)		//第一次已经判断为逆时针状态,过程3
				f_ecd_ccw_s2 = 1;	//第二次判断为逆时针状态		
			else					//如果没有进行首次判断,进行判断,过程1	
				f_ecd_cw_s1 = 1;	//顺时针首次判断标志位置1	
			return;				
		}
		else{						//k1低电平,k2低电平,过程2
			if(!f_ecd_cw_s2 && !f_ecd_ccw_s2)	//如未出现第二次判断的标志位,判断正常
				return;				//正常则ruturn,保留标志位,异常清标志位
		}
	}
	else{							//k1高电平
		if(!p_ecd_k2){				//k1高电平,k2低电平
			if(f_ecd_cw_s1)		//第一次已经判断为顺时针状态,过程3
				f_ecd_cw_s2 = 1;	//第二次判断为顺时针状态
			else					//如果没有进行首次判断,进行判断,过程1	
				f_ecd_ccw_s1 = 1;	//逆时针首次判断标志位置1		
			return;
		}
		else{						//k1高电平,k2高电平时,为信号判断结束或无信号输入,过程4
			if(f_ecd_cw_s2)
				f_ecd_cw = 1;		//判断为顺时针
			else if(f_ecd_ccw_s2)	
				f_ecd_ccw = 1;		//判断为逆时针
			return;
		}
	}
	f_ecd_ccw_s2 = f_ecd_cw_s2 = f_ecd_ccw_s1 = f_ecd_cw_s1 = f_ecd_cw = 0;		//异常或判断完成后,清除标志位	
	return;
} 

4. 编码器按键处理程序

void Encoder_Keypress()
{ 
 	if(b_dspall)    return;				//全显示不响应
	
	pc_edc_k3 = GPIO_In_PU;				//上拉输入模式

	if(!p_edc_k3){						//中间按键按下
		if(cnt_edc_key)					//消抖
			cnt_edc_key--;
		if(!cnt_edc_key && !f_ecd_key){	//短按有效,长按无效
			f_ecd_key = 1;
			Key_start();
		}
	}
	else{								//无按键按下
		f_ecd_key = 0;					//标志位复位
		cnt_edc_key = 5;				//计数器清0
		return;
	}	
}

  

四.最后提醒

  程序考虑情况比较多,写的相对繁琐,如果不需要异常处理,请自行修改,因为我也不知道需要不需要,总的来说这些异常情况都是来自于器件有问题,说实话,硬件有问题关我软件什么事,对吧!但是还是跟着波形进行考虑了
  如果对这个异常情况是否需要处理有看法的,请在评论区告诉我,十分谢谢!

要是觉得对你有帮助的话,点个赞收个藏吧,我会开心一整天的😀

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

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

相关文章

什么是S参数

S参数是网络参数,定义了反射波和入射波之间的关系,给定频率的S参数矩阵指定端口反射波b的矢量相对于端口入射波a的矢量,如下所示: bS∙a 在此基础上,如下图所示,为一个常见的双端口网络拓扑图:…

sqli.labs靶场(54-65关)

54、第五十四关 提示尝试是十次后数据库就重置,那我们尝试union 原来是单引号闭合 id-1 union select 1,database(),(select group_concat(table_name) from information_schema.tables where table_schemadatabase()) -- 数据库:challenges&#xff0c…

visio对任意形状进行任意角度旋转调整

在使用VISIO进行绘图时,可能需要对任意的形状进行旋转,让其达到一致。如下图所示,灰色矩形与直线要保持一致,而实际在绘制矩形时,成水平朝向。需要对矩形进行调整,将其与直线倾斜保持一致。具体步骤如下&am…

(已解决)vueQQ邮箱注册发送验证码前端设计,如何发送验证码设计倒计时

我们之前已经通过前端测试成功完成qq邮箱动态验证码发送&#xff08;未使用redis&#xff0c;我准备自己了解完后&#xff0c;后期有时间补上&#xff09; 衔接文章&#xff1a; 1&#xff1a; spingboot 后端发送QQ邮箱验证码 2&#xff1a; 这段代码建设图形化界面 <di…

双向链表的插入、删除、按位置增删改查、栈和队列区别、什么是内存泄漏

2024年2月4日 1.请编程实现双向链表的头插&#xff0c;头删、尾插、尾删 头文件&#xff1a; #ifndef __HEAD_H__ #define __HEAD_H__ #include<stdio.h> #include<stdlib.h> #include<string.h> typedef int datatype; enum{FALSE-1,SUCCSE}; typedef str…

RabbitMQ-2.SpringAMQP

SpringAMQP 2.SpringAMQP2.1.创建Demo工程2.2.快速入门2.1.1.消息发送2.1.2.消息接收2.1.3.测试 2.3.WorkQueues模型2.2.1.消息发送2.2.2.消息接收2.2.3.测试2.2.4.能者多劳2.2.5.总结 2.4.交换机类型2.5.Fanout交换机2.5.1.声明队列和交换机2.5.2.消息发送2.5.3.消息接收2.5.4…

文件夹正在使用无法删除(重命名)解决办法

1、问题描述 相信都遇到文件夹无法删除&#xff0c;或者无法重命名的情况。如果将文件夹正在使用的文件都已经关闭后&#xff0c;文件夹仍旧无法删除或重命名。 这个时候大概率是有隐藏的进程没有关闭&#xff0c;可以重启电脑&#xff0c;或者采用下面的方式关闭对应文件夹的…

小白水平理解面试经典题目LeetCode 20. Valid Parentheses【栈】

20.有效括号 小白渣翻译 给定一个仅包含字符 ‘(’ 、 ‘)’ 、 ‘{’ 、 ‘}’ 、 ‘[’ 和 ‘]’ &#xff0c;判断输入字符串是否有效。 输入字符串在以下情况下有效&#xff1a; 左括号必须由相同类型的括号封闭。 左括号必须按正确的顺序关闭。 每个右括号都有一个对…

vscode 突然连接不上服务器了(2024年版本 自动更新从1.85-1.86)

vscode日志 ll192.168.103.5s password:]0;C:\WINDOWS\System32\cmd.exe [17:09:16.886] Got some output, clearing connection timeout [17:09:16.887] Showing password prompt [17:09:19.688] Got password response [17:09:19.688] "install" wrote data to te…

uniapp踩坑之项目:简易版不同角色显示不一样的tabbar和页面

1. pages下创建三个不同用户身份的“我的”页面。 显示第几个tabbar&#xff0c;0是管理员 1是财务 2是司机 2. 在uni_modules文件夹创建底部导航cc-myTabbar文件夹&#xff0c;在cc-myTabbar文件夹创建components文件夹&#xff0c;在components文件夹创建cc-myTabbar.vue组件…

【机器学习】机器学习简单入门

&#x1f388;个人主页&#xff1a;甜美的江 &#x1f389;欢迎 &#x1f44d;点赞✍评论⭐收藏 &#x1f917;收录专栏&#xff1a;matplotlib &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff0c;让我们共同学习、交流进…

【高质量精品】2024美赛C题高质量成品论文分享获取入口(后续会更新)

一定要点击文末的卡片&#xff0c;进入后&#xff0c;即可获取完整论文&#xff01;&#xff01; 首先&#xff0c;我们需要对缺失的 speed_mph 进行插补。缺失值处理是数据预处理的 重要环节之一。可以采用均值、中位数或者根据其他相关特征进行预测的方法来 填补缺失值。在这…

Packet Tracer - Configure IOS Intrusion Prevention System (IPS) Using the CLI

Packet Tracer - 使用CLI配置IOS入侵防御系统&#xff08;IPS&#xff09; 地址表 目标 启用IOS入侵防御系统&#xff08;IPS&#xff09;。 配置日志记录功能。 修改IPS签名规则。 验证IPS配置。 背景/场景 您的任务是在R1上启用IPS&#xff0c;扫描进入192.168.1.0网络…

Unity3d Cinemachine篇(完)— TargetGroup

文章目录 前言使用TargetGroup追随多个模型1. 创建二个游戏物体2. 创建TargetGroup相机3. 设置相机4. 完成 前言 上一期我们简单的使用了ClearShot相机&#xff0c;这次我们来使用一下TargetGroup 使用TargetGroup追随多个模型 1. 创建二个游戏物体 2. 创建TargetGroup相机 3…

刚刚晋升为管理者,还不会如何管理团队?你要重点关注这9个策略

管理团队需要明确团队目标、提前要求承诺、明确组织架构、团队高效协作、洞察员工、引入敏捷、执行可视化、及时反馈和复盘优化。 这样管理团队可以极大提高团队组织能力。团队组织能力强大的话&#xff0c;团队成员是可以实现自我管理的&#xff0c;会自我驱动去完成目标和执…

2024.2.5 vscode连不上虚拟机,始终waiting for server log

昨天还好好的&#xff0c;吃着火锅&#xff0c;做着毕设&#xff0c;突然就被vscode给劫了。 起初&#xff0c;哥们跟着网上教程有模有样地删除了安装包缓存&#xff0c;还删除了.vscode-server&#xff0c;发现没卵用&#xff0c;之前都是搜那个弹窗报错。 后来发现原来是vsco…

SpringBoot 全局异常处理

介绍 如果代码没有做异常处理&#xff0c;就会报框架错误&#xff0c;而这种格式不符合REST风格&#xff0c;也可以在每一个接口添加 try{ } catch { } 捕获异常&#xff0c;但是会非常的繁琐&#xff0c;这时候可以使用全局异常处理。 统一响应类 Data NoArgsConstructor …

掌握Linux du命令:高效查看文件和目录大小

今天我们在生产环境中的服务器上收到了有关/var磁盘目录使用率较高的警报。为了解决这一问题&#xff0c;我们进行了/var目录下一些大文件的清理和转移操作。在查找那些占用磁盘空间较多的文件时&#xff0c;我们频繁使用了du命令。在Linux系统中&#xff0c;du命令是一款功能强…

5G智能卷烟工厂数字孪生可视化平台,推进烟草行业数字化转型

5G智能卷烟工厂数字孪生可视化平台&#xff0c;推进烟草行业数字化转型。随着5G技术的不断发展&#xff0c;智能卷烟工厂数字孪生可视化平台成为了推进烟草行业数字化转型的重要手段。该平台将5G技术与数字孪生技术相结合&#xff0c;实现了对卷烟生产全过程的实时监控、数据分…

Springboot启动出现Waiting for changelog lock...问题

今天在开发的时候&#xff0c;Springboot启动的时候出现Waiting for changelog lock…问题. 问题原因&#xff1a;该问题就是发生了数据库的死锁问题&#xff0c;可能是由于一个杀死的liquibase进程没有释放它对DATABASECHANGELOGLOCK表的锁定&#xff0c;导致服务启动失败&…