最近用到旋转编码器,在网上找了一大堆资料,发现这篇好文章。收藏到自己的空间待用。
[ME850扩展应用]旋转编码器计数程序(飞梭旋钮功能)-数码管显示
/*******************************************************************
* *
* ME850单片机开发实验仪演示程序 - 旋转编码器计数程序 *
* *
* 3位数码管显示 *
* *
* MCU: AT89S52 晶振:11.0592MHz *
* *
* 版本:V1.1 (2009/04/29) *
* 作者:gguoqing (Email:
gguoqing@willar.com) *
* 网站:
www.sofi-tech.com (硕飞科技) *
*
www.mcusj.com (伟纳单片机世界) *
* 邮箱:
sofitech@tom.com *
* *
*【版权】Copyright(C) 深圳硕飞科技有限公司 All Rights Reserved *
*【声明】此程序仅用于学习与参考,引用请注明版权和作者信息! *
* *
********************************************************************
* *
* 功能简述: (飞梭旋钮功能) *
* 当旋钮顺时针旋转时,计数值增加。达到最大值255后,不再响应。 *
* 当逆钮顺时针旋转时,计数值减小。达到最小值0后,不再响应。 *
* 当按下旋钮时,将计数值清零(归位)。 *
* *
*******************************************************************/
#include <reg52.h>
sbit PINA = P1^0;
sbit PINB = P1^1;
sbit PIND = P1^2;
unsigned char display[3];
unsigned char code LEDData[ ] =
{
0xC0,0xF9,0xA4,0xB0,0x99,0x92,
0x82,0xF8,0x80,0x90,0xff
};
char code reserve[3]_at_ 0x3b; //保留0x3b开始的3个字节
unsigned char counter = 0; //编码器脉冲计数
unsigned char n,shift;
/**********************************************************
ms延时子函数
**********************************************************/
void delayms(unsigned int ms)
{
unsigned char k;
while (ms--)
{
for (k = 0; k < 114; k++)
;
}
}
/**********************************************************
扫描编码器子函数
在编码器引脚A为低电平期间:
编码器引脚B从0到1为正转,编码器引脚B从1到0为反转。
**********************************************************/
void scan_encoder(void)
{
static bit Curr_encoder_b; //定义一个变量来储存当前B信号
static bit Last_encoder_b; //定义一个变量来储存上次B脚信号
static bit updata= 0;
if( PINA && PINB) //编码器无转动退出
{
updata = 0;
return;
}
Last_encoder_b = PINB; //记录B信号
while(!PINA) //等待A由低变高
{
Curr_encoder_b = PINB; //记录等待期间的B信号(指当前B信号)
updata = 1;
}
if(updata)
{
updata = 0 ;
if( (Last_encoder_b == 0)&&(Curr_encoder_b== 1) ) //B从0到1为正转
{
if(counter == 255)
return;
counter++; //正转计数加
}
else if( (Last_encoder_b == 1)&&(Curr_encoder_b == 0) ) //B从1到0为反转
{
if(counter == 0)
return;
counter--; //反转计数减
}
}
}
/**********************************************************
主函数
**********************************************************/
void main(void)
{
P0 = 0xff;
P1 = 0xff;
P2 = 0xff;
T2CON = 0x00; //设置T2CON寄存器
TH2 = 0xfc; //1ms定时
TL2 = 0x66;
ET2 = 1; //启用Timer2中断
EA = 1; //总中断允许
TR2 = 1; //启动定时器2
counter = 0; //计数单元清零
while(1)
{
scan_encoder();
if(! PIND) //当按下旋钮时
{
counter = 0; //计数单元清零(归位)
delayms(10);
}
}
}
/*********************************************************
Timer2中断函数
**********************************************************/
void timer2() interrupt 5
{
TR2 = 0;
TF2 = 0; //手工清中断标志
TH2 = 0xfc; //1ms定时常数
TL2 = 0x66;
if(n >= 3) //3位数码管显示
{
n = 0;
shift = 0xfe; //送位码初值
P2 = 0xff; //关闭显示
}
else
{
display[0] = counter%10; //个位数据
display[1] = (counter%100)/10; //十位数据
display[2] = counter/100; //百位数据
if(display[2] == 0)
{
display[2] = 0x0a; //百位为0,不显示
if(display[1] == 0)
display[1] =0x0a; //十位为0,不显示
}
P0 = LEDData[display[n++]]; //送段码
P2 = shift; //送位码
shift = (shift<<1)|0x01; //调整位码
}
TR2 = 1;
}
/*********************************************************/
;********************************************************************
;* *
;* ME850单片机开发实验仪演示程序 - 旋转编码器计数程序 *
;* *
;* 3位数码管显示 *
;* *
;* MCU: AT89S52 晶振:11.0592MHz *
;* *
;* 版本:V1.1 (2009/04/29) *
;* 作者:gguoqing (Email:
gguoqing@willar.com) *
;* 网站:
www.sofi-tech.com (硕飞科技) *
;*
www.mcusj.com (伟纳单片机世界) *
;* 邮箱:
sofitech@tom.com *
;* *
;*【版权】Copyright(C) 深圳硕飞科技有限公司 All Rights Reserved *
;*【声明】此程序仅用于学习与参考,引用请注明版权和作者信息! *
;* *
;********************************************************************
;* *
;* 功能简述: (飞梭旋钮功能) *
;* 当旋钮顺时针旋转时,计数值增加。达到最大值255后,不再响应。 *
;* 当逆钮顺时针旋转时,计数值减小。达到最小值0后,不再响应。 *
;* 当按下旋钮时,将计数值清零(归位)。 *
;* *
;********************************************************************
--------------------------------------------------------------------------------
以下为回复后可浏览的内容:
$ INCLUDE(TIMER2.INC)
PINA BIT P1.0
PINB BIT P1.1
PIND BIT P1.2
LAST_B BIT 20H.0
CURR_B BIT 20H.1
UPDATA BIT 20H.2
DISPLAY EQU 40H
COUNT EQU 45H
;**********************************************************
ORG 0000H
AJMP MAIN
ORG 002BH
AJMP TIMER2
ORG 0050H
;**********************************************************
; 主程序
;**********************************************************
MAIN:
MOV SP,#60H ;设置堆栈指针
MOV P0,#0FFH ;端口初始化
MOV P2,#0FFH
MOV P1,#0FFH
MOV COUNT,#00H ;清计数单元
MOV R0,#DISPLAY ;获得显示单元首地址
MOV R1,#0FEH ;位码初值
MOV T2CON,#00H ;设置T2CON寄存器
MOV TH2,#0FCH ;1ms定时常数
MOV TL2,#66H
SETB ET2 ;允许Timer2中断
SETB EA ;允许总中断
SETB TR2
LOOP:
ACALL ENCODER_SCAN
JB PIND,LOOP ;判断轴向开关是否按下
MOV COUNT,#00H ;清计数单元(归位)
AJMP LOOP
RET
;**********************************************************
; 编码器扫描子程序
; 在编码器引脚A为低电平期间:
; 编码器引脚B从0变到1为正转,编码器引脚B从1变到0为反转。
;**********************************************************
ENCODER_SCAN:
MOV P1,#0FFH
NOP
NOP
MOV A,P1
ANL A,#03H
CJNE A,#03H,SCAN1
AJMP SCAN_END ;旋钮没有旋转退出
SCAN1:
JB PINB,SCAN1A ;记录B脚电平
CLR LAST_B
AJMP SCAN2
SCAN1A:
SETB LAST_B
SCAN2:
JB PINA,SCAN3
SETB UPDATA ;当旋钮旋转时,A脚有低电平产生
JB PINB,SCAN2A ;在A为低电平期间,循环记录B脚电平
CLR CURR_B
AJMP SCAN2
SCAN2A:
SETB CURR_B
AJMP SCAN2
SCAN3:
JNB UPDATA,SCAN_END ;旋钮没有旋转(没有新数据产生)退出
JNB CURR_B,SCAN5 ;
JB LAST_B,SCAN_END
MOV A,COUNT
CJNE A,#0FFH,SCAN4 ;判断是否达到最大值
AJMP SCAN_END
SCAN4:
INC COUNT ;顺时针旋转,计数值加1
AJMP SCAN_END
SCAN5:
JNB LAST_B,SCAN_END
MOV A,COUNT
CJNE A,#00H,SCAN6 ;判断是否达到最小值
AJMP SCAN_END
SCAN6:
DEC COUNT ;逆时针旋转计数值减1
SCAN_END:
CLR UPDATA ;清更新数据标志
RET
;**********************************************************
; Timer2 中断服务子程序
;**********************************************************
TIMER2:
CLR TR2
PUSH ACC
PUSH B
CLR TF2 ;清中断标志
MOV TH2,#0F8H ;2ms定时常数
MOV TL2,#0CCH
MOV A,R1
JB ACC.3,T2_1 ;判3位数码管是否显示完?
MOV R0,#DISPLAY ;获得显示单元首地址
MOV R1,#0FEH ;位码初值
MOV P2,#0FFH ;关闭显示
AJMP T2_END
T2_1:
MOV A,COUNT ;转换计数值数据
MOV B,#100
DIV AB
MOV DISPLAY+2,A ;百位数据
XCH A,B ;数据交换
MOV B,#10
DIV AB
MOV DISPLAY+1,A ;十位数据
MOV DISPLAY,B ;个位数据
MOV A,DISPLAY+2 ;百位数据
CJNE A,#00H,T2_2
MOV DISPLAY+2,#0AH ;百位数据为0,不显示
MOV A,DISPLAY+1 ;十位数据
CJNE A,#00H,T2_2
MOV DISPLAY+1,#0AH ;十位数据为0,不显示
T2_2:
MOV A,@R0 ;取显示数据
MOV DPTR,#TABLE ;获得表头
MOVC A,@A+DPTR ;查表获得段码显示数据
MOV P0,A ;送段码
MOV P2,R1 ;送位码
MOV A,R1 ;准备下一位显示的位码
RL A
MOV R1,A
INC R0 ;取下一个显示单元地址
T2_END:
POP B
POP ACC
SETB TR2
RETI
;**********************************************************
TABLE:
DB 0C0H,0F9H,0A4H,0B0H,99H,92H,82H,0F8H,80H,90H
DB 0FFH ; '熄灭'
;**********************************************************
END ;结束
;**********************************************************