zui近用到旋转编码器,在网上找了一大堆资料,发现这篇好文章。供大家参考!
[ME850扩展应用]旋转编码器计数程序(飞梭旋钮功能)-数码管显示
/*******************************************************************
* *
* ME850单片机开发实验仪演示程序 - 旋转编码器计数程序 *
* *
* 3位数码管显示 *
* *
* MCU: AT89S52 晶振:11.0592MHz *
* *
* 版本:V1.1 (2009/04/29) *
* 作者:gguoqing (: gguoqing@) *
* : (硕飞科技) *
* (伟纳单片机世界) *
* :sofitech@ *
* *
*【版权】Copyright(C) 深圳硕飞科技有限公司 All Rights Reserved *
*【声明】此程序仅用于学习与参考,引用请注明版权和作者信息! *
* *
********************************************************************
* *
* 功能简述: (飞梭旋钮功能) *
* 当旋钮顺时针旋转时,计数值增加。达到zui大值255后,不再响应。 *
* 当逆钮顺时针旋转时,计数值减小。达到zui小值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;
}