STM32学习100步之第四十七-四十八步——旋转编码器驱动程序
旋转编码器
旋转编码器是一种可以左右旋转,同时也可以按下,也可以按下旋转的器件,通过左右旋转对应着内部不同开关的导通,同时按下也可以旋转,由此看来旋转编码器可以实现很复杂的功能,简单的通过左右旋转可以调节音量、亮暗等功能,按键可以发挥普通按键的作用,按下按键的同时左右旋转又可以区别普通旋转的按键,因此可以用一个旋转编码器同时调节音量和亮暗(举例),同时也可以通过不同的转速实现不同的功能,总之,功能很复杂,作为初学者,本次只介绍普通旋转和按键作用,同时分析卡死的问题。
开发板上的端口映射原理图如下:其中旋转编码器和模拟量摇杆线路复用,使用其中一个器件时,将对应的跳线帽断开即可。
旋转编码器的具体原理图如下所示,我们开发板中的1和4接地,如上图所示,按键按下时,开关1闭合,1和2接通,当向左右旋转时,开关2和3以一定的先后顺序闭合,也可能同时闭合,时序电路如下图所示,另外卡死是由于旋转编码器内部的机械结构不灵敏,正常情况下,每旋转一次,旋转编码器都会正常的咔哒一声,但是极少数情况下,会卡在咔哒声之前,即旋钮停在了两个格段之间,使得K2一直保持低电平,单片机退不出循环,从而导致卡死。
具体的程序如下,其中读取旋钮旋转的方向的方法有两种。1、同时读取两个按键的状态,如果同时读到K2是高电平、K3是低电平,则是方向1,如果同时读到K2是低电平、K3是高电平,则是方向2。2、只读取K2的状态,当K2的状态是低电平的时候,取一段及短的时间再判断K3的状态,若K3的状态是低电平,则是方向1,若K3的状态是高电平,则是方向2。卡死的状态变化通过标志位KUO以及累加COUT来判断。
读取程序如下:
u8 ENCODER_READ(void){ //接口初始化u8 a;//存放按键的值u8 kt;a=0;if(GPIO_ReadInputDataBit(ENCODER_PORT_A,ENCODER_L))KUP=0; //判断旋钮是否解除锁死if(!GPIO_ReadInputDataBit(ENCODER_PORT_A,ENCODER_L)&&KUP==0){ //判断是否旋转旋钮,同时判断是否有旋钮锁死delay_us(100);kt=GPIO_ReadInputDataBit(ENCODER_PORT_B,ENCODER_R); //把旋钮另一端电平状态记录delay_ms(3); //延时if(!GPIO_ReadInputDataBit(ENCODER_PORT_A,ENCODER_L)){ //去抖if(kt==0){ //用另一端判断左或右旋转a=1;//右转}else{a=2;//左转}cou=0; //初始锁死判断计数器while(!GPIO_ReadInputDataBit(ENCODER_PORT_A,ENCODER_L)&&cou<60000){ //等待放开旋钮,同时累加判断锁死cou++;KUP=1;delay_us(20); //}}}if(!GPIO_ReadInputDataBit(ENCODER_PORT_A,ENCODER_D)&&KUP==0){ //判断旋钮是否按下 delay_ms(20);if(!GPIO_ReadInputDataBit(ENCODER_PORT_A,ENCODER_D)){ //去抖动a=3;//在按键按下时加上按键的状态值//while(ENCODER_D==0); 等等旋钮放开}}return a;
}
其中delay_us(100)是等待一小段时间,等待稳定之后检测K3的按键值,另外delay_ms(3)是消抖函数,因为在电平的变化时,会产生抖动,消抖之后如果仍然有效,则给相应的按键赋值。其中最后一段的锁死判断程序用了两个&&,即同时起作用,第一个条件是等待旋转之后的自动弹起,当弹起时,直接退出while语句这时KUP标志位为1,注意此时是正常的状态,通过单片机的不断扫描,下一次再进入读取函数后会通过第一个判断语句,将KUP清为0,如果真的是锁死状态则第一个条件恒为真,执行第二个为真的条件,这时延时大概1.2秒之后退出了循环(正常情况下,旋转的弹起时间必然小于1.2秒),这时仍然是锁死状态,单片机再次进入读取函数时KUP不会被清为0(因为锁死状态不满足if语句),因为一个KUP=1,所以以后的读取函数所有的语句都不被执行,这时单片机处于不被卡死的状态,即完成了卡死的程序处理。
主函数实例如下:
int main (void){//主程序u8 a=0,b=0,c=0x01;RCC_Configuration(); //系统时钟初始化 RTC_Config(); //RTC初始化ENCODER_Init(); //旋转编码器初始化TM1640_Init(); //TM1640初始化TM1640_display(0,a/10); //显示数值TM1640_display(1,a%10);TM1640_display(2,20);TM1640_display(3,20);TM1640_display(4,20);TM1640_display(5,20);TM1640_display(6,20);TM1640_display(7,20);while(1){b=ENCODER_READ(); //读出旋转编码器值 if(b==1){a++;if(a>99)a=0;} //分析按键值,并加减计数器值。if(b==2){if(a==0)a=100;a--;}if(b==3)a=0;if(b!=0){ //如果有旋转器的操作TM1640_display(0,a/10); //显示数值TM1640_display(1,a%10);}// TM1640_led(c); //与TM1640连接的8个LED全亮
// c<<=1; //数据左移 流水灯
// if(c==0x00)c=0x01; //8个灯显示完后重新开始
// delay_ms(150); //延时}
}
这里需要注意的是,如果同时将下面的流水灯程序打开之后,因为延时函数的存在,会使得旋转按钮便的不灵敏,这是因为延时函数占用了CPU空间,从而使得扫描的频率变慢,使得灵敏度降低,解决的方法有两种。1、在延时函数中加入读取按键旋转的函数,同时扫描读取显示即可。2、将K2开关接入外部中断触发,即将读取函数放入中断函数,一旦旋转按钮,则直接从延时函数进入中断读取,进而判断扫描显示,这也是方法2的优势,只占用了一个中断资源。
图中所有图片出自洋桃电子。
STM32学习100步之第四十七-四十八步——旋转编码器驱动程序相关推荐
- (十七 ~ 二十八)巴菲特与索罗斯的投资习惯:明确你的投资目标
作者:chen_h 微信号 & QQ:862251340 微信公众号:coderpai (一)巴菲特与索罗斯的投资习惯:思考习惯的力量 (二)巴菲特与索罗斯的投资习惯:七种致命的投资信念 (三 ...
- 【Vue学习】—Vue UI组件库(二十八)
[Vue学习]-Vue UI组件库(二十八) 一.移动端常用的UI组件库 二.PC端常用的UI组件库 三.具体使用自行查看文档,这里就不做概述了
- 读书笔记:汇编语言 第三版 王爽 清华出版社 章十六 章十七 章十八
第十六章 直接定址表16.1 描述了单位长度的标号地址标号,表征了位置的偏移地址label:数据标号,表征了一段内存空间的物理地址和长度,增强型地址标号段地址,数据标号所在段的关联段寄存器,assum ...
- STM32学习100步之第七十二-七十六步——U盘、TF卡与单片机的通信(利用SPI总线通信)
SPI通信 由图中可以看出,SPI有四条主要的信号线,即MISO(主机输入从机输出).MOSI(主机输出从机输入),CS是对于从机而言的,当为0时,允许通信,由主机控制是否选通,另外可以使用单片机的I ...
- STM32学习100步之第八十九步-第九十一步——加速度传感器MPU6050
MPU6050传感器 MPU-6000 ( 605Q)为全球首例整合性6轴运动处理组件,相较于多组件方案,免除了组合陀螺仪鸟加速器时间轴之差的问题,减少了大量的封装空间.当连接到三轴磁强计时,MPU- ...
- STM32学习100步之第三十二步——MIDI音乐程序
什么是MIDI音乐 MIDI音乐的产生原理 编写MIDI音乐 代码解读 什么是MIDI音乐 HIDI(Musical Instrument Digital Interface)乐器数字接口 是20世纪 ...
- PyTorch 学习笔记(六):PyTorch的十八个损失函数
本文截取自<PyTorch 模型训练实用教程>,获取全文pdf请点击:https://github.com/tensor-yu/PyTorch_Tutorial 文章目录 1.L1loss ...
- 深入浅出CChart 每日一课——快乐高四第五十八课 大道至简,炫彩界面库之接口代码优化
上节课对CChart在新版炫彩界面库中的使用进行了详细说明,大家看到CChart对炫彩界面库具有完美的兼容性. 但是呢,大家也发现了,要实现CChart的完整功能,需要用户编写的代码不少,杂七杂八地接 ...
- PostgreSQL的学习心得和知识总结(一百一十八)|深入理解PostgreSQL数据库 匿名块 的词法解析和语法解析流程(DRCLARE子句)
目录结构 注:提前言明 本文借鉴了以下博主.书籍或网站的内容,其列表如下: 1.参考书籍:<PostgreSQL数据库内核分析> 2.参考书籍:<数据库事务处理的艺术:事务管理与并发 ...
最新文章
- ai皮肤检测分数_智能AI皮肤检测仪三步走话术
- wxWidgets:Sizer 概览
- Web服务安全性和SOA路线图的人为维度
- C++学习笔记1:virtual 继承
- 使用Xerte创建简单的在线学习资料的指南
- 如何删除尾随换行符?
- (Foxit PDF阅读器设置)禁止改变当前缩放比例,改善书签跳转阅读体验
- 【算法学习】纯高斯模糊算法处理灰度图片
- C中处理Python的Numpy数组的代码范例
- vant组件二次封装-下拉刷新列表组件
- bootstraptable 一条数据跨行_据说它是唐山市拥有奶茶店最多的一条街,你一定也逛过!...
- delphi 发送html邮件,delphi – 以HTML格式发送电子邮件
- vue嵌入app中——首次加载慢的动画
- Modesim仿真出现vlog-2388问题
- 用于信号处理的Xilinx FPGA XC7K325T PCIeX8 FMC处理板卡
- 大数据分析练习-第八届泰迪杯A题-基于数据挖掘的上市公司高送转预测
- Python实现AES中ECB模式pkcs5padding填充加密/解密(需要加密文档中可以有中文)
- Mysql内核查询成本计算
- Mybatis捕捉异常
- seo搜索引擎优化教程:新网站怎么做seo优化才能提高收录?
热门文章
- ubuntu16.04下配置samba共享服务支持Windows访问
- 问题解决FileNotFoundError: [Errno 2] No such file or directory: '/tmp/_MEImHg8uh/django/contrib/auth/pas
- 苹果手机数据线充不了电_手机充不满电?教你四个办法解决!
- ROS Melodic中costmap2D详解
- Bregman Divergence
- bootstrap datetimepicker的时间变成1899年
- foxmail邮箱手机客户端设置
- ARM WFI和WFE
- 懒人笔记-mupdf篇<ubuntu>
- acw周赛 - 点的赋值 —— 二分图染色