目次>5章 第2ステップ(色々な実験)> (21)DCモータの制御(ON/OFF,スピード制御)> ソース
DCモータの制御
− ON/OFF,スピード制御 −
更新日2008.9.21
以下のソースを取り込んで、アセンブル→PIC書き込み→実行して下さい。
; ========================== ここから ============================== ; ファイル名 RC_AD_motor.asm ; 作成日 2008.9.3 ; 作成者 mit.ueno ; バージョン 1.0 ; PIC PIC16F84A ; クロック 20MHz ; 概要 ; 簡易A/D変換を行い、PWM制御でDCモータの ; スピード制御 ; A/D変換結果などはLCDに表示する ; 使用ポート ; RB0 RB0/INT(積分結果入力) ; RB4 LCD DB4 ; RB5 LCD DB5 ; RB6 LCD DB6 ; RB7 LCD DB7 ; ; RA0 LCD RS (4:Register Select) ; RA1 LCD E (5:Enable Signal) ; RA3 矩形波出力 → 積分回路 ; RA2 プッシュボタンスイッチ ; RB3 DCモータ(FET制御) ; 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 save_st AD_counter ;AD変換ワーク AD_max ;AD変換最大値 AD_max_diff ;0FFh - AD変換最大値 flag ;bit0:INT割込みフラグ char ;LCD表示データ CNT50uS CNT1mS CNT5mS CNT15mS PWM_cycle PWM_width PWM_width_i WORK_0 ;計算一時ワーク ENDC f_int EQU 0 ;INT割込みフラグ( flag[0] ) 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 MOVF PWM_width_i,W ;PWMパルス幅は BTFSS STATUS,Z ;0? BSF PORTB,3 ;No モーターON MOVWF PWM_width ;PWMパルス幅初期化 GOTO int_exit int_T0_10 DECFSZ PWM_width,F ;PWMパルスON時間経過? GOTO int_exit ; No BCF PORTB,3 ; Yes モーター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 007h ; MOVWF TRISB ;RB3-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初期化 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 ; 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表示 MOVLW d'31' MOVWF PWM_cycle CLRF PWM_width CALL wait1ms CLRF TMR0 BSF INTCON,T0IE ; ============================== メイン ========================= main CALL AD_proc ;簡易A/D変換 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進表示 CALL wait1ms ; CALL wait50us ;コンデンサの放電完了待ち(合計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 ; ----------------------------------------------------- ; バイナリ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 ; ========================== ここまで ==============================