今天給大家介紹一下28BYJ-48步進電機掌握程序是怎樣的。,文章的內容小編覺得不錯,現在給大家分享一下,覺得有需要的朋友可以了解一下,希望對大家有所幫助,下面跟著小編的思路一起來閱讀吧。
下面我們固然完成了用中綴掌握電機遷移轉變的程序,但實踐上這個程序照樣沒若干適用價值的,我們不克不及每次想讓它遷移轉變的時分都上下電啊,是吧。還有就是它不只能正轉還得能反轉啊,也就是說不只能轉過來,還得能轉回來呀。好吧,我們就來做一個實例程序吧,聯合第 8 章的按鍵程序,我們設計如許一個功用程序:按數字鍵 1~9,掌握電機轉過 1~9 圈;合營上下鍵改動遷移轉變偏向,按向上鍵后正向轉 1~9 圈,向下鍵則反向轉 1~9 圈;左鍵固定正轉 90 度,右鍵固定反轉 90;Esc 鍵終止遷移轉變。經過這個程序,我們也可以進一步領會到若何用按鍵來掌握程序完成復雜的功用,以及掌握和履行模塊之間若何調和任務,而你的編程程度也可以在如許的理論演習中失掉錘煉和晉升。
#include <reg52.h> sbit KEY_IN_1 = P2^4; sbit KEY_IN_2 = P2^5; sbit KEY_IN_3 = P2^6; sbit KEY_IN_4 = P2^7; sbit KEY_OUT_1 = P2^3; sbit KEY_OUT_2 = P2^2; sbit KEY_OUT_3 = P2^1; sbit KEY_OUT_4 = P2^0; unsigned char code KeyCodeMap[4][4] = { //矩陣按鍵編號到規范鍵盤鍵碼的映射表 { 0x31, 0x32, 0x33, 0x26 }, //數字鍵 1、數字鍵 2、數字鍵 3、向上鍵 { 0x34, 0x35, 0x36, 0x25 }, //數字鍵 4、數字鍵 5、數字鍵 6、向左鍵 { 0x37, 0x38, 0x39, 0x28 }, //數字鍵 7、數字鍵 8、數字鍵 9、向下鍵 { 0x30, 0x1B, 0x0D, 0x27 } //數字鍵 0、ESC 鍵、 回車鍵、 向右鍵 }; unsigned char KeySta[4][4] = { //全體矩陣按鍵的以后形態 {1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1} }; signed long beats = 0; //電機遷移轉變節奏總數 void KeyDriver(); void main(){ EA = 1; //使能總中綴 TMOD = 0x01; //設置 T0 為形式 1 TH0 = 0xFC; //為 T0 賦初值 0xFC67,準時 1ms TL0 = 0x67; ET0 = 1; //使能 T0 中綴 TR0 = 1; //啟動 T0 while (1){ KeyDriver(); //挪用按鍵驅動函數 } } /* 步進電機啟動函數,angle-需轉過的角度 */ void StartMotor(signed long angle){ //在盤算前封閉中綴,完成后再翻開,以防止中綴打斷盤算進程而形成毛病 EA = 0; beats = (angle * 4076) / 360; //實測為 4076 拍遷移轉變一圈 EA = 1; } /* 步進電機中止函數 */ void StopMotor(){ EA = 0; beats = 0; EA = 1; } /* 按鍵舉措函數,依據鍵碼履行響應的操作,keycode-按鍵鍵碼 */ void KeyAction(unsigned char keycode){ static bit dirMotor = 0; //電機遷移轉變偏向 //掌握電機遷移轉變 1-9 圈 if ((keycode>=0x30) && (keycode<=0x39)){ if (dirMotor == 0){ StartMotor(360*(keycode-0x30)); }else{ StartMotor(-360*(keycode-0x30)); } }else if (keycode == 0x26){ //向上鍵,掌握遷移轉變偏向為正轉 dirMotor = 0; }else if (keycode == 0x28){ //向下鍵,掌握遷移轉變偏向為反轉 dirMotor = 1; }else if (keycode == 0x25){ //向左鍵,固定正轉 90 度 StartMotor(90); }else if (keycode == 0x27){ //向右鍵,固定反轉 90 度 StartMotor(-90); }else if (keycode == 0x1B){ //Esc 鍵,中止遷移轉變 StopMotor(); } } /* 按鍵驅動函數,檢測按鍵舉措,調劑響應舉措函數,需在主輪回中挪用 */ void KeyDriver(){ unsigned char i, j; static unsigned char backup[4][4] = { //按鍵值備份,保管前一次的值 {1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1} }; for (i=0; i<4; i++){ //輪回檢測 4*4 的矩陣按鍵 for (j=0; j<4; j++){ if (backup[i][j] != KeySta[i][j]){ //檢測按鍵舉措 if (backup[i][j] != 0){ //按鍵按下時履行舉措 KeyAction(KeyCodeMap[i][j]); //挪用按鍵舉措函數 } backup[i][j] = KeySta[i][j]; //刷新前一次的備份值 } } } } /* 按鍵掃描函數,需在準時中綴中挪用,引薦挪用距離 1ms */ void KeyScan(){ unsigned char i; static unsigned char keyout = 0; //矩陣按鍵掃描輸入索引 static unsigned char keybuf[4][4] = { //矩陣按鍵掃描緩沖區 {0xFF, 0xFF, 0xFF, 0xFF}, {0xFF, 0xFF, 0xFF, 0xFF}, {0xFF, 0xFF, 0xFF, 0xFF}, {0xFF, 0xFF, 0xFF, 0xFF} }; //將一行的 4 個按鍵值移入緩沖區 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; //消抖后更新按鍵形態 for (i=0; i<4; i++){ //每行 4 個按鍵,所以輪回 4 次 if ((keybuf[keyout][i] & 0x0F) == 0x00){ //延續 4 次掃描值為 0,即 4*4ms 內多是按下形態時,可以為按鍵已波動的按下 KeySta[keyout][i] = 0; }else if ((keybuf[keyout][i] & 0x0F) == 0x0F){ //延續 4 次掃描值為 1,即 4*4ms 內多是彈起形態時,可以為按鍵已波動的彈起 KeySta[keyout][i] = 1; } } //履行下一次的掃描輸入 keyout++; //輸入索引遞增 keyout = keyout & 0x03; //索引值加到 4 即歸零 //依據索引,釋放以后輸入引腳,拉低下次的輸入引腳 switch (keyout){ case 0: KEY_OUT_4 = 1; KEY_OUT_1 = 0; break; case 1: KEY_OUT_1 = 1; KEY_OUT_2 = 0; break; case 2: KEY_OUT_2 = 1; KEY_OUT_3 = 0; break; case 3: KEY_OUT_3 = 1; KEY_OUT_4 = 0; break; default: break; } } /* 電機遷移轉變掌握函數 */ void TurnMotor(){ unsigned char tmp; //暫時變量 static unsigned char index = 0; //節奏輸入索引 unsigned char code BeatCode[8] = { //步進電機節奏對應的 IO 掌握代碼 0xE, 0xC, 0xD, 0x9, 0xB, 0x3, 0x7, 0x6 }; if (beats != 0){ //節奏數不為 0 則發生一個驅動節奏 if (beats > 0){ //節奏數大于 0 時正轉 index++; //正轉時節奏輸入索引遞增 index = index & 0x07; //用&操作完成到 8 歸零 beats--; //正轉時節奏計數遞加 }else{ //節奏數小于 0 時反轉 index--; //反轉時節奏輸入索引遞加 index = index & 0x07; //用&操作異樣可以完成到-1 時歸 7 beats++; //反轉時節奏計數遞增 } tmp = P1; //用 tmp 把 P1 口以后值暫存 tmp = tmp & 0xF0; //用&操作清零低 4 位 tmp = tmp | BeatCode[index]; //用|操作把節奏代碼寫到低 4 位 P1 = tmp; //把低 4 位的節奏代碼和高 4 位的原值送回 P1 }else{ //節奏數為 0 則封閉電機一切的相 P1 = P1 | 0x0F; } } /* T0 中綴效勞函數,用于按鍵掃描與電機遷移轉變掌握 */ void InterruptTimer0() interrupt 1{ static bit div = 0; TH0 = 0xFC; //從新加載初值 TL0 = 0x67; KeyScan(); //履行按鍵掃描 //用一個靜態 bit 變量完成二分頻,即 2ms 準時,用于掌握電機 div = ~div; if (div == 1){ TurnMotor(); } }這個程序是第 8 章和本章常識的一個綜合——用按鍵掌握步進電機遷移轉變。程序中有這么幾點值得留意,我們分述如下:
針對電機要完成正轉和反轉兩個分歧的操作,我們并沒有運用正轉啟動函數和反轉啟動函數這么兩個函數來完成,也沒有在啟動函數界說的時分添加一個方式參數來指明其偏向。我們這里的啟動函數 void StartMotor(signed long angle)與單向正轉時的啟動函數獨一的差別就是把方式參數 angle 的類型從 unsigned long 改為了 signed long,我們用有符號數固有的正負特征來辨別正轉與反轉,負數表現正轉 angle 度,正數就表現反轉 angle 度,如許處置是不是很簡練又很清楚明了呢?而你對有符號數和無符號數的差別用法是不是也更有領會了?
針對終止電機遷移轉變的操作,我們界說了一個獨自的 StopMotor 函數來完成,雖然這個函數十分復雜,雖然它也只在 Esc 按鍵分支內被挪用了,但我們依然把它獨自提出來作為了一個函數。而這種做法就是基于如許一條編程準繩:盡能夠用獨自的函數來完成硬件的某種操作,當一個硬件包括多個操作時,把這些操作函數組織在一同,構成一個對下層的一致接口。如許的條理化處置,會使得全部程序層次明晰,既有利于程序的調試保護,又有利于功用的擴大。
中綴函數中要處置按鍵掃描和電機驅動兩件工作,而為了防止中綴函數過于復雜,我們就又分出了按鍵掃描和電機驅動兩個函數(這也異樣契合上述 2 的編程準繩),而中綴函數的邏輯就變得簡練而明晰了。這里還有個矛盾,就是按鍵掃描我們選擇的準時工夫是 1ms,而本章之前的實例中電機節奏繼續工夫多是 2ms;很顯然,用 1ms 的準時可以定出 2ms 的距離,而用 2ms 的準時卻得不到精確的 1ms 距離;所以我們的做法就是,準時器仍然準時 1ms,然后用一個 bit 變量做標記,每 1ms 改動一次它的值,而我們只選擇值為 1 的時分履行一次舉措,如許就是 2ms 的距離了;假如我要 3ms、4ms呢,把 bit 改為 char 或 int 型,然后對它們遞增,判別到哪個值該歸零,就可以了。這就是在硬件準時器的根底上完成精確的軟件準時。
以上就是28BYJ-48步進電機掌握程序是怎樣的的全部內容了,更多與28BYJ-48步進電機掌握程序是怎樣的相關的內容可以搜索億速云之前的文章或者瀏覽下面的文章進行學習哈!相信小編會給大家增添更多知識,希望大家能夠支持一下億速云!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。