提起編碼器,可能大家并不陌生,因為這東西真的很常用,現(xiàn)在的主流編碼器一般精度都是比較高的,基本上都是基于光柵的。畢竟用硬件用電刷做到512精度以上是很困難的,而且成本也是很高的,這里我就不多說什么了。
編碼器一般共有三個主通道,每個主通道有分為兩個分支;一個VCC,一個GND,一條屏蔽線。前兩個通道一般是比較精確的脈沖信號,且之間有四分之一左右的相位差用來判斷正反轉(zhuǎn)的,第三通道基本上是旋轉(zhuǎn)一周才會有一個脈沖信號的那種。
提到步進電機,就一定要有一個合適的電機驅(qū)動,個人是比較喜歡用L298n這款芯片的,因為它價格低,操作比較簡單。
對于這個系統(tǒng),我是用128的外部中斷的下降沿觸發(fā)方式來捕捉編碼器的脈沖的,硬件連接方面電機驅(qū)動和主控芯片一定要注意地線的連接。
下面是程序的完整代碼下載地址: http://www.zg4o1577.cn/f/bmma.rar
這里是delay.h ==================================================================== //根據(jù)CPU時鐘頻率選擇 #ifndef F_CPU //#define F_CPU 7372800 //#define F_CPU 8000000 //#define F_CPU 11059200 //#define F_CPU 12000000 #define F_CPU 16000000 #endif //------------------------------------------------------------------------------ //1、2、3、5和10us的精確延時,用于需要精確時間的場合,比如DS18B20 //------------------------------------------------------------------------------ #if F_CPU == 7372800 #define DELAY_1US NOP();NOP();NOP();NOP();NOP();NOP();NOP() #define DELAY_2US DELAY_1US;DELAY_1US #define DELAY_3US DELAY_1US;DELAY_1US;DELAY_1US #define DELAY_5US DELAY_2US;DELAY_3US #define DELAY_10US DELAY_5US;DELAY_5US #elif F_CPU == 8000000 #define DELAY_1US NOP();NOP();NOP();NOP();NOP();NOP();NOP();NOP() #define DELAY_2US DELAY_1US;DELAY_1US #define DELAY_3US DELAY_1US;DELAY_1US;DELAY_1US #define DELAY_5US DELAY_2US;DELAY_3US #define DELAY_10US DELAY_5US;DELAY_5US #elif F_CPU == 11059200 #define DELAY_1US NOP();NOP();NOP();NOP();NOP();NOP();NOP();NOP();NOP();NOP();NOP() #define DELAY_2US DELAY_1US;DELAY_1US #define DELAY_3US DELAY_1US;DELAY_1US;DELAY_1US #define DELAY_5US DELAY_2US;DELAY_3US #define DELAY_10US DELAY_5US;DELAY_5US #elif F_CPU == 12000000 #define DELAY_1US NOP();NOP();NOP();NOP();NOP();NOP();NOP();NOP();NOP();NOP();NOP();NOP() #define DELAY_2US DELAY_1US;DELAY_1US #define DELAY_3US DELAY_1US;DELAY_1US;DELAY_1US #define DELAY_5US DELAY_2US;DELAY_3US #define DELAY_10US DELAY_5US;DELAY_5US #elif F_CPU == 16000000 #define DELAY_1US NOP();NOP();NOP();NOP();NOP();NOP();NOP();NOP();NOP();NOP();NOP();NOP();NOP();NOP();NOP();NOP() #define DELAY_2US DELAY_1US;DELAY_1US #define DELAY_3US DELAY_1US;DELAY_1US;DELAY_1US #define DELAY_5US DELAY_2US;DELAY_3US #define DELAY_10US DELAY_5US;DELAY_5US #endif //------------------------------------------------------------------------------ //函數(shù)聲明 //------------------------------------------------------------------------------ void delay_nus(unsigned int);//<10us時誤差較大,用于無須精確延時的場合 void delay_nms(unsigned int); #endif//__DELAY_H ==================================================================== 這里是delay.c ==================================================================== //|文件名稱|delay.c //|--------|-------------------------------------------------------------------- //|描 述|延時文件 //|--------|-------------------------------------------------------------------- //|說 明|delay_us(unsigned int time)用于不需精確定時的場合,<10us時誤差較大 //| |若要精確定時用delay.h里的宏 //|--------|-------------------------------------------------------------------- //|調(diào)用文件|delay.h //|--------|-------------------------------------------------------------------- //|作 者| //|--------|-------------------------------------------------------------------- //|版 本| //|--------|-------------------------------------------------------------------- //|時 間| //|--------|-------------------------------------------------------------------- //|E-mail | //|--------|-------------------------------------------------------------------- //|開發(fā)環(huán)境|ICCAVR6.31 //============================================================================== #include "delay.h" #if F_CPU == 7372800 void delay_nus(unsigned int time) { unsigned int i; for(i=0;i<time;i++) { NOP(); } } void delay_nms(unsigned int time) { unsigned int i,j; for(i=0;i<time;i++) { for(j=0;j<1045;j++); } } #elif F_CPU == 8000000 void delay_nus(unsigned int time) { unsigned int i; for(i=0;i<time;i++) { NOP();NOP(); } } void delay_nms(unsigned int time) { unsigned int i,j; for(i=0;i<time;i++) { for(j=0;j<1178;j++); } } #elif F_CPU == 11059200 void delay_nus(unsigned int time) { unsigned int i; for(i=0;i<time;i++) { NOP();NOP();NOP();NOP();NOP(); } } void delay_nms(unsigned int time) { unsigned int i,j; for(i=0;i<time;i++) { for(j=0;j<1578;j++); } } #elif F_CPU == 12000000 void delay_nus(unsigned int time) { unsigned int i; for(i=0;i<time;i++) { NOP();NOP();NOP();NOP();NOP(); } } void delay_nms(unsigned int time) { unsigned int i,j; for(i=0;i<time;i++) { for(j=0;j<1713;j++); } } #elif F_CPU == 16000000 void delay_us(unsigned int time) { unsigned int i; for(i=0;i<time;i++) { NOP();NOP();NOP();NOP();NOP();NOP(); NOP();NOP();NOP();NOP(); } } void delay_ms(unsigned int time) { unsigned int i,j; for(i=0;i<time;i++) { for(j=0;j<2288;j++); } } #endif ==================================================================== 這里是dianji.h ==================================================================== #ifndef __DIANJI_H #define __DIANJI_H #define EN_1 PORTC|=(1<<0) #define EN_0 PORTC&=~(1<<0) void one_circle(void); void circle(unsigned int xcircle); #endif ==================================================================== 這里是dianji.c ==================================================================== #include"dianji.h" #include"delay.h" #include<iom128v.h> /*步進電機旋轉(zhuǎn)一周子函數(shù)*/ void one_circle(void) { unsigned int i; for(i=0;i<3200;i++) { EN_1; delay_us(100); EN_0; delay_us(100); } } /*步進電機根據(jù)編碼器計算的數(shù)值旋轉(zhuǎn)任意角度子函數(shù)*/ void circle(unsigned int xcircle) { unsigned int i,j; for(j=0;j<xcircle;j++) { for(i=0;i<3;i++) { EN_1; delay_us(100); EN_0; delay_us(100); } } } ==================================================================== 這里是caiji.h ==================================================================== #ifndef __CAIJI_H #define __CAIJI_H //宏定義595 #define SCK_0 PORTB&=~(1<<PB4) #define SCK_1 PORTB|=(1<<PB4) #define LCK_0 PORTB&=~(1<<PB5) #define LCK_1 PORTB|=(1<<PB5) #define SDI_0 PORTB&=~(1<<PB6) #define SDI_1 PORTB|=(1<<PB6) #define DIR_0 PORTC&=~(1<<1) #define DIR_1 PORTC|=(1<<1) void init_xianshi(void); void send_595(unsigned char dat); void jiaoduzhuanhuan(void); #endif ==================================================================== 這里是caiji.c ==================================================================== #include"caiji.h" #include"dianji.h" #include<iom128v.h> #include<macros.h> #include<math.h> //一些變量的定義 int k=0; unsigned int x=1,d=0,c=0,cir=0; unsigned int a,aa,q,angle=0,p=0; //595(數(shù)碼管)顯示數(shù)組 unsigned char led[]= { 0x3F, // 0 0x06, // 1 0x5B, // 2 0x4F, // 3 0x66, // 4 0x6D, // 5 0x7D, // 6 0x07, // 7 0x7F, // 8 0x6F, // 9 }; //外部中斷0~3向量號碼 #pragma interrupt_handler Zhongduan_0:2 #pragma interrupt_handler Zhongduan_1:3 #pragma interrupt_handler Zhongduan_2:4 //端口輸入輸出初始化 void init_xianshi(void) { DDRA=0XFF; DDRB=0XFF;//595控制口 DDRC=0XFF;//正反轉(zhuǎn)提示LED PORTC=0XFF;//LED初始化(暗) } //595串入一字節(jié)并處發(fā)送一字節(jié)子函數(shù) void send_595(unsigned char dat) { unsigned char i; LCK_0; SDI_1; SCK_0; //上面的三條語句為了初始化端口狀態(tài) for(i=0;i<8;i++) { LCK_0;//時鐘線拉低 if(dat&0x80) SDI_1; else SDI_0; dat=dat<<1; delay_us(100); LCK_1; //時鐘線拉高將數(shù)據(jù)讀入595的移位寄存器 delay_us(100); } SCK_1; //發(fā)送數(shù)據(jù)到并行端口 SCK_0; } void jiaoduzhuanhuan(void) { init_xianshi(); EIMSK=0X0F; EICRA=0XAA; while(1) { if(a!=aa) /*如果有角度變化就執(zhí)行下面的程序*/ { angle++; if(!(PING&0X04)) cir++; while(cir) { if(!k) { delay_ms(800); if(d<=3) one_circle(); d++; } } if(!(PING&0X02)) { while(PING&0X01) { DIR_0; circle(1); p++; while(p==angle); } while(PING&0X01); if(q=-1)//正轉(zhuǎn) DIR_1; circle(1); if(q==1) //反轉(zhuǎn) DIR_1; } aa=a; if(!x) { PORTC=0X00; } } /*下面為數(shù)碼管顯示編碼器當前計數(shù)的數(shù)值*/ PORTA=0X08; send_595(0x00); send_595(led[abs(k)%10]); PORTA=0X01; send_595(0x00); send_595(led[(abs(k)%100)/10]); PORTA=0X02; send_595(0x00); send_595(led[(abs(k)%1000)/100]); PORTA=0X04; send_595(0x00); send_595(led[abs(k)/1000]); SEI(); /*使能中斷*/ } } void Zhongduan_0(void) { CLI(); x=0; ////////////////// if(PIND&0X02) q=-1; if(!(PIND&0X02)) q=1; //////////////// k=k+q; SEI(); } void Zhongduan_1(void) { CLI(); if(PIND&0X01) q=1; k=k+q; if(abs(k)==10000) { k=0; } a=k; //EIMSK=0X0E; SEI(); } void Zhongduan_2(void) { CLI(); k=0; SEI(); } ==================================================================== 這里是main.c ==================================================================== #include<iom128v.h> #include<macros.h> #include"delay.h" #include"caiji.h" #include"dianji.h" void init(void) { DDRC=0X03; PORTC=0X00; } void main(void) { init(); //初始化子函數(shù) jiaoduzhuanhuan(); //主程序的實現(xiàn) } ==================================================================== 程序中涉及到了一些嵌套,如果不明白的話可以給我留言哦!^_^