;*********************************************************** ; 車速パルス分周(専用)プログラム・アセンブラ版 ; ; RB0が入力、RC3が出力 ;*********************************************************** ; JP1とJP2の組み合わせにより分周比を5種類より選択 ; 1/2の分周 (JP1 1-2,JP2 NC) DEVIDE_TYPE=2 PULSE_DEVIDE=1 ; 1/4の分周 (JP1 NC, JP2 2-3) DEVIDE_TYPE=3 PULSE_DEVIDE=2 ; 1/8の分周 (JP1 2-3,JP2 2-3) DEVIDE_TYPE=4 PULSE_DEVIDE=4 ; 1/16の分周 (JP1 1-2,JP2 2-3) DEVIDE_TYPE=5 PULSE_DEVIDE=8 ; 1/20の分周 (JP1 NC, JP2 1-2) DEVIDE_TYPE=6 PULSE_DEVIDE=10 ; その他のジャンパ設定時はデフォルトの1/2分周となる ;16ビットの割り算ルーチンは、 ;ELECTRONICS SHELVES ;http://www4.zero.ad.jp/electronics/index.htmlから入手しました。 ;入手先で著作権の掲示はありませんでした。~ list P=P18F2420 include P18F2420.INC ;コンフィギュレーション・ビットの設定 CONFIG OSC = INTIO67 CONFIG FCMEN = OFF CONFIG IESO = OFF CONFIG PWRT = OFF CONFIG BOREN = OFF CONFIG WDT = OFF CONFIG MCLRE = OFF CONFIG LPT1OSC = OFF CONFIG PBADEN = OFF CONFIG CCP2MX = PORTBE CONFIG STVREN = OFF CONFIG LVP = OFF CONFIG XINST = OFF CONFIG DEBUG = OFF CONFIG CP0 = OFF CONFIG CP1 = OFF CONFIG CPB = OFF CONFIG CPD = OFF CONFIG WRT0 = OFF CONFIG WRT1 = OFF CONFIG WRTB = OFF CONFIG WRTC = OFF CONFIG WRTD = OFF CONFIG EBTR0 = OFF CONFIG EBTR1 = OFF CONFIG EBTRB = OFF ;Internal oscillator block, port function on RA6 and RA7 ;Fail-Safe Clock Monitor disabled ;Oscillator Switchover mode disabled ;PWRT disabled ;Brown-out Reset disabled in hardware and software ;WDT disabled (control is placed on the SWDTEN bit) ;RE3 input pin enabled; MCLR disabled ;Timer1 configured for higher power operation ;PORTB<4:0> pins are configured as digital I/O on Reset ;CCP2 input/output is multiplexed with RB3 ;Stack full/underflow will not cause Reset ;Single-Supply ICSP disabled ;Instruction set extension and Indexed Addressing mode disabled (Legacy mode) ;Background debugger disabled, RB6 and RB7 configured as general purpose I/O pins ; ; ; ; ;Data EEPROM not code-protected ; ; ; ; ;Data EEPROM not write-protected ; ; ; errorlevel -205 ; Suppress message 205 from list file ;*********************************************************** ; 変数定義とレジスタ割付 ;*********************************************************** CBLOCK h'0' ; Bank0 前半 DEVIDE_TYPE PULSE_DEVIDE DEVIDECOUNTER ; 2n回に1度を実現する為のカウンター div1b ;割られる数上位 (終了時には0になって戻る) div1a ;割られる数下位 div2b ;割る数上位 (変化せず戻る) div2a ;割る数下位 div3b ;答え上位    (答えが返る) div3a ;答え下位 div4b ;余り上位    (余りが返る、内部ワークにも使用) div4a ;余り下位 divl1 ;内部ループ用 divl2 ;内部ループ用 diverr ;割る数が0であった場合に1をセットして戻る ENDC #define PULSE_PORT LATC,3 org h'0' goto Start org h'8' bra HighInt ;*********************************************************** ; 高優先度・割り込みサブルーチン ;*********************************************************** HighInt ; 外部割り込みフラグクリア bcf INTCON,INT0IF decfsz DEVIDECOUNTER,F retfie FAST btg PULSE_PORT movff PULSE_DEVIDE,DEVIDECOUNTER retfie FAST Start ;*********************************************************** ; 入出力ピン初期化 ;*********************************************************** movlw b'01110010' movwf OSCCON ; 内部クロックを8MHzで使用 movlw b'11111111' movwf TRISA ; PORTAは全て入力 movlw b'00000001' movwf TRISB ; RB0を入力 movlw b'11110111' movwf TRISC ; RC3を出力 movlw b'11111111' movwf LATA movlw b'11111111' movwf LATB movlw b'11111111' movwf LATC bcf RCON,IPEN ; Disable priority levels on interrupts ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; INT01のInitialize bsf INTCON,INT0IE ; Enable INIT01 External interrupt bsf INTCON2,INTEDG0 ; rising edge(Default) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ADCのInitialize movlw b'00001101' movwf ADCON1 ;AN0,AN1 movlw b'10100101' movwf ADCON2 ;右詰,ACQT:8TAD,ADCS:FOSC/16 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; AD変換によりジャンパ設定値取得 movlw b'00000001' movwf ADCON0 ;AD有効,AN0選択 bsf ADCON0,GO ;A/D変換開始 ADCON0_LOOP btfsc ADCON0,GO ;A/D変換完了? goto ADCON0_LOOP ; Noなら再度 ; 割られる数をセット movff ADRESH,div1b movff ADRESL,div1a ; 割る数(342)をセット movlw b'00000001' movwf div2b movlw b'01010110' movwf div2a call div16 ;割り算実行 movff div3a,DEVIDE_TYPE ;答え下位(だけを使用) movlw b'00000101' movwf ADCON0 ;AD有効,AN1選択 bsf ADCON0,GO ;A/D変換開始 ADCON1_LOOP btfsc ADCON0,GO ;A/D変換完了? goto ADCON1_LOOP ; Noなら再度 ; 割られる数をセット movff ADRESH,div1b movff ADRESL,div1a ; 割る数(342)をセット movlw b'00000001' movwf div2b movlw b'01010110' movwf div2a call div16 ;割り算実行 movf div3a,W ;答え下位(だけを使用) mullw d'3' ;3倍する movf PRODL,W ;3倍した答えをWREGにロード addwf DEVIDE_TYPE,F ;DEVIDE_TYPEに加える ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; DEVIDE_TYPEとPULSE_DEVIDEを変換 ; DEVIDE_TYPEが2の場合、PULSE_DEVIDE=1 movf DEVIDE_TYPE,W xorlw d'2' btfss STATUS,Z bra $+8 movlw d'1' movwf PULSE_DEVIDE bra CONV_END ; DEVIDE_TYPEが3の場合、PULSE_DEVIDE=2 movf DEVIDE_TYPE,W xorlw d'3' btfss STATUS,Z bra $+8 movlw d'2' movwf PULSE_DEVIDE bra CONV_END ; DEVIDE_TYPEが4の場合、PULSE_DEVIDE=4 movf DEVIDE_TYPE,W xorlw d'4' btfss STATUS,Z bra $+8 movlw d'4' movwf PULSE_DEVIDE bra CONV_END ; DEVIDE_TYPEが5の場合、PULSE_DEVIDE=8 movf DEVIDE_TYPE,W xorlw d'5' btfss STATUS,Z bra $+8 movlw d'8' movwf PULSE_DEVIDE bra CONV_END ; DEVIDE_TYPEが6の場合、PULSE_DEVIDE=10 movf DEVIDE_TYPE,W xorlw d'6' btfss STATUS,Z bra $+8 movlw d'10' movwf PULSE_DEVIDE bra CONV_END movlw d'1' ; Default movwf PULSE_DEVIDE CONV_END movff PULSE_DEVIDE,DEVIDECOUNTER ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; bsf INTCON,GIE ; Enables all unmasked interrupts bsf INTCON,PEIE ; Enables all unmasked peripheral interrupts ;*********************************************************** ; メインループ ;*********************************************************** main_loop goto main_loop ;********************************************************************* ;--------------------------------------------------------------------- div16 ;16ビットの割り算ルーチン ; ;http://www4.zero.ad.jp/electronics/pic/pic.htmlより ;-------------------- div16 での使用変数 ;div1b equ xxh ;割られる数上位 (終了時には0になって戻る) ;div1a equ xxh ;割られる数下位 ;div2b equ xxh ;割る数上位 (変化せず戻る) ;div2a equ xxh ;割る数下位 ;div3b equ xxh ;答え上位    (答えが返る) ;div3a equ xxh ;答え下位 ;div4b equ xxh ;余り上位    (余りが返る、内部ワークにも使用) ;div4a equ xxh ;余り下位 ;divl1 equ xxh ;内部ループ用 ;divl2 equ xxh ;内部ループ用 ;diverr equ xxh ;割る数が0であった場合に1をセットして戻る ;使用変数の xxh には適切なアドレスを記入してご使用下さい。 ;-------------------- 使用例 ; movlw 0ffh ;割られる数上位 (ffffh=65535) ; movwf div1b ; movlw 0ffh ;割られる数下位 ; movwf div1a ; movlw 027h ;割る数上位 (2710h=10000) ; movwf div2b ; movlw 010h ;割る数下位 ; movwf div2a ; call div16 ;呼ぶ。答えは div3b,a 、余りは div4b,a に返る ;-------------------- 主ルーチン movlw 10h ;10h=16 movwf divl1 movf div2a,W ;割る数下位をワークにコピー movwf div4a movf div2b,W ;割る数上位をワークにコピー movwf div4b di1601 rlcf div4a,F ;左シフトする rlcf div4b,F btfsc STATUS,C ;キャリフラグを見る bra di1602 ;割る数の上位ビット位置検索 decfsz divl1,F bra di1601 movlw 1 movwf diverr ;割る数が0である。エラーコードをセット return ;戻る di1602 clrf div3a ;答え用変数のクリア clrf div3b clrf div4a ;ワーク用変数のクリア clrf div4b movlw 10h ;10h=16 movwf divl2 movf divl1,W subwf divl2,F ;残り、実ループの回数 di1603 bcf STATUS,C ;キャリフラグを0に rlcf div1a,F rlcf div1b,F rlcf div4a,F rlcf div4b,F decfsz divl1,F ;割られる数を初期位置までシフト bra di1603 di1604 ;現位置での減算が可能かチェック movf div2b,W subwf div4b,W btfss STATUS,W bra di1606 movf div4b,W subwf div2b,W btfss STATUS,C bra di1605 movf div2a,W subwf div4a,W btfss STATUS,C bra di1606 di1605 movf div2a,W subwf div4a,F ;ワークから下位を引く btfss STATUS,W ;キャリフラグが 1(正)なら次をスキップ decf div4b,F ;上位 -1 movf div2b,W subwf div4b,F ;ワークから上位を引く bsf STATUS,C ;キャリフラグを1に bra di1607 di1606 bcf STATUS,C ;キャリフラグを0に di1607 rlcf div3a,F ;キャリフラグの内容を答えにシフト rlcf div3b,F movf divl2,F ;divl2 が 0 か検査 btfsc STATUS,Z bra di1608 ;最下位まで処理したなら終了 decf divl2,F ;ビット位置を1つ下げる(右へ) bcf STATUS,C ;キャリフラグを0に rlcf div1a,F ;ワークへ1ビット左シフト rlcf div1b,F rlcf div4a,F rlcf div4b,F bra di1604 di1608 clrf diverr ;正常終了 return end