Walaupun kami telah menyelesaikan program menggunakan gangguan untuk mengawal putaran motor, sebenarnya, program ini masih mempunyai sedikit nilai praktikal. Kami tidak boleh menghidupkan dan mematikannya setiap kali kami mahu ia berputar, bukan? . Selain itu, ia mesti boleh bukan sahaja berputar ke hadapan tetapi juga terbalik, iaitu, ia mesti bukan sahaja boleh berputar, tetapi ia juga mesti boleh berputar ke belakang. Okay, mari kita buat contoh program Digabungkan dengan program kunci dalam Bab 8, kami mereka bentuk program berfungsi seperti ini: tekan kekunci angka 1 hingga 9 untuk mengawal motor untuk memutar 1 hingga 9 bulatan tukar arah putaran, tekan butang atas untuk berputar ke hadapan 1 hingga 9 kali, dan butang bawah untuk berputar 1 hingga 9 kali ke arah terbalik; darjah; kekunci Esc akan menamatkan peralihan. Melalui program ini, kami juga boleh memahami lebih lanjut cara menggunakan butang untuk mengawal atur cara untuk melengkapkan fungsi yang kompleks, dan cara menyelaraskan tugas antara modul kawalan dan pelaksanaan, dan tahap pengaturcaraan anda juga boleh dilaksanakan dan dipertingkatkan dalam latihan teori tersebut.
#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(); } }
Program ini adalah gabungan Bab 8 dan pengetahuan dalam bab ini - menggunakan butang untuk mengawal putaran motor stepper. Terdapat beberapa perkara yang perlu diberi perhatian dalam program kami menerangkannya seperti berikut:
Untuk membolehkan motor menyelesaikan dua operasi putaran hadapan dan putaran belakang yang berbeza, kami tidak menggunakan fungsi mula ke hadapan dan Fungsi permulaan terbalik dilaksanakan oleh kedua-dua fungsi ini, dan parameter kaedah tidak ditambah semasa mentakrifkan fungsi permulaan untuk menunjukkan arahnya. Satu-satunya perbezaan antara fungsi permulaan kami batal StartMotor (sudut panjang yang ditandatangani) dan fungsi mula untuk putaran ke hadapan sehala ialah jenis sudut parameter kaedah ditukar daripada panjang tidak bertanda kepada panjang bertanda Kami menggunakan ciri positif dan negatif yang wujud daripada nombor bertanda untuk membezakan antara putaran ke hadapan dan pembalikan, nombor negatif mewakili sudut putaran ke hadapan, dan nombor positif mewakili sudut putaran terbalik Bukankah penyelesaian ini sangat mudah dan jelas? Dan adakah anda mempunyai pemahaman yang lebih baik tentang penggunaan berbeza nombor bertanda dan nombor tidak bertanda?
Untuk menamatkan operasi putaran motor, kami telah menentukan fungsi StopMotor yang berasingan untuk diselesaikan, walaupun fungsi ini sangat kompleks, walaupun ia hanya dipanggil dalam cawangan kunci Esc , tetapi kami masih meletakkannya sebagai satu fungsi. Pendekatan ini adalah berdasarkan prinsip pengaturcaraan ini: cuba gunakan fungsi berasingan untuk menyelesaikan operasi perkakasan tertentu Apabila sekeping perkakasan merangkumi berbilang operasi, atur fungsi operasi ini bersama-sama untuk membentuk antara muka bersatu pada lapisan asas. Pemprosesan hierarki sedemikian akan menjadikan keseluruhan program berhierarki dengan jelas, yang kondusif untuk penyahpepijatan dan penyelenggaraan program dan pengembangan fungsi.
Fungsi infiks mengendalikan dua tugas: pengimbasan kunci dan pemanduan motor Untuk mengelakkan fungsi infiks daripada menjadi terlalu kompleks, kami telah memisahkan dua fungsi: pengimbasan kunci dan pemanduan motor. Ini juga selaras dengan prinsip pengaturcaraan 2 di atas), dan logik fungsi gangguan menjadi mudah dan jelas. Terdapat satu lagi percanggahan di sini, iaitu, masa masa yang kita pilih untuk pengimbasan butang ialah 1ms, manakala dalam contoh sebelum bab ini, tempoh irama motor mungkin 2ms jelas, menggunakan pemasaan 1ms boleh menentukan jarak 2ms, tetapi menggunakan pemasaan 2ms boleh menentukan jarak 2ms Tetapi kita tidak boleh mendapatkan jarak 1ms yang tepat jadi apa yang kita lakukan ialah, pemasa masih 1ms pada masa, dan kemudian menandakannya dengan sedikit pembolehubah, menukar nilainya; setiap 1ms, dan kami hanya memilih untuk melaksanakan tindakan apabila nilainya ialah 1, Ini ialah jarak 2ms jika saya mahu 3ms atau 4ms, tukar bit kepada jenis char atau int, kemudian naikkannya, dan tentukan nilai yang sepatutnya; set semula kepada sifar. Ini adalah untuk mencapai pemasaan perisian yang tepat berdasarkan pemasa perkakasan.
Atas ialah kandungan terperinci Apakah prosedur penguasaan untuk motor stepper 28BYJ-48?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!