Obwohl wir das Programm zur Verwendung von Interrupts zur Steuerung der Motordrehung abgeschlossen haben, ist dieses Programm tatsächlich nicht von großem praktischen Wert. Wir können es nicht jedes Mal ein- und ausschalten, wenn wir möchten, dass es sich dreht, oder? Außerdem muss es sich nicht nur vorwärts, sondern auch rückwärts drehen können, das heißt, es muss sich nicht nur herumdrehen, sondern auch zurückdrehen können. Okay, erstellen wir ein Beispielprogramm in Kapitel 8 und entwerfen ein Funktionsprogramm wie dieses: Drücken Sie die Zifferntasten 1 bis 9, um den Motor so zu steuern, dass er 1 bis 9 Kreise dreht Ändern Sie die Drehrichtung, drücken Sie die Aufwärtstaste, um 1 bis 9 Mal vorwärts zu drehen, und die Abwärtstaste, um 1 bis 9 Mal in die Rückwärtsrichtung zu drehen. Die linke Taste dreht sich um 90 Grad vorwärts Grad; die Esc-Taste beendet den Übergang. Durch dieses Programm können wir auch besser verstehen, wie man mit Tasten Programme steuert, um komplexe Funktionen auszuführen, und wie man Aufgaben zwischen Steuerungs- und Ausführungsmodulen koordiniert, und in solchen theoretischen Übungen kann auch Ihr Programmierniveau trainiert und verbessert werden.
#includesbit 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(); } }
Dieses Programm ist eine Synthese des Wissens aus Kapitel 8 und diesem Kapitel – Verwendung von Tasten zur Steuerung von Schrittmotorübergängen. Es gibt mehrere erwähnenswerte Punkte im Programm, die wir wie folgt beschreiben:
Angesichts der Tatsache, dass der Motor zwei verschiedene Vorgänge ausführen muss, nämlich Vorwärtsdrehung und Rückwärtsdrehung, verwenden wir nicht zwei Funktionen: Vorwärtsdrehung Startfunktion und Startfunktion für umgekehrte Drehung Um dies zu erreichen, wird beim Definieren der Startfunktion kein Methodenparameter hinzugefügt, der die Richtung angibt. Der einzige Unterschied zwischen unserer Startfunktion „void StartMotor“ (vorzeichenbehafteter langer Winkel) und der Startfunktion für die Vorwärtsdrehung in eine Richtung besteht darin, dass der Typ des Methodenparameters „winkel“ von „vorzeichenlos lang“ in „vorzeichenbehaftet lang“ geändert wird. Wir verwenden die inhärenten positiven und negativen Eigenschaften von vorzeichenbehafteten Zahlen. Um zwischen Vorwärtsdrehung und Rückwärtsdrehung zu unterscheiden, stellt eine negative Zahl den Winkel der Vorwärtsdrehung und eine positive Zahl den Winkel der Rückwärtsdrehung dar. Ist diese Lösung nicht sehr einfach und klar? Und haben Sie ein besseres Verständnis für die unterschiedliche Verwendung von vorzeichenbehafteten und nicht vorzeichenbehafteten Zahlen?
Um den Betrieb der Motordrehung zu beenden, haben wir eine separate StopMotor-Funktion definiert, um sie abzuschließen. Obwohl diese Funktion sehr komplex ist und nur im Esc-Tastenzweig aufgerufen wird, erwähnen wir sie dennoch separat. Kommt als Funktion heraus. Dieser Ansatz basiert auf einem solchen Programmierprinzip: Verwenden Sie separate Funktionen, um bestimmte Operationen der Hardware so weit wie möglich abzuschließen. Wenn eine Hardware mehrere Operationen umfasst, organisieren Sie diese Operationsfunktionen zusammen, um eine einheitliche Schnittstelle zur darunter liegenden Ebene zu bilden. Durch eine solche hierarchische Verarbeitung wird das gesamte Programm klar hierarchisch, was dem Debuggen und der Wartung des Programms sowie der Funktionserweiterung zugute kommt.
Die Interrupt-Funktion muss zwei Aufgaben bewältigen: Schlüsselscannen und Motorantrieb. Um zu verhindern, dass die Interrupt-Funktion zu komplex wird, haben wir zwei Funktionen getrennt: Schlüsselscannen und Motorantrieb (dies steht auch im Einklang mit dem oben Gesagten). 2. Programmierprinzipien) und die Logik der Infix-Funktion wird prägnant und klar. Hier gibt es einen weiteren Widerspruch: Die von uns gewählte Timing-Zeit für das Tastenscannen beträgt 1 ms, während in den Beispielen vor diesem Kapitel die Dauer des Motorrhythmus offensichtlich 2 ms betragen kann. Mit einem Timing von 2 ms kann jedoch der Abstand von 2 ms bestimmt werden. Wir können jedoch nicht den genauen Abstand von 1 ms ermitteln alle 1 ms, und wir entscheiden uns nur dafür, die Aktion auszuführen, wenn der Wert 1 ist. Dies ist der Abstand von 2 ms. Wenn ich 3 ms oder 4 ms möchte, ändern Sie einfach die Bits in den Typ char oder int, erhöhen Sie sie dann und bestimmen Sie, welcher Wert sein soll auf Null zurückgesetzt werden. Das war's. Dadurch soll ein genaues Software-Timing basierend auf dem Hardware-Timer erreicht werden.
Das obige ist der detaillierte Inhalt vonWas ist das Mastering-Verfahren für den Schrittmotor 28BYJ-48?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!