目次>5章 第2ステップ(色々な実験)> (22)DCモータの制御(正転/逆転,スピード制御)> ソース
DCモータの制御
− 正転/逆転,スピード制御 −
更新日2008.11.9
以下のソースを取り込んで、アセンブル→PIC書き込み→実行して下さい。
; ========================== ここから ============================== ; ファイル名 TA_motor2.asm ; 作成日 2008.9.27 ; 作成者 mit.ueno ; バージョン 1.0 ; PIC PIC16F84A ; クロック 20MHz ; 概要 ; TA7291PによるDCモータの正転・逆転制御 ; 簡易A/D変換を行い、PWM制御でDCモータの ; スピード制御 ; A/D変換結果などはLCDに表示する ; 使用ポート ; RB0 RB0/INT(積分結果入力) ; RB2 DCモータ(TA7291P-IN1) ; RB3 DCモータ(TA7291P-IN2) ; RB4 LCD DB4 ; RB5 LCD DB5 ; RB6 LCD DB6 ; RB7 LCD DB7 ; ; RA0 LCD RS (4:Register Select) ; RA1 LCD E (5:Enable Signal) ; RA2 プッシュボタンスイッチ ; RA3 矩形波出力 → 積分回路 ; TMR0(409.6uS) ; プリスケーラ 8 ; TMR0 256(フリーラン) ; 割込み周期 (1/20MHz)*4*8*256=409.6uS ; ; LCDフォーマット ; 0123456789012345 ; A/D=xx PWM=xx + ; Max=xx dif=xx ; LIST P=PIC16F84A INCLUDE P16F84A.INC __CONFIG _HS_OSC & _WDT_OFF & _PWRTE_ON & _CP_OFF CBLOCK 0Ch save_w ;Wreg save area save_st ;STATUS save area AD_counter ;AD変換ワーク AD_max ;AD変換最大値 AD_max_diff ;0FFh - AD変換最大値 flag ;bit0:INT割込みフラグ ;bit1:スイッチON char ;LCD表示データ CNT50uS ;50uS用カウンタ CNT1mS ;1mS用カウンタ CNT5mS ;5mS用カウンタ CNT15mS ;15mS用カウンタ PWM_cycle ;PWMの1サイクルカウンタ PWM_width ;PWMのパルス幅カウンタ PWM_width_i ;PWMのパルス幅 PWM_bit ;PWM制御するビット位置 WORK_0 ;計算一時ワーク pattern ;TA7291Pの制御パターン(順番) ENDC f_int EQU 0 ;INT割込みフラグ( flag[0] ) SW_on EQU 1 ;スイッチ状態フラグ( flag[1] ) RS EQU 00h ;LCD Register Select E EQU 01h ;LCD Enable ORG 0 GOTO init ; =========== 割り込み処理 (RB0/INT,TMR0) ========== ORG 4 ;割込みの入口 MOVWF save_w ;W-regセーブ SWAPF STATUS,W MOVWF save_st ;STATUSレジスタセーブ BTFSC INTCON,INTF ;INT割込み? GOTO int_INT ; Yes ; ==== TMR0割込み ==== int_TMR0 BCF INTCON,T0IF DECFSZ PWM_cycle,F ;PWM 1サイクル終了? GOTO int_T0_10 ; No MOVLW d'31' MOVWF PWM_cycle ;PWMサイクル初期化 MOVF PWM_width_i,W ;PWMパルス幅は BTFSC STATUS,Z ;0? GOTO int_T0_05 ; Yes MOVF PWM_bit,W ;PWM制御ビットでPORTBとORし IORWF PORTB,F ;モーターON int_T0_05 MOVF PWM_width_i,W MOVWF PWM_width ;PWMパルス幅初期化 GOTO int_exit int_T0_10 DECFSZ PWM_width,F ;PWMパルスON時間経過? GOTO int_exit ; No COMF PWM_bit,W ;PWM制御ビットを反転してPORTBとANDし ANDWF PORTB,F ;モーターOFF GOTO int_exit ; ==== INT割込み ==== int_INT BCF INTCON,INTF BSF flag,f_int ;INT割込みフラグON ; ==== exit ==== int_exit SWAPF save_st,W MOVWF STATUS ;STATUSレジスタロード SWAPF save_w,F SWAPF save_w,W ;W-regロード RETFIE ;割込み許可リターン ; ======================= 初期処理 ================== init CLRF flag BSF STATUS,RP0 ;■バンク1に切替え MOVLW 0F4h ; MOVWF TRISA ;RA0,1,3は出力 MOVLW 003h ; MOVWF TRISB ;RB2-7は出力 MOVLW 0C2h ;プリスケーラ:8,プルアップなし,RB0/INT立ち上がり MOVWF OPTION_REG BCF STATUS,RP0 ;■バンク0に切替え BSF INTCON,GIE CLRF PORTA ;PORTAをクリア CLRF PORTB ;PORTBをクリア CALL LCD_init ;LCD初期化 CALL LCD_init_disp ;LCD初期表示 CALL AD_1st ;初回A/D変換(最大値) MOVLW d'31' MOVWF PWM_cycle CLRF PWM_width MOVLW d'6' MOVWF pattern ;制御パターン初期化 CALL wait1ms ; ===================== メイン処理 ================= main CALL AD_proc ;簡易A/D変換&PWMパルス幅設定 CALL AD_LCD ;A/D変換結果&PWMパルス幅をLCD表示 BTFSC PORTA,2 ;スイッチOFF? BCF flag,SW_on ; Yes スイッチ状態OFF BTFSS PORTA,2 ;スイッチON? CALL SW_CHK ; Yes パターン切り替え&設定 CALL wait1ms ;コンデンサの放電完了待ち(最低200uS) GOTO main ; ================= A/D変換処理 ================ AD_proc BCF flag,f_int ;INT割込みフラグOFF BSF INTCON,INTE ;RB0/INT割込み許可 CLRF AD_counter ;AD変換結果クリア BSF PORTA,3 ;AD開始 AD_proc3 INCF AD_counter,F BTFSS flag,f_int ;INT割込み(A/D変換終了)? GOTO AD_proc3 BCF INTCON,INTE ;RB0/INT割込み禁止 BCF PORTA,3 ; A/D変換結果を最大値(0FFh)に換算し、上位5ビットを取り出す MOVF AD_counter,W ADDWF AD_max_diff,W ;最大値換算 MOVWF WORK_0 BCF STATUS,C ;上位5ビットを取り出す RRF WORK_0,F ; BCF STATUS,C ; RRF WORK_0,F ; BCF STATUS,C ; RRF WORK_0,W ; MOVWF PWM_width_i ;PWMのパルス幅にセット RETURN ; =========== A/D変換結果&PWMパルス幅をLCD表示 ===== AD_LCD MOVLW 084h ;LCD表示位置を4桁目に CALL LCD_command MOVF AD_counter,W CALL LCD_hex ;A/D変換結果をLCDに16進表示 MOVLW 08Bh ;LCD表示位置を11桁目に CALL LCD_command MOVF PWM_width_i,W CALL LCD_hex ;PWMパルス幅をLCDに16進表示 RETURN ; ============= スイッチON確認 =================== SW_CHK BTFSC flag,SW_on ;既にON? GOTO SW_CHK90 ; Yes CALL wait15ms ;チャタリングキャンセル待ち BTFSC PORTA,2 ;スイッチON? GOTO SW_CHK90 ; No BSF flag,SW_on ;→スイッチONに変化した DECFSZ pattern,F ;制御パターン1サイクル終了? GOTO SW_CHK10 MOVLW d'6' MOVWF pattern ;制御パターン初期化 SW_CHK10 CALL PTN_set ;patternからRB2/RB3を設定 SW_CHK90 RETURN ;================= パターンセット ================== ; pattern(モータ制御パターン)により ; ・RB2/RB3およびPWM制御ビットを設定 ; ・PWM制御のためのTMR0割込み設定 ; ・状態をLCDに表示 PTN_set MOVLW 08Fh ;LCD表示位置を15桁目に設定 CALL LCD_command ; patternにより処理を選択 MOVF pattern,W ADDWF PCL,F NOP GOTO PTN_01 ;1 逆転 GOTO PTN_11 ;2 ブレーキ GOTO PTN_00 ;3 ストップ GOTO PTN_10 ;4 正転 GOTO PTN_11 ;5 ブレーキ GOTO PTN_00 ;6 ストップ PTN_00 ;ストップ BCF INTCON,T0IE ;TMR0割込み禁止 BCF PORTB,2 BCF PORTB,3 MOVLW 'P' CALL LCD_write GOTO PTN_90 PTN_11 ;ブレーキ BCF INTCON,T0IE ;TMR0割込み禁止 BSF PORTB,2 BSF PORTB,3 MOVLW 'B' CALL LCD_write GOTO PTN_90 PTN_01 ;逆転 BCF PORTB,2 BSF PORTB,3 MOVLW '-' CALL LCD_write MOVLW 08h MOVWF PWM_bit ;PWM制御ビット設定 GOTO PTN_80 PTN_10 ;正転 BSF PORTB,2 BCF PORTB,3 MOVLW '+' CALL LCD_write MOVLW 04h MOVWF PWM_bit ;PWM制御ビット設定 ; GOTO PTN_80 PTN_80 CLRF TMR0 BSF INTCON,T0IE ;TMR0割込み有効 PTN_90 RETURN ;================= 初回A/D変換 ================== AD_1st ; A/D変換の最大値と0FFhとの差を求める CALL AD_proc MOVF AD_counter,W SUBLW 0FFh MOVWF AD_max_diff ;0FFh - AD_max MOVLW 0C4h ;LCD表示位置を2行4桁目に CALL LCD_command MOVF AD_counter,W CALL LCD_hex ;A/D変換最大値をLCDに16進表示 MOVLW 0CBh ;LCD表示位置を2行11桁目に CALL LCD_command MOVF AD_max_diff,W CALL LCD_hex ;A/D変換最大値と0FFhの差をLCD表示 RETURN ;================= LCDの初期表示 ================ LCD_init_disp MOVLW 'A' CALL LCD_write MOVLW '/' CALL LCD_write MOVLW 'D' CALL LCD_write MOVLW '=' CALL LCD_write MOVLW 087h ;LCD表示位置を7桁目に CALL LCD_command MOVLW 'P' CALL LCD_write MOVLW 'W' CALL LCD_write MOVLW 'M' CALL LCD_write MOVLW '=' CALL LCD_write MOVLW 0C0h ;LCD表示位置を2行0桁目に CALL LCD_command MOVLW 'M' CALL LCD_write MOVLW 'a' CALL LCD_write MOVLW 'x' CALL LCD_write MOVLW '=' CALL LCD_write MOVLW 0C7h ;LCD表示位置を2行7桁目に CALL LCD_command MOVLW 'd' CALL LCD_write MOVLW 'i' CALL LCD_write MOVLW 'f' CALL LCD_write MOVLW '=' CALL LCD_write RETURN ; ================================================== ; バイナリ4ビットをLCD表示用16進数に変換 bin2hex ADDWF PCL,F RETLW '0' ;0 RETLW '1' ;1 RETLW '2' ;2 RETLW '3' ;3 RETLW '4' ;4 RETLW '5' ;5 RETLW '6' ;6 RETLW '7' ;7 RETLW '8' ;8 RETLW '9' ;9 RETLW 'A' ;A RETLW 'B' ;b RETLW 'C' ;C RETLW 'D' ;d RETLW 'E' ;E RETLW 'F' ;F ;=============== LCDに16進数で表示 ============ LCD_hex MOVWF WORK_0 SWAPF WORK_0,W ANDLW 00Fh ;上位4ビットを CALL bin2hex ;16進数で CALL LCD_write ;LCDに表示 MOVF WORK_0,W ANDLW 00Fh ;下位4ビットを CALL bin2hex ;16進数で CALL LCD_write ;LCDに表示 RETURN ;============= LCD表示をクリアする ============== LCD_clear MOVLW 01h CALL LCD_command CALL wait5ms ;LCDのBFをチェックしないので1.64mS以上待つ RETURN ;========== LCDのカーソル位置を先頭に戻す ======= LCD_home MOVLW 080h CALL LCD_command RETURN ;========= LCDのカーソル位置を2行目の先頭に ===== LCD_2line MOVLW 0C0h CALL LCD_command RETURN ;========= LCDのディスプレイをONにする ========= LCD_on MOVLW 0Ch CALL LCD_command RETURN ;======= LCDのディスプレイとカーソルをONにする == LCD_on_cur MOVLW 0Eh CALL LCD_command RETURN ;=========== LCDのディスプレイをOFFにする ======= LCD_off MOVLW 08h CALL LCD_command RETURN ;============== LCDにデータを送る ================== LCD_write MOVWF char BSF PORTA,RS ;RS=1(Data) MOVLW 00Fh ;PORTBの上位4ビットを ANDWF PORTB,F ; クリア MOVF char,W ;上位 ANDLW 0F0h ;4ビットを IORWF PORTB,F ;PORTB(4-7)にセット(PORTB(0-3)はそのまま) BSF PORTA,E ;LCDにデータ書き込み NOP BCF PORTA,E MOVLW 00Fh ;PORTBの上位4ビットを ANDWF PORTB,F ; クリア SWAPF char,W ;下位 ANDLW 0F0h ;4ビットを IORWF PORTB,F ;PORTB(4-7)にセット(PORTB(0-3)はそのまま) BSF PORTA,E ;LCDにデータ書き込み NOP BCF PORTA,E CALL wait50us ;LCDのBFをチェックしないので50uS待つ RETURN ;============ LCDにコマンドを送る ================== LCD_command MOVWF char BCF PORTA,RS ;RS=0(Command) MOVLW 00Fh ;PORTBの上位4ビットを ANDWF PORTB,F ; クリア MOVF char,W ;上位 ANDLW 0F0h ;4ビットを IORWF PORTB,F ;PORTB(4-7)にセット(PORTB(0-3)はそのまま) BSF PORTA,E ;LCDにデータ書き込み NOP BCF PORTA,E MOVLW 00Fh ;PORTBの上位4ビットを ANDWF PORTB,F ; クリア SWAPF char,W ;下位 ANDLW 0F0h ;4ビットを IORWF PORTB,F ;PORTB(4-7)にセット(PORTB(0-3)はそのまま) BSF PORTA,E ;LCDにデータ書き込み NOP BCF PORTA,E CALL wait50us ;LCDのBFをチェックしないので50uS待つ RETURN ;================= LCD初期化 ========================== LCD_init CALL wait5ms ;5mS待つ BCF PORTA,RS ;RS=0 BCF PORTA,E ;E=0 MOVLW 030h ;上位4ビットに'3'をセット MOVWF PORTB BSF PORTA,E ;ファンクションセット(1回目) NOP BCF PORTA,E CALL wait5ms ;5mS待つ BSF PORTA,E ;ファンクションセット(2回目) NOP BCF PORTA,E CALL wait5ms ;5mS待つ BSF PORTA,E ;ファンクションセット(3回目) NOP BCF PORTA,E CALL wait5ms ;5mS待つ MOVLW 020h ;4ビットモード MOVWF PORTB ;に BSF PORTA,E ;設定 NOP BCF PORTA,E CALL wait1ms ;1mS待つ MOVLW 028h ;4ビットモード,2行表示,7ドット CALL LCD_command CALL LCD_off ;ディスプレイOFF CALL LCD_clear ;LCDクリア MOVLW 06h ; CALL LCD_command ;カーソルモードセット (Increment) CALL LCD_on ;ディスプレイON,カーソルOFF RETURN ;================= 15mS WAIT ==================== wait15ms MOVLW d'3' MOVWF CNT15mS wait15ms_loop CALL wait5ms DECFSZ CNT15mS,F GOTO wait15ms_loop RETURN ;================= 5mS WAIT ===================== wait5ms MOVLW d'100' MOVWF CNT5mS wait5ms_loop CALL wait50us DECFSZ CNT5mS,F GOTO wait5ms_loop RETURN ;================= 1mS WAIT ===================== wait1ms MOVLW d'20' MOVWF CNT1mS wait1ms_loop CALL wait50us DECFSZ CNT1mS,F GOTO wait1ms_loop RETURN ;================= 50μS WAIT =================== wait50us ; 1サイクル(4クロック):0.2μS ; 50μS=0.2μS×250サイクル MOVLW d'82' ;1 MOVWF CNT50uS ;1 wait50us_loop DECFSZ CNT50uS,F ;1 GOTO wait50us_loop ;2 RETURN ;2+1 END ; ========================== ここまで ==============================