技術(shù)頻道

娓娓工業(yè)
您現(xiàn)在的位置: 中國傳動網(wǎng) > 技術(shù)頻道 > 應(yīng)用方案 > 用單片機(jī)按鍵控制步進(jìn)電機(jī)轉(zhuǎn)動的程序

用單片機(jī)按鍵控制步進(jìn)電機(jī)轉(zhuǎn)動的程序

時間:2018-01-02 10:46:39來源:網(wǎng)絡(luò)轉(zhuǎn)載

導(dǎo)語:?結(jié)合按鍵程序,我們設(shè)計這樣一個功能程序:按數(shù)字鍵1~9,控制電機(jī)轉(zhuǎn)過1~9圈;

結(jié)合按鍵程序,我們設(shè)計這樣一個功能程序:按數(shù)字鍵1~9,控制電機(jī)轉(zhuǎn)過1~9圈;配合上下鍵改變轉(zhuǎn)動方向,按向上鍵后正向轉(zhuǎn)1~9圈,向下鍵則反向轉(zhuǎn)1~9圈;左鍵固定正轉(zhuǎn)90度,右鍵固定反轉(zhuǎn)90;Esc鍵終止轉(zhuǎn)動。通過這個程序,我們也可以進(jìn)一步體會到如何用按鍵來控制程序完成復(fù)雜的功能,以及控制和執(zhí)行模塊之間如何協(xié)調(diào)工作,而你的編程水平也可以在這樣的實踐練習(xí)中得到鍛煉和提升。

#include

sbitKEY_IN_1=P2^4;

sbitKEY_IN_2=P2^5;

sbitKEY_IN_3=P2^6;

sbitKEY_IN_4=P2^7;

sbitKEY_OUT_1=P2^3;

sbitKEY_OUT_2=P2^2;

sbitKEY_OUT_3=P2^1;

sbitKEY_OUT_4=P2^0;

unsignedcharcodeKeyCodeMap[4][4]={//矩陣按鍵編號到標(biāo)準(zhǔn)鍵盤鍵碼的映射表

{0x31,0x32,0x33,0x26},//數(shù)字鍵1、數(shù)字鍵2、數(shù)字鍵3、向上鍵

{0x34,0x35,0x36,0x25},//數(shù)字鍵4、數(shù)字鍵5、數(shù)字鍵6、向左鍵

{0x37,0x38,0x39,0x28},//數(shù)字鍵7、數(shù)字鍵8、數(shù)字鍵9、向下鍵

{0x30,0x1B,0x0D,0x27}//數(shù)字鍵0、ESC鍵、回車鍵、向右鍵

};

unsignedcharKeySta[4][4]={//全部矩陣按鍵的當(dāng)前狀態(tài)

{1,1,1,1},{1,1,1,1},{1,1,1,1},{1,1,1,1}

};

signedlongbeats=0;//電機(jī)轉(zhuǎn)動節(jié)拍總數(shù)

voidKeyDriver();

voidmain(){

EA=1;//使能總中斷

TMOD=0x01;//設(shè)置T0為模式1

TH0=0xFC;//為T0賦初值0xFC67,定時1ms

TL0=0x67;

ET0=1;//使能T0中斷

TR0=1;//啟動T0

while(1){

KeyDriver();//調(diào)用按鍵驅(qū)動函數(shù)

}

}

/*步進(jìn)電機(jī)啟動函數(shù),angle-需轉(zhuǎn)過的角度*/

voidStartMotor(signedlongangle){

//在計算前關(guān)閉中斷,完成后再打開,以避免中斷打斷計算過程而造成錯誤

EA=0;

beats=(angle*4076)/360;//實測為4076拍轉(zhuǎn)動一圈

EA=1;

}

/*步進(jìn)電機(jī)停止函數(shù)*/

voidStopMotor(){

EA=0;

beats=0;

EA=1;

}

