Ⅰ 51单片机连接编码器 关于外部中断的问题
你的编码器接入是否正确
你打开了外部中断1,但没有中断服务程序,程序可能跑飞。
编码器最好还是接入到定时器中断比较好,采用计数模式。
Ⅱ 有关编码器与51单片机连接的问题
E6A2-CW3C旋转编码器输出两路正交(相位相差90°)脉冲信号。分辨率200意味着编码器每旋转一周输出200个周期脉冲。如果把每一路脉冲的上沿和下沿都利用起来,相当于四倍频,分辨率可以达到200×4=800。
编码器输出通常为5v的TTL电平,可以直接连接到单片机。能否利用单片机直接读取编码器并计数,则取决于你的应用中,编码器轴旋转的速度有多大?因为,单片机对两路脉冲的计数只能基于对脉冲的上跳(或者下跳,下同)的处理。而单片机对随机上跳处理的较好的方案是上跳引起一个中断,在中断程序中实施判断后再进行加1或减1的计数。中断处理是需要时间的。当编码器旋转足够快,输出脉冲周期少于中断处理时间时,将导致脉冲丢失,这会引起计数误差。
所以,你要准确估计你的编码器旋转速度,得到最小的脉冲周期;然后估算你的中断处理程序的执行时间(在AT89S52最大系统时钟下)。两者比较后才能确定你的设计是否可行。
Ⅲ E6B2-CWZ6C编码器怎么判断AB相哪个在前,另外计数怎么实现,是用单片机中断计数器吗
中断的话除非你的单片机非常快,或你的编码器很慢,一般不大建议用中断,不过中断是一个不错的办法。
判断哪个在前,一般可以是设定了其中一相作为检测输入,比如A相,当A相为低(0)时,判断B是高还是低。如果高,比如你让数据+1,低就让数据-1.
Ⅳ 我想实现一个单片机读取编码器方向的功能,请问我应该向哪方面学习
部分编码器带有方向判断(就是有2根脉冲信号线A B) 如果正转A就线输出 反之则是B 具体计数要靠MCU来完成 编码器只负责输出脉冲 因为你已经有MCU板了 具体电路也不好说
大致上你可以用一个或逻辑来判断AB有没有输出 接到中断脚 触发中断以后 MCU的IO脚再读取AB 谁先高电平就表示选择方向(具体高低电平要看编码器的输出规范了)
Ⅳ 51单片机ec11编码器中断法
配置一个1ms定时器,并设置为自动清零模式,配置好后记得打开定时器中断。首先要开启定时器TIM3,我们使用这个 HAL_TIM_IC_Start_IT(htim, Channel);启动定时器。
使用定时器回调函数
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
在里面编写上面的程序,因为我们将B相接在PA7引脚,所以我们使用switch case语句进行判断引脚电平,如果单片机检测到A相为高电平就会进入这个中断判断B相电平,低电平为反转,高电平极为正转(程序中的cnt为计数作用)。
Ⅵ 51单片机利用外部中断INT0和INT1实现编码器双向计数功能
分数给的太少了。我只能给你提供一个思路,然后你自已写程序:
int0和int1分别对应单片机两个不同的引脚,你要先在单片机复位时在特殊功能寄存器中来配置这两个引脚的功能,int0和int1的中断都分别有两个功能,一个是计数器工作方式,一个是外部中断工作方式。
你的这个要求是不能用int0和int1两个引脚的计数器功能的,你只能用外部中断功能。
然后定义好int0和int1分别在中断时的跳转地址,在程序进入中断之后,分别在不同的中断程序中对一个寄存器表示的计数器进行加1或者减1操作。
一定记得在处理中断的时候,要把中断使能的寄存器标置位关掉,以避免中断重复执行和错误。
Ⅶ 求单片机C程序,判断旋转编码器正转和反转,以及转数
旋转编码器一般输出3路信号ABZ,AB相位差是90°
将A接到中断。当A下降沿时:B为高就是正转一步,B为低则是反转一步。
转速可以用若干步用的时间进行计算。
Ⅷ 中断P3.3口连了一个编码器,我想用来做脉冲计数,用的51单片机,再用定时器中断定时50ms,请问
定时器1对外部脉冲计数时TMOD高4位设置应该是5
因此TMOD=0x51;
以下我的频率计程序:
#include <reg52.h>//因没用到STC12C5410专有特殊功能寄存器,此处用52或51的头文件均可
#define unit unsigned int
#define uchar unsigned char
//定义以I/O口的功能
sbit beiguang=P3^2;//液晶屏背光
sbit rs=P1^3;//液晶屏写选择,0命令 1数据
sbit rw=P1^4;//液晶屏读写选择
sbit lcden=P1^5;//液晶屏使能
sbit fm=P1^7;//蜂鸣器
#define db P2 //定义P2为数据输出口,写数据时用db代替P2,增加液晶屏程序的通用性
//更改硬件接线时,只更改此处,而不必去更改液晶屏读写子程序
uchar aa,bb,cc;//变量声明
unit dd,ee;
void Delay1ms(unsigned int i) //1ms延时程序
{
unsigned int j;
for(;i>0;i--)
{
for(j=0;j<125;j++)
{;}
}
}
void init()//初始化设置
{
TMOD=0x15;//定时器0作为计数器,定时器1作为定时器用
TH0=0;//计数器清0
TL0=0;
EA=1;//开总中断
ET1=1;//允许定时器1中断
TH1=0x4c;
TL1=0x5c;
TR0=1;//启动计数器
TR1=1;//启动定时器
aa=0;
}
void write_com(uchar com)//向液晶屏写命令
{
db=com;
rs=0;
rw = 0;
lcden=0;
Delay1ms(10*12);
lcden=1;
Delay1ms(10*12);
lcden=0;
}
void write_date(uchar date)//向液晶屏写数据
{
db=date;
rs=1;
rw = 0;
lcden=0;
Delay1ms(10*12);
lcden=1;
Delay1ms(10*12);
lcden=0;
}
void init2()//液晶屏初始化
{
beiguang=0;
rw=0;
write_com(0x38);
Delay1ms(10*12);
write_com(0x0f);
Delay1ms(10*12);
write_com(0x06);
Delay1ms(10*12);
write_com(0x01);
Delay1ms(10*12);
}
void display4(unsigned int number) //单行多位显示程序
{
uchar A1,A2,A3,A4,A5;
init2();//液晶屏初始化
A1=number/10000%10;//分离出万,千,百,十,个,对于int型数据,最大不超过65535
A2=number/1000%10;
A3=number/100%10;
A4=number/10%10;
A5=number%10;
write_com(0x80);//第1个数据的位置设定,第1行第1列
Delay1ms(10);
write_date(0x30+A1);//写数据
Delay1ms(10);
write_date(0x30+A2);
Delay1ms(10);
write_date(0x30+A3);
Delay1ms(10);
write_date(0x30+A4);
Delay1ms(10);
write_date(0x30+A5);
Delay1ms(10);
write_com(0x87);//第6个数据'H'的位置,中间空85和86 二格
write_date('H');
Delay1ms(10);
write_date('z');
Delay1ms(10);
}
void main()//主程序很简单
{
init();//初始化
while(1)//循环程序
{
dd=bb*256+cc;//0.5S的计数值
ee=2*dd;//换算为1秒钟的计数值
if(aa==1)
{
if(TH0>12)//预判断,50ms内TH0>12,1s内计数值将超过可计数的最大值65535
fm=0;//报警
}
display4(ee);//显示
fm=1;//报警停止
}
}
void timer1()interrupt 3//注意:定时器1的中断序号为3
{
aa++;
TH1=0x4c;//11.0592Mhz
TL1=0x5c;
if(aa==10)//中断10次,共0.5S
{
TR0=0;//暂停计数
aa=0;
bb=TH0;//读出计数器数据
cc=TL0;
TL0=0;//计数器清0
TH0=0;
TR0=1;//重新启动
}
}