#include <reg52.h> /********IO引腳定義***********************************************************/ sbit SW1=P1^0; //四個獨立按鍵定義 sbit SW2=P1^1; sbit SW3=P1^2; sbit SW4=P1^3; sbit SMG1 = P1^4; //數碼管第一位定義 sbit SMG2 = P1^5; //數碼管第二位定義 sbit SMG3 = P1^6; //數碼管第三位定義 sbit SMG4 = P1^7; //數碼管第四位定義 int table[]={0x3f,0x06,0x5b,0x4f, 0x66,0x6d,0x7d,0x07, 0x7f,0x6f,0x40}; //共陰極數碼管段值 unsigned char flag; //right(lhj[i+1],lhj[i+2]); //正轉,兩個參數代表步進量和轉速 /********數據定義***********************************************************/ // 512個脈沖 90度 unsigned char dataout[8]={0xf1,0xf2,0xf4,0xf8}; //這里我們定義4組數,分別對應四拍:A-B-C-D 從板上設計來分配,選擇P2口的低四位輸出 //P2。0為A相,P2。1為B相,P2。2為C相,P2。3為D相,將高四位都置1,也就是F。 //我們用索引的方式輸出,比如正轉,元素由0到3這樣的循環,反轉則由3到0的循環 //程序中我們保存索引號,比如上次轉在第2元素停下,則下次的正轉由3開始向后計數,反轉則由1開始向前計數 //這樣,電機的轉角度就會很精確 unsigned char datac=0; //存放索引號(元素號) unsigned int gStep = 0; unsigned long gMainchong = 0; unsigned int gJd = 0; unsigned int gKey_flag = 0; unsigned int b1,b2,b3; //臨時變量 void delayms(xms); void Timer0_Init(); void Display(); void rightAll(); void leftAll(); void stepAll(); void Ang(); void KeyScan(); /********函數聲明*************************************************************/ void right(unsigned int Speed,unsigned int road); //正轉 void left(unsigned int Speed,unsigned int road); //反轉 void mDelay(unsigned int DelayTime); //延時函數 /***********主函數開始********************************************************/ void main() { unsigned char i=0; P2&=0XF0; //因ULN2003A直接驅動,為高電平輸出,初始時為低電平,這里一定不能少了 mDelay(100); Timer0_Init(); while(1) { KeyScan(); Ang(); } } /****************************************************************************** * 名稱: Timer0_Init() * 功能: 定時器0初始化 * 輸入: 無 * 輸出: 無 * 說明: ******************************************************************************/ void Timer0_Init() { TMOD=0x01; //定時器方式一 TH0=(65536-500)/256; //定義高字節 TL0=(65536-500)%256; //定義低字節 ET0=1; //計數器中斷 EA=1; //開總中斷 // TR0 = 1; } /****************************************************************************** /****************************************************************************** * 名稱: Set_Display() * 功能: 數碼管顯示函數 * 輸入: 無 * 輸出: 無 * 說明: ******************************************************************************/ void Display() { //以下把num值區分開 以便數碼管顯示 b1=gJd%1000/100; //百位 b2=gJd%1000%100/10; //十位 b3=gJd%1000%100%10; //個位 P0=0x40; SMG1=0; //顯示"-" delayms(3); SMG1=1; P0=table[b1]; SMG2=0; //顯示百位 delayms(3); SMG2=1; P0=table[b2]; SMG3=0; //顯示十位 delayms(3); SMG3=1; P0=table[b3]; SMG4=0; delayms(3); //顯示個位 SMG4=1; } /***********左轉,兩個參數代表步進量和轉速*************************************/ void right(unsigned int Speed,unsigned int road) { //步進節拍:A-B-C-D do{ if(datac==3) //索引號超出3回到0 datac=0; else datac++; P2=dataout[datac]; //這里就在P2口輸出我們定義好的相序步進,P2。0為A相,P2。1為B相,P2。2為C相,P2。3為D相 //這里我們不考慮P2的高四位,直接賦值 mDelay(road); //這里的延時就可控制轉速 Speed--; } while(Speed); P2&=0XF0; //將四個腳復位0 } /***********右轉,兩個參數代表步進量和轉速*************************************/ void rightAll() { if(gStep == 3) gStep = 0; else gStep++; P2=dataout[gStep]; if(gMainchong == 2048) gMainchong = 0; else gMainchong++; } /***********整體左轉*************************************/ void leftAll() { if(gStep == 0) gStep = 3; else gStep--; P2=dataout[gStep]; if(gMainchong == 0) // gMainchong = 4096; gMainchong = 2048; else gMainchong--; } /***********固定動作*************************************/ void stepAll() { right(512, 50); left(1024, 50); right(215, 50); } /***********計算并顯示角度*************************************/ void Ang() // 計算角度 { unsigned int i; // gJd = gMainchong*5.625/32.0; gJd = gMainchong*11.25/64.0; b1=gJd%1000/100; //將得到的數據拆分,以便數碼管顯示 百位 b2=gJd%1000%100/10; //十位4 b3=gJd%1000%100%10; //個位 for(i=0;i<20;i++) Display(); //顯示20遍,防止顯示數據抖動,變化太快 } /***********反轉,兩個參數代表步進量和轉速*************************************/ void left(unsigned int Speed,unsigned int road) { //步進節拍A-D-C-B do{ if(datac==0) //索引號超出0回到3 datac=3; else datac--; P2=dataout[datac]; //這里就在P2口輸出我們定義好的相序步進,P2。0為A相,P2。1為B相,P2。2為C相,P2。3為D相 //這里我們不考虛P2的低四位,直接賦值 mDelay(road); //這里的延時就可控制轉速 Speed--; } while(Speed); P2&=0XF0; //將四個腳復位0 } /***********延時函數*******************************************************/ void mDelay(unsigned int DelayTime) // 10ms { unsigned char j=0; while(DelayTime--) { for(j=0;j<10;j++){} } } // 延時函數 void delayms(xms) { unsigned int x,y; for(x=xms;x>0;x--) for(y=110;y>0;y--) ; } /***********按鍵掃描函數*************************************/ void KeyScan() { if(SW1 == 0) { delayms(10); if(SW1 == 0) // 正傳 { TR0 = 0; gKey_flag = 1; // Timer0_Init(); TR0 = 1; } } if(SW2 == 0) { delayms(10); if(SW2 == 0) // 反傳 { TR0 = 0; gKey_flag = 2; Timer0_Init(); TR0 = 1; } } if(SW3 == 0) { delayms(10); if(SW3 == 0) // 自定義動作 { TR0 = 0; gKey_flag = 3; Timer0_Init(); TR0 = 1; } } if(SW4 == 0) { delayms(10); if(SW4 == 0) // 停止 { TR0 = 0; gKey_flag = 0; Timer0_Init(); TR0 = 1; } } } /****************************************************************************** * 名稱: T0_int() interrupt 1 * 功能: 定時器0 中斷函數 * 輸入: 無 * 輸出: 無 * 說明: ******************************************************************************/ void T0_int() interrupt 1 { // flag=1; //標志位之一 TR0 = 0; switch(gKey_flag) { case 0x00: P2&=0XF0; break; case 0x01: rightAll(); TH0=(65536-10000)/256; //定義高字節 TL0=(65536-10000)%256; //定義低字節 TR0 = 1; break; case 0x02: leftAll(); TH0=(65536-10000)/256; //定義高字節 TL0=(65536-10000)%256; //定義低字節 TR0 = 1; break; case 0x03: stepAll(); break; default: break; } }
|