Ⅰ 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;//重新啟動
}
}