TOP>PICC Lite編(PIC16F887)> ステッピングモータの制御(PIC16F887 PICC-Lite)> ソース
ステッピングモータの制御(ソース)
(PIC16F887 PICC-Lite)
更新日2009.5.6
以下のソースを取り込んで、コンパイル→PIC書き込み→実行して下さい。
// ========================== ここから ============================== // ファイル名 motor_RL.c // 作成日 2009.3.22 // 作成者 mit.ueno // 機種 PIC16F887 // CLOCK 8MHz(INTIO) // 概要 // ステッピングモータの左右動作 //I/Oポート // RA0:LED // RB1:右検出スイッチ // RB2:左検出スイッチ // stepping motor // RC0:ステッピングモータ(X) // RC1:ステッピングモータ(Y) // RC2:ステッピングモータ(^X) // RC3:ステッピングモータ(^Y) // LCD // RD2:LCD_RS // RD3:LCD_E // RD4:LCD_DB4 // RD5:LCD_DB5 // RD6:LCD_DB6 // RD7:LCD_DB7 // // LCD_R/W : GND // LCD_V0 : 5KΩVRでGND // LCD_DB0-3: open // //TMR0 // プリスケーラ 1 // TMR0 256(フリーラン) // 割込み周期 (1/8MHz)*4*1*256=128uS // #include "pic.h" #define LCD_E RD3 #define LCD_RS RD2 __CONFIG(INTIO & WDTDIS & PWRTEN & MCLRDIS & BORDIS & IESODIS & LVPDIS); struct i_x { unsigned char wk[2]; }; static void pic_init(); static void motor_init(); static void RB1_on(); static void RB2_on(); static void motor1_auto(); static void itox_LCD(struct i_x *); static void LCD_send4(unsigned char); static void LCD_cmd(unsigned char); static void LCD_data(unsigned char); static void LCD_init(); static void wait_50us(); static void wait_1ms(); static void wait_ms(unsigned char); unsigned char motor1_period; // パルス周期 unsigned char motor1_period_i; // パルス周期初期値 unsigned char motor1_pattern; // XY^X^Y パルス出力パターン unsigned char motor1_round; // 回転方向 // 回転方向 0:stop , 1:right , 2:stop , 3:left unsigned int motor1_pos; // モータ位置 unsigned int motor1_posmax; // モータ位置右の最大値 unsigned char motor1_add; // モータ位置加算値 bit sw_RB1; bit sw_RB2; bit RB1_chg; bit RB2_chg; unsigned int Cnt_T0_500mS; bit Flg_T0_500mS; const char hex_tbl[] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'}; // =================== 割り込み処理 ==================== static void interrupt intr(void) { if (T0IF) { // TMR0割込み T0IF = 0; // TMR0割り込みクリア Cnt_T0_500mS--; if (Cnt_T0_500mS == 0) { Cnt_T0_500mS = 3906; Flg_T0_500mS = 1; } // ステッピングモータの制御 motor1_period--; if (motor1_period == 0) { motor1_period = motor1_period_i; switch (motor1_round) { case 0: { // 停止 motor1_pattern = 0; break; } case 1: { // 右回転 motor1_pattern <<= 1; if (motor1_pattern == 0x18) { // 2相制御 motor1_pattern = 0x09; } else if (motor1_pattern == 0x12) { motor1_pattern = 0x03; } motor1_pos += motor1_add; break; } case 2: { // 停止 motor1_pattern = 0; break; } case 3: { // 左回転 motor1_pattern >>= 1; if (motor1_pattern == 0x01) { // 2相制御 motor1_pattern = 0x09; } else if (motor1_pattern == 0x04) { motor1_pattern = 0x0C; } motor1_pos -= motor1_add; break; } } PORTC = (PORTC & 0xF0) | motor1_pattern; } } else if (RBIF) { // ピン変化割込み if (!RB1) { // RB1 on RB1_chg = 1; } else if (!RB2) { // RB2 on RB2_chg = 1; } RBIF = 0; // PORTBピン変化割り込みクリア } } // ================ メイン処理 ======================= main() { pic_init(); // PICの初期化 LCD_init(); // LCDの初期化 LCD_cmd(0x80); // 1行1桁 wait_ms(2); LCD_data('0'); // DEBUG motor_init(); // モータ制御情報などの初期化 while(1) { // スイッチON? if (RB1_chg) { // RB1 wait_ms(10); // チャタリングキャンセル待ち RB1_chg = 0; RB1_on(); } if (RB2_chg) { // RB2 wait_ms(10); // チャタリングキャンセル待ち RB2_chg = 0; RB2_on(); } LCD_cmd(0xC3); // 2行4桁 itox_LCD(&motor1_pos); // motor1_posを16進でLCDに表示 // motor1自動モード if (motor1_posmax) { motor1_auto(); } // スイッチ状態リセット if (RB1) { sw_RB1 = 0; } if (RB2) { sw_RB2 = 0; } // LED点滅 if (Flg_T0_500mS) { Flg_T0_500mS = 0; PORTA ^= 0x01; } } } // ===== int型を4桁の16進数でLCDに表示 ========= static void itox_LCD(struct i_x *ix_wk) { unsigned char c1; unsigned char wk1,wk2,wk3; wk2 = ix_wk->wk[1]; wk3 = ix_wk->wk[0]; wk1 = wk2 & 0xF0; wk1 >>=4; c1 = hex_tbl[wk1]; LCD_data(c1); wk1 = wk2 & 0x0F; c1 = hex_tbl[wk1]; LCD_data(c1); wk1 = wk3 & 0xF0; wk1 >>=4; c1 = hex_tbl[wk1]; LCD_data(c1); wk1 = wk3 & 0x0F; c1 = hex_tbl[wk1]; LCD_data(c1); } // =============== RB1スイッチON =================== static void RB1_on() { if (!RB1) { if (!sw_RB1) { // swは今までoff? sw_RB1 = 1; // 右回転 motor1_round = 1; motor1_pattern = 3; motor1_pos = 0; motor1_period_i = 188; motor1_period = 188; LCD_cmd(0x80); // 1行1桁 LCD_data('1'); } } } // =============== RB2スイッチON =================== static void RB2_on() { if (!RB2) { if (!sw_RB2) { // swは今までoff? sw_RB2 = 1; // 左回転 motor1_round = 3; motor1_pattern = 3; motor1_period_i = 47; motor1_period = 47; motor1_posmax = motor1_pos; LCD_cmd(0x80); // 1行1桁 LCD_data('2'); LCD_cmd(0x83); // 1行4桁 itox_LCD(&motor1_pos); // motor1_posを16進でLCDに表示 } } } // =============== motor1自動運転 ==================== static void motor1_auto() { if (motor1_pos == 0) { // 右回転 motor1_round = 1; } else if (motor1_pos == motor1_posmax) { // 左回転 motor1_round = 3; } } // ========== モータ制御などの初期化 ================= static void motor_init() { Cnt_T0_500mS = 3906; Flg_T0_500mS = 0; motor1_pattern = 0x03; // 2相 motor1_round = 0; // 停止 motor1_pattern = 0; motor1_posmax = 0; motor1_add = 1; sw_RB1 = 0; sw_RB2 = 0; } // =============== PICの初期化 ======================= static void pic_init() { OSCCON = 0x71; // INTOSC 8MHz ANSEL = 0x00; // AN未使用 ANSELH = 0x00; // AN未使用 TRISA = 0xFE; // RA0:out TRISC = 0xF0; // RC0-3:out TRISD = 0x03; // RD2-7:out PORTA = 0x00; PORTC = 0x00; OPTION = 0x88; // TMR0プリスケーラ:なし INTCON = 0xA8; // GIE:1 ,T0IE:1 ,RBIE:1 IOCB = 0x06; // RB1,2 ピン変化割込み } // ====================== LCD 送信(4bit) ====================== static void LCD_send4(unsigned char c) { PORTD = (PORTD & 0x0F) | c; LCD_E = 1; NOP(); LCD_E = 0; return; } // ==================== LCDコマンドWRITE ================= static void LCD_cmd(unsigned char cmd) { LCD_RS = 0; PORTD = (PORTD & 0x0F) | (cmd & 0xF0); LCD_E = 1; // 上位4ビット書き込み NOP(); LCD_E = 0; PORTD = (PORTD & 0x0F) | ((cmd <<4) & 0xF0); LCD_E = 1; // 下位4ビット書き込み NOP(); LCD_E = 0; wait_50us(); return; } // ==================== LCDデータWRITE ================= static void LCD_data(unsigned char cmd) { LCD_RS = 1; PORTD = (PORTD & 0x0F) | (cmd & 0xF0); LCD_E = 1; // 上位4ビット書き込み NOP(); LCD_E = 0; PORTD = (PORTD & 0x0F) | ((cmd <<4) & 0xF0); LCD_E = 1; // 下位4ビット書き込み NOP(); LCD_E = 0; wait_50us(); return; } // ==================== LCDの初期化 =========================== static void LCD_init() { wait_ms(15); LCD_E = 0; LCD_RS = 0; LCD_send4(0x30); // DB4-7に'3'を出力(8bitモードに)@ wait_ms(5); LCD_send4(0x30); // DB4-7に'3'を出力(8bitモードに)A wait_ms(1); LCD_send4(0x30); // DB4-7に'3'を出力(8bitモードに)B wait_ms(1); LCD_send4(0x20); // DB4-7に'2'を出力(4bitモードに) wait_ms(1); // ここからは4bitモードで、Busyフラグが使える LCD_cmd(0x28); // DL=0:4bit ,N=1:2lines ,F=0:5*7dot LCD_cmd(0x08); // Display off LCD_cmd(0x0C); // Display on ,cursor on ,no blink LCD_cmd(0x06); // Entry mode (Inc ,No Shift) LCD_cmd(0x01); // Clear Display wait_ms(2); return; } // ==================== 50μSウェイトルーチン ================ static void wait_50us() { unsigned char i; for (i=32 ; i>0 ; i--) {} return; } // ==================== 1mSウェイトルーチン ================ static void wait_1ms() { unsigned char i; for (i=250 ; i>0 ; i--) { NOP(); NOP(); NOP(); NOP(); NOP(); } return; } // ==================== 1mS×ms ウェイトルーチン =========== static void wait_ms(unsigned char ms) { unsigned char c; for (c=ms ; c>0 ; c--) { wait_1ms(); } return; } // ========================== ここまで ==============================