/*按鍵動作函數(shù),根據(jù)鍵碼執(zhí)行相應(yīng)的操作,keycode-按鍵鍵碼*/

voidKeyAction(unsignedcharkeycode){

staticbitdirMotor=0;//電機(jī)轉(zhuǎn)動方向

//控制電機(jī)轉(zhuǎn)動1-9圈

if((keycode>=0x30)&&(keycode<=0x39)){

if(dirMotor==0){

StartMotor(360*(keycode-0x30));

}else{

StartMotor(-360*(keycode-0x30));

}

}elseif(keycode==0x26){//向上鍵,控制轉(zhuǎn)動方向為正轉(zhuǎn)

dirMotor=0;

}elseif(keycode==0x28){//向下鍵,控制轉(zhuǎn)動方向為反轉(zhuǎn)

dirMotor=1;

}elseif(keycode==0x25){//向左鍵,固定正轉(zhuǎn)90度

StartMotor(90);

}elseif(keycode==0x27){//向右鍵,固定反轉(zhuǎn)90度

StartMotor(-90);

}elseif(keycode==0x1B){//Esc鍵,停止轉(zhuǎn)動

StopMotor();

}

}

/*按鍵驅(qū)動函數(shù),檢測按鍵動作,調(diào)度相應(yīng)動作函數(shù),需在主循環(huán)中調(diào)用*/

voidKeyDriver(){

unsignedchari,j;

staticunsignedcharbackup[4][4]={//按鍵值備份,保存前一次的值

{1,1,1,1},{1,1,1,1},{1,1,1,1},{1,1,1,1}

};

for(i=0;i<4;i++){//循環(huán)檢測4*4的矩陣按鍵

for(j=0;j<4;j++){

if(backup[i][j]!=KeySta[i][j]){//檢測按鍵動作

if(backup[i][j]!=0){//按鍵按下時執(zhí)行動作

KeyAction(KeyCodeMap[i][j]);//調(diào)用按鍵動作函數(shù)

}

backup[i][j]=KeySta[i][j];//刷新前一次的備份值

}

}

}

}

/*按鍵掃描函數(shù),需在定時中斷中調(diào)用,推薦調(diào)用間隔1ms*/

voidKeyScan(){

unsignedchari;

staticunsignedcharkeyout=0;//矩陣按鍵掃描輸出索引

staticunsignedcharkeybuf[4][4]={//矩陣按鍵掃描緩沖區(qū)

{0xFF,0xFF,0xFF,0xFF},{0xFF,0xFF,0xFF,0xFF},

{0xFF,0xFF,0xFF,0xFF},{0xFF,0xFF,0xFF,0xFF}

};

//將一行的4個按鍵值移入緩沖區(qū)

keybuf[keyout][0]=(keybuf[keyout][0]<<1)|KEY_IN_1;

keybuf[keyout][1]=(keybuf[keyout][1]<<1)|KEY_IN_2;

keybuf[keyout][2]=(keybuf[keyout][2]<<1)|KEY_IN_3;

keybuf[keyout][3]=(keybuf[keyout][3]<<1)|KEY_IN_4;

//消抖后更新按鍵狀態(tài)

for(i=0;i<4;i++){//每行4個按鍵,所以循環(huán)4次

if((keybuf[keyout][i]&0x0F)==0x00){

//連續(xù)4次掃描值為0,即4*4ms內(nèi)都是按下狀態(tài)時,可認(rèn)為按鍵已穩(wěn)定的按下

KeySta[keyout][i]=0;

}elseif((keybuf[keyout][i]&0x0F)==0x0F){

//連續(xù)4次掃描值為1,即4*4ms內(nèi)都是彈起狀態(tài)時,可認(rèn)為按鍵已穩(wěn)定的彈起

KeySta[keyout][i]=1;

}

}

//執(zhí)行下一次的掃描輸出

keyout++;//輸出索引遞增

keyout=keyout&0x03;//索引值加到4即歸零

//根據(jù)索引,釋放當(dāng)前輸出引腳,拉低下次的輸出引腳

switch(keyout){

case0:KEY_OUT_4=1;KEY_OUT_1=0;break;

case1:KEY_OUT_1=1;KEY_OUT_2=0;break;

case2:KEY_OUT_2=1;KEY_OUT_3=0;break;

case3:KEY_OUT_3=1;KEY_OUT_4=0;break;

default:break;

}

}

/*電機(jī)轉(zhuǎn)動控制函數(shù)*/

voidTurnMotor(){

unsignedchartmp;//臨時變量

staticunsignedcharindex=0;//節(jié)拍輸出索引

unsignedcharcodeBeatCode[8]={//步進(jìn)電機(jī)節(jié)拍對應(yīng)的IO控制代碼

0xE,0xC,0xD,0x9,0xB,0x3,0x7,0x6

};

if(beats!=0){//節(jié)拍數(shù)不為0則產(chǎn)生一個驅(qū)動節(jié)拍

if(beats>0){//節(jié)拍數(shù)大于0時正轉(zhuǎn)

index++;//正轉(zhuǎn)時節(jié)拍輸出索引遞增

index=index&0x07;//用&操作實現(xiàn)到8歸零

beats--;//正轉(zhuǎn)時節(jié)拍計數(shù)遞減

}else{//節(jié)拍數(shù)小于0時反轉(zhuǎn)

index--;//反轉(zhuǎn)時節(jié)拍輸出索引遞減

index=index&0x07;//用&操作同樣可以實現(xiàn)到-1時歸7

beats++;//反轉(zhuǎn)時節(jié)拍計數(shù)遞增

}

tmp=P1;//用tmp把P1口當(dāng)前值暫存

tmp=tmp&0xF0;//用&操作清零低4位

tmp=tmp|BeatCode[index];//用|操作把節(jié)拍代碼寫到低4位

P1=tmp;//把低4位的節(jié)拍代碼和高4位的原值送回P1

}else{//節(jié)拍數(shù)為0則關(guān)閉電機(jī)所有的相

P1=P1|0x0F;

}

}

/*T0中斷服務(wù)函數(shù),用于按鍵掃描與電機(jī)轉(zhuǎn)動控制*/

voidInterruptTimer0()interrupt1{

staticbitp=0;

TH0=0xFC;//重新加載初值

TL0=0x67;

KeyScan();//執(zhí)行按鍵掃描

//用一個靜態(tài)bit變量實現(xiàn)二分頻,即2ms定時,用于控制電機(jī)

p=~p;

if(p==1){

TurnMotor();

}

}這個程序是第8章和本章知識的一個綜合——用按鍵控制步進(jìn)電機(jī)轉(zhuǎn)動。程序中有這么幾點值得注意,我們分述如下:

針對電機(jī)要完成正轉(zhuǎn)和反轉(zhuǎn)兩個不同的操作,我們并沒有使用正轉(zhuǎn)啟動函數(shù)和反轉(zhuǎn)啟動函數(shù)這么兩個函數(shù)來完成,也沒有在啟動函數(shù)定義的時候增加一個形式參數(shù)來指明其方向。我們這里的啟動函數(shù)voidStartMotor(signedlongangle)與單向正轉(zhuǎn)時的啟動函數(shù)唯一的區(qū)別就是把形式參數(shù)angle的類型從unsignedlong改為了signedlong,我們用有符號數(shù)固有的正負(fù)特性來區(qū)分正轉(zhuǎn)與反轉(zhuǎn),正數(shù)表示正轉(zhuǎn)angle度,負(fù)數(shù)就表示反轉(zhuǎn)angle度,這樣處理是不是很簡潔又很明了呢?而你對有符號數(shù)和無符號數(shù)的區(qū)別用法是不是也更有體會了?

針對終止電機(jī)轉(zhuǎn)動的操作,我們定義了一個單獨的StopMotor函數(shù)來完成,盡管這個函數(shù)非常簡單,盡管它也只在Esc按鍵分支內(nèi)被調(diào)用了,但我們?nèi)匀话阉鼏为毺岢鰜碜鳛榱艘粋€函數(shù)。而這種做法就是基于這樣一條編程原則:盡可能用單獨的函數(shù)來完成硬件的某種操作,當(dāng)一個硬件包含多個操作時,把這些操作函數(shù)組織在一起,形成一個對上層的統(tǒng)一接口。這樣的層次化處理,會使得整個程序條理清晰,既有利于程序的調(diào)試維護(hù),又有利于功能的擴(kuò)充。

中斷函數(shù)中要處理按鍵掃描和電機(jī)驅(qū)動兩件事情,而為了避免中斷函數(shù)過于復(fù)雜,我們就又分出了按鍵掃描和電機(jī)驅(qū)動兩個函數(shù)(這也同樣符合上述2的編程原則),而中斷函數(shù)的邏輯就變得簡潔而清晰了。這里還有個矛盾,就是按鍵掃描我們選擇的定時時間是1ms,而本章之前的實例中電機(jī)節(jié)拍持續(xù)時間都是2ms;很顯然,用1ms的定時可以定出2ms的間隔,而用2ms的定時卻得不到準(zhǔn)確的1ms間隔;所以我們的做法就是,定時器依然定時1ms,然后用一個bit變量做標(biāo)志,每1ms改變一次它的值,而我們只選擇值為1的時候執(zhí)行一次動作,這樣就是2ms的間隔了;如果我要3ms、4ms??呢,把bit改為char或int型,然后對它們遞增,判斷到哪個值該歸零,就可以了。這就是在硬件定時器的基礎(chǔ)上實現(xiàn)準(zhǔn)確的軟件定時,其實類似的操作我們在講數(shù)碼管的時候也用過了,回想一下吧。

標(biāo)簽:

點贊

分享到:

上一篇:無線傳感器網(wǎng)絡(luò)的結(jié)構(gòu)和技術(shù)...

下一篇:大型風(fēng)力發(fā)電機(jī)組齒輪傳動技...

中國傳動網(wǎng)版權(quán)與免責(zé)聲明:凡本網(wǎng)注明[來源:中國傳動網(wǎng)]的所有文字、圖片、音視和視頻文件,版權(quán)均為中國傳動網(wǎng)(m.u63ivq3.com)獨家所有。如需轉(zhuǎn)載請與0755-82949061聯(lián)系。任何媒體、網(wǎng)站或個人轉(zhuǎn)載使用時須注明來源“中國傳動網(wǎng)”,違反者本網(wǎng)將追究其法律責(zé)任。

本網(wǎng)轉(zhuǎn)載并注明其他來源的稿件,均來自互聯(lián)網(wǎng)或業(yè)內(nèi)投稿人士,版權(quán)屬于原版權(quán)人。轉(zhuǎn)載請保留稿件來源及作者,禁止擅自篡改,違者自負(fù)版權(quán)法律責(zé)任。

網(wǎng)站簡介|會員服務(wù)|聯(lián)系方式|幫助信息|版權(quán)信息|網(wǎng)站地圖|友情鏈接|法律支持|意見反饋|sitemap

傳動網(wǎng)-工業(yè)自動化與智能制造的全媒體“互聯(lián)網(wǎng)+”創(chuàng)新服務(wù)平臺

網(wǎng)站客服服務(wù)咨詢采購咨詢媒體合作

Chuandong.com Copyright ?2005 - 2024 ,All Rights Reserved 深圳市奧美大唐廣告有限公司 版權(quán)所有
粵ICP備 14004826號 | 營業(yè)執(zhí)照證書 | 不良信息舉報中心 | 粵公網(wǎng)安備 44030402000946號