旋转编码器好像不是单片机玩家很常用的器件,但是我们的开发板上有,原因如下:
旋转编码器挺好用的。电位器能旋转的角度有限,旋转编码器可以无限圈旋转;旋转时不连续,有卡点,适合对应离散数据。
开发板上选用的旋转编码器,使用起来简单、方便。
本来旁边的电位器(旋钮,以后会讲)一枝独秀,挺孤单的,我就配一个高度大致相同的旋转编码器陪伴它。
今天我想写旋转编码器,于是在网络上搜索了一下,相关资料很少。最基本地,旋转编码器的作用是将角位移、角速度等机械量转换为电信号。本文不求成为旋转编码器的百科全书,但会把 触点电刷式 增量式 旋转编码器的原理讲清楚。这里出现了两个定语,是对类别的限定;关于旋转编码器的分类,请自行百度。
开发板上的旋转编码器是从淘宝买的,淘宝商家提供了资料,这是本讲的主题。为避免广告嫌疑,我不能放链接上来,所以我就把它转换成图片放在文章里(请在新页面中查看):
我们从旋转编码器的原理开始。旋转编码器的内部是触点与电刷,可以看作按键:当两者接触时,开关闭合;反之断开。实际上它们的本质是一样的。在旋转时,按键会周期性地闭合、断开;如果一端接地,另一端接上拉电阻,就会有周期性高、低电平的脉冲信号产生。我们使用的旋转编码器每转过一圈会输出24个脉冲。
通过对脉冲进行计数,可以知道编码器转过的角度。如果不管方向,测量角度或角加速度等,用一个输出就够了。但是如果考虑方向,无论是顺时针还是逆时针转动,电平都是“高低高低高……”。为了获得方向的信息,需要使用两个输出,它们的相位相差90°,如图所示:
A和B是两个输出端,C端接地。当程序检测到A端由高电平变为低电平时(方法在按键那里讲过了),如果检测到B端是高电平(这就更简单了),那就是顺时针旋转;如果是低电平,那就是逆时针旋转。实际上不一定要检测A端的下降沿,只要按照这张图来,怎么都对。
库函数使用的检测方法是:A、B端由低低变为高低时,判为顺时针转过一格;由低低变为低高时,判为逆时针转过一格。这不是最好的方法(你可以想一下怎样改进,但是不要低估它的难度),但从实际使用上来看,只要用户不故意在两个卡点之间扭来扭去,这种方法是可以胜任的。
我们写一个用旋转编码器控制数码管显示数字的程序,也可以理解为对旋转编码器进行计数并用数码管显示。旋转编码器A和B端分别连接端口4和5,数码管连接6和7。程序的思路是:每隔一毫秒调用rotary_rotated(它和button_pressed函数类似——如果你还记得的话)检测编码器是否被转动以及转动的方向,并根据方向对计数器变量num进行增减。(为什么让num为uint8_t类型?)为了凸显旋转编码器的主题,数码管就用segment_auto来解决了。
#include #include #include
int main()
{
rotary_init(PIN_4, PIN_5);
segment_init(PIN_6, PIN_7);
segment_auto();
uint8_t num = 0;
while (1)
{
switch (rotary_rotated())
{
case ROTARY_CW:
++num;
break;
case ROTARY_ACW:
--num;
break;
default:
break;
}
segment_hex(num);
delay(1);
}
}
注意相邻卡点之间挤了4个AB端口的状态,因此延时不能过长。你可以试试更长的间隔。
关键字:AVR 单片机教程 旋转编码器
引用地址:
AVR单片机教程——旋转编码器
推荐阅读最新更新时间:2024-11-13 12:35
自制AVR高压编程器,解锁熔丝位错误的avr单片机
这段时间在用atmel的系列单片机at90usb128x/64x和atmega32u4设计键盘,有一块at90的单片机由于熔丝位设置错误被锁死,导致progisp无法给其刷程序,网上查了有几种方法解锁: 用有源晶振的输出脚给到单片机的晶振输入脚。(前提是单片机的熔丝位中设置为外部时钟) 用正常单片机对的晶振输出脚给到熔丝位错误的单片机的晶振输入脚。(前提是单片机的熔丝位中设置为外部时钟) 用正常单片机编程输出时钟给到熔丝位错误的单片机的晶振输入脚。(前提是单片机的熔丝位中设置为外部时钟) 由于我的单片机熔丝位设置成了内部时钟,以上三种方法无效,只能请出最后的救命稻草——高压编程。在百度上找的一些方案大都只支持atm
[单片机]
ATtiny2313 状态寄存器
状态寄存器包含了最近执行的算术指令的结果信息。这些信息可以用来改变程序流程以实现条件操作。如指令集所述,所有ALU 运算都将影响状态寄存器的内容。这样,在许多情况下就不需要专门的比较指令了,从而使系统运行更快速,代码效率更高。在进入中断服务程序时状态寄存器不会自动保存,中断返回时也不会自动恢复。这些工作需要软件来处理。 AVR 中断寄存器 SREG 定义如下: ·Bit 7 – I: 全局中断使能 I 置位时使能全局中断。单独的中断使能由其他独立的控制寄存器控制。如果I 清零,则不论单独中断标志置位与否,都不会产生中断。任意一个中断发生后I 清零,而执行RETI指令后I 恢复置位以使能中断。I 也可以通过SEI 和CLI 指令
[单片机]
AVR单片机—(三)、ATMEGA16驱动16*2点阵字符液晶模块—01
三、ATMEGA16驱动16*2点阵字符液晶 三—(01)、ATMEGA16驱动16*2点阵字符液晶 这篇文章只是简单的驱动并让1602显示,并没有用到读数据和读状态的部分,也没有用到读写检测(要是感兴趣的话还是写写这里吧) 1、那就是用什么样的液晶,又该怎么驱动,现在把datasheet的部分图片贴出来,看看,so easy~~的 1)就是它的引脚说明(个人感觉要想具体了解还是在网上搜搜吧~~我这里也就是简单了解~) 这里也就三个引脚需要注意就是RS、R/W、E,这三个引脚,传输数据的必用引脚,别的就不用详细介绍了吧~~(后面的程序就是根据这三个引脚的时序图来写的! 2)(说实话,我真的不太想详细说,因为好多人对于驱动
[单片机]
基于AVR单片机实现超声波测距的程序编写
#include #defineucharunsignedchar #defineuintunsignedint ucharint_flag; uintqian,bai,shi,ge; uinti; floatdistance; //AlphanumericLCDModulefuncTIons #asm .equ__lcd_port=0x18;PORTB #endasm #include //ExternalInterrupt0servicerouTIne interrupt voidext_int0_isr(void) {#asm( sei ) if(int_flag) { distance=i*17.3; } elsei
[单片机]
AVR128的程序——DS18B20与12864液晶时钟综合运用
#include macros.h #define uchar unsigned char #define uint unsigned int #define DQ_IN DDRE &= ~(1 PE6) #define DQ_OUT DDRE |= (1 PE6) #define DQ_CLR PORTE &= ~(1 PE6) #define DQ_SET PORTE |= (1 PE6) #define DQ_R PINE & (1 PE6) #define psbset DDRB |= (1 4) #define psbset PORTB |= (1 4) #define
[单片机]
ATtiny13 时钟系统及其分布
时钟系统及其分布 Figure 11为AVR的主要时钟系统及其分布。这些时钟并不需要同时工作。为了降低功耗, 可以通过使用不同的睡眠模式来禁止无需工作的模块的时钟,详见ATtiny13 P26“ 电源管理及睡眠 模式 ” 。时钟系统详见 Figure 11。 CPU 时钟- clkCPU CPU时钟与操作AVR内核的子系统相连,如通用寄存器文件、状态寄存器及保存堆栈指针的数据存储器。终止CPU 时钟将使内核停止工作和计算。 I/O 时钟- clkI/O I/O时钟用于主要的I/O模块,如定时器计数器。 I/O时钟还用于外部中断模块。要注意的是有些外部中断由异步逻辑检测,因此即使 I/O时钟停止了这些中断仍然可以得到监控。 Fl
[单片机]
基于AVR单片机的无线远程数据采集终端的研制与开发
一、引言 随着城市供水规模扩大,城市管网不断增大,厦门自来水公司原有遥测系统难以适应生产调度需求。要求有一套可靠、快速的调度遥测系统,综合国内RTU(Remote Terminal Unit 远程测控终端)的发展状况及公司的具体情况,厦门自来水公司独立研制开发了一套新的基于AVR单片机及专用MODEM芯片的MTU(Master Terminal Unit中心调度机)、RTU无线电遥测系统。系统的整体结构如图1,其中粗黑框部分为系统的核心MTU、RTU。 分散地分布在全市的管网监测点上的远端RTU(系统可带256个RTU)采集数据,进行数据处理后通过无线电台向中心调度端发送数据,中心调度端接收到数据后进行数据处理,数据存储,并送
[单片机]
AVR的外部中断INT示例程
使用AVR的外部中断INT1检测PD3Key,如果有按键按下,则唤醒休眠的MCU,并使它的PB口的LED做加1指示。 #include iom16v.h #include D:ICC_HCmmICC.H #define DISP_DDR DDRB #define DISP_PORT PORTB #define IN_PD3 cbi(DDRD,3) //PD3 #define SET_PD3 sbi(PORTD,3) #define GET_PD3 gbi(PIND,3) /*---------------------------------------------------
[单片机]