模块图片
测试平台:STC89C516单片机 晶振:12MHz 其他单片机(如STC12单片机)或晶振,请在程序的LCD1602.c和rotary_encoder.c文件中修改延时函数
连线如图(连线的接口在程序的port.h文件里)
测试代码功能: 将程序下载到开发板,LCD显示0FF,显示数字000. 按下旋转编码器的按键,OFF变为ON,转动旋转编码器就可以在LCD1602中看到数字变化. 再次按下旋转按键,ON变为OFF,此时转动旋转编码器不可以在LCD1602中看到数字变化.
结尾:
测试程序的注释也比较详细,自我感觉这个程序对较慢的转速和正常的转速的兼容性都比较好,只有极少数情况出现丢步,已经实现较好的实现了旋转编码器的功能了.
本帖测试程序参考过以下帖子
http://www.51hei.com/bbs/dpj-93972-1.html
单片机源程序如下:
- #include <intrins.h>
- #include "public.h"
- #include "rotary_encoder.h"
- #include "LCD1602.h"
- #include "port.h"
- void rotary_encoder_delay50us()//12.000MHz
- {
- u8 i;
- _nop_();
- i=22;
- while(--i);
- }
- void rotary_encoder_delay10ms() //12.000MHz
- {
- u8 i,j;
- i=20;
- j=113;
- do
- {
- while (--j);
- }while (--i);
- }
- //旋转编码器初始化
- void rotary_encoder_init()
- {
- ROTARY_ENCODER_CLK=1;
- ROTARY_ENCODER_DT=1;
- ROTARY_ENCODER_SW=1;
-
- IT0=1;
- EX0=1;
- EA=1;
-
- LCD1602_print_char(0,0,'O');
- LCD1602_print_char(0,1,'F');
- LCD1602_print_char(0,2,'F');
-
- LCD1602_print_char(1,0,'0'+0);
- LCD1602_print_char(1,1,'0'+0);
- LCD1602_print_char(1,2,'0'+0);
- }
- //扫描旋转编码器,返回值为1代表正转,返回值为0代表反转,返回值为0xFF代表未旋转或旋转错误
- u8 scan_rotary_encoder()
- {
- u8 rotary_encoder_state;//旋转编码器状态
- u16 forced_out;//强制退出
-
- //旋转编码器状态
- //如果在刚开始ROTARY_ENCODER_CLK和ROTARY_ENCODER_DT都为1,则状态为1
- //如果在刚开始ROTARY_ENCODER_CLK和ROTARY_ENCODER_DT都为0,则状态为0
- if((ROTARY_ENCODER_CLK)&&(ROTARY_ENCODER_DT)) rotary_encoder_state=1;
- else if((!ROTARY_ENCODER_CLK)&&(!ROTARY_ENCODER_DT)) rotary_encoder_state=0;
-
- //ROTARY_ENCODER_CLK和ROTARY_ENCODER_DT为同一电平时检测
- if(((ROTARY_ENCODER_CLK)&&(ROTARY_ENCODER_DT))||((!ROTARY_ENCODER_CLK)&&(!ROTARY_ENCODER_DT)))
- {
- //用最多150ms时间来等待ROTARY_ENCODER_CLK电平或ROTARY_ENCODER_DT电平变化(此时AB为11或00)
- forced_out=3000;
- while(((ROTARY_ENCODER_CLK)&&(ROTARY_ENCODER_DT))||((!ROTARY_ENCODER_CLK)&&(!ROTARY_ENCODER_DT)))
- {
- --forced_out;
- rotary_encoder_delay50us();
- if(!forced_out) return 0xFF;//超时则强制退出,返回错误码
- }
-
- //每次电平变化必定旋转了编码器,电平变化后要消抖
- rotary_encoder_delay10ms();
-
- //当ROTARY_ENCODER_CLK为低电平,ROTARY_ENCODER_DT为高电平时
- if((!ROTARY_ENCODER_CLK)&&(ROTARY_ENCODER_DT))
- {
- //用150ms时间来等待ROTARY_ENCODER_DT电平变化(此时AB为01)
- forced_out=3000;
- while((!ROTARY_ENCODER_CLK)&&(ROTARY_ENCODER_DT))
- {
- --forced_out;
- rotary_encoder_delay50us();
- if(!forced_out) return 0xFF;//超时则强制退出,返回错误码
- }
-
- //每次电平变化必定旋转了编码器,电平变化后要消抖
- rotary_encoder_delay10ms();
-
- //当ROTARY_ENCODER_CLK为低电平,而且ROTARY_ENCODER_DT也为低电平
- //或ROTARY_ENCODER_CLK为高电平,而且ROTARY_ENCODER_DT也为高电平(AB为11或00)
- //此时 AB从11到01到00 或 AB从00到01到11
- if(((ROTARY_ENCODER_CLK)&&(ROTARY_ENCODER_DT))||((!ROTARY_ENCODER_CLK)&&(!ROTARY_ENCODER_DT)))
- {
- //如果旋转编码器的状态为1则返回1,代表正转一下
- if(rotary_encoder_state) return 1;
- //如果旋转编码器的状态为0则返回0,代表反转一下
- else return 0;
- }
- //若AB不为11或不为00则返回旋转编码器错误码
- else return ROTARY_ENCODER_ERROR;
- }
- //当ROTARY_ENCODER_CLK为高电平,ROTARY_ENCODER_DT为低电平时
- else
- {
- //当ROTARY_ENCODER_CLK为高电平,ROTARY_ENCODER_DT为低电平时
- if((ROTARY_ENCODER_CLK)&&(!ROTARY_ENCODER_DT))
- {
- //用150ms时间来等待ROTARY_ENCODER_CLK电平变化(此时AB为10)
- forced_out=3000;
- while((ROTARY_ENCODER_CLK)&&(!ROTARY_ENCODER_DT))
- {
- --forced_out;
- rotary_encoder_delay50us();
- if(!forced_out) return 0xFF;//超时则强制退出,返回错误码
- }
-
- //每次电平变化必定旋转了编码器,电平变化后要消抖
- rotary_encoder_delay10ms();
-
- //当ROTARY_ENCODER_CLK为低电平,而且ROTARY_ENCODER_DT也为低电平
- //或ROTARY_ENCODER_CLK为高电平,而且ROTARY_ENCODER_DT也为高电平(AB为11或00)
- //此时 AB从11到10到00 或 AB从00到10到11
- if(((ROTARY_ENCODER_CLK)&&(ROTARY_ENCODER_DT))||((!ROTARY_ENCODER_CLK)&&(!ROTARY_ENCODER_DT)))
- {
- //如果旋转编码器的状态为0则返回1,代表正转一下
- if(!rotary_encoder_state) return 1;
- //如果旋转编码器的状态为1则返回0,代表反转一下
- else return 0;
- }
- //若AB不为11或不为00则返回旋转编码器错误码
- else return ROTARY_ENCODER_ERROR;
- }
- }
- }
- //未响应返回旋转编码器错误码
- return 0xFF;
- }
- //旋转编码器中断
- void rotary_encoder_interrupt() interrupt 0
- {
- static u8 dat=0;
- u8 temp=0xFF;//临时变量先赋旋转编码器错误码的值
- if(!ROTARY_ENCODER_SW)//检查按键是否按下
- {
- rotary_encoder_delay10ms();//若按键按下,则消抖
- if(!ROTARY_ENCODER_SW)//再次检查按键是否按下
- {
- while(!ROTARY_ENCODER_SW);//按键按住则程序卡死在这里
- rotary_encoder_delay10ms();//松手消抖
-
- LCD1602_print_char(0,0,'O');
- LCD1602_print_char(0,1,'N');
- LCD1602_print_char(0,2,' ');
-
- while(ROTARY_ENCODER_SW)//现在扫描旋转编码器
- {
- //扫描旋转编码器,返回值为1代表正转,返回值为0代表反转,返回值为0xFF代表未旋转或旋转错误
- temp=scan_rotary_encoder();
-
- if(temp!=0xFF)//去除旋转编码器错误码
- {
- //利用 unsigned char 特性
- //当temp为255时,再加1则溢出,变为0
- //同理,当temp为0时,再减1则变为255
- if(temp==0x01) ++dat;
- if(temp==0x00) --dat;
-
- //LCD1602打印字符(行,列,字符)
- LCD1602_print_char(1,0,'0'+(dat/100%10));
- LCD1602_print_char(1,1,'0'+(dat/10%10));
- LCD1602_print_char(1,2,'0'+(dat/1%10));
- }
- }
- rotary_encoder_delay10ms();//按键按下,则消抖
-
- while(!ROTARY_ENCODER_SW);//按键按住则程序卡死在这里
- rotary_encoder_delay10ms();//松手消抖
-
- LCD1602_print_char(0,0,'O');
- LCD1602_print_char(0,1,'F');
- LCD1602_print_char(0,2,'F');
- }
- }
- }
复制代码
链接:游客,本帖隐藏的内容需要积分高于 1 才可浏览,您当前积分为 0
全部资料51hei下载地址:
旋转编码器测试代码.rar
(1.44 MB, 下载次数: 138)
|