;**************************************************** ; ; XS1用のイグナイタプログラム。 ; 16F84でコントロール。 ; PBは全て入力に、PAの出力ポート以外も全て入力に設定。 ; PB4=RIN、PB5=LIN、PA2=ROUT、PA3=LOUT ; ;15度進角した場所基準。反対側はそれから180度基準 ;1302rpmからプログラム進角を始める ; ;10MHz駆動 ; ;カム軸で検出して左右の気筒交互に点火するバージョン ; ;低速モードの時だけドエル制御有り 通電時間8.2ms GX250フルトラコイル基準 ;進角は直線で最大進角量を規制 ;低速時にタイミングがばらつくので、T2と旧T2を平均化してみた ; ; ; ;16ビット計算の試験プログラム ;このプログラムを色々弄って煮詰めていく ;**************************************************** LIST P=PIC16F84A INCLUDE "P16F84A.INC" __CONFIG _CP_OFF & _PWRTE_ON & _WDT_OFF & _HS_OSC T1L EQU H'10' ;メインカウンタをデータメモリの10番地におく T1H EQU H'11' ;メインカウンタをデータメモリの10番地におく T2L EQU H'12' ;点火待ち用カウンタをデータメモリの11番地におく T2H EQU H'13' ;点火待ち用カウンタをデータメモリの11番地におく TDL EQU H'14' ;時間稼ぎ用カウンタをデータメモリの12番地におく TDH EQU H'15' ;時間稼ぎ用カウンタをデータメモリの12番地におく TDDL EQU H'16' ;ドエル用カウンタをデータメモリの13番地におく TDDH EQU H'17' ;ドエル用カウンタをデータメモリの13番地におく T5L EQU H'18' ;5度相当カウンタをデータメモリの20番地に置く T5H EQU H'19' ;5度相当カウンタをデータメモリの20番地に置く T11L EQU H'1A' ;11度相当カウンタをデータメモリの21番地に置く T11H EQU H'1B' ;11度相当カウンタをデータメモリの21番地に置く T22L EQU H'1C' ;22度相当カウンタをデータメモリの14番地に置く T22H EQU H'1D' ;22度相当カウンタをデータメモリの14番地に置く T45L EQU H'1E' ;45度相当カウンタをデータメモリの15番地に置く T45H EQU H'1F' ;45度相当カウンタをデータメモリの15番地に置く T90L EQU H'20' ;90度相当カウンタをデータメモリの16番地に置く T90H EQU H'21' ;90度相当カウンタをデータメモリの16番地に置く TNL EQU H'22' ;通常進角カウンタをデータメモリの18番地に置く TNH EQU H'23' ;通常進角カウンタをデータメモリの18番地に置く TMAXL EQU H'24' ;最大進角カウンタをデータメモリの19番地に置く TMAXH EQU H'25' ;最大進角カウンタをデータメモリの19番地に置く T2OLDL EQU H'26' ;旧点火待ち用カウンタをデータメモリの26番地におく T2OLDH EQU H'27' ;旧点火待ち用カウンタをデータメモリの27番地におく BSF STATUS,RP0 ;STATUSレジスタのRP0ビットを1にしてBank1(Page1)に切替える MOVLW B'11110011' ;出力モード用の設定ビット列をセット MOVWF TRISA ;PORTA2とPORT3を出力モード、後は入力に設定 MOVLW B'11111111' ;入力モード用の設定ビット列をセット MOVWF TRISB ;PORTBをすべて入力モードに設定 BCF STATUS,RP0 ;Bank0(Page0)に戻る MOVLW B'00000000' ;PORTAの初期値0をセット MOVWF PORTA ;PORTAに初期値0を出力しておく MOVLW D'150' ; MOVWF T2OLDL ; MOVLW D'22' ; MOVWF T2OLDH ; ;**************************************************************** ;**************************************************************** ;低速では左右の信号のオンを交互にチェックし、どちらかがオンになったら簡易ドエル制御の後に点火する ;このドエル制御は一定の待ち時間を引いているだけなので、規定アイドリングよりも回転が下がると通電時間が ;長くなってしまう ;右気筒用 WAITPBONR ;単純に右信号のオンを待つ部分 BTFSS PORTB,4 ;信号の状態チェック GOTO WAITPBONL ;オフである→WAITPBONLに飛んで左をチェック BTFSS PORTB,4 ;信号の状態チェック GOTO WAITPBONL ;オフである→WAITPBONLに飛んで左をチェック BTFSS PORTB,4 ;信号の状態チェック GOTO WAITPBONR ;オフである→WAITPBONLに飛んで左をチェック ;この段階で3回目のチェックでも右信号がオンであることが確認できている CALL LSCLONR ;右コイルの通電開始 CALL LSFIRER ;右信号のオフを待って右気筒を点火する ;この段階で右信号はオフになっている ;カウントアップ用タイマをゼロセットする MOVLW B'00000000' ;T1カウンタの初期値0をWにセット MOVWF T1L ;WからT1Lに0を保存 MOVWF T1H ;WからT1Hに0を保存 GOTO NORML ;左気筒の通常点火モードへ飛び、左信号のオンを待つ ;**************************************************************** ;左気筒用 WAITPBONL ;単純に左信号のオンを待つ部分 BTFSS PORTB,5 ;信号の状態チェック GOTO WAITPBONR ;オフである→WAITPBONRに飛んで右をチェック BTFSS PORTB,5 ;信号の状態チェック GOTO WAITPBONR ;オフである→WAITPBONRに飛んで右をチェック BTFSS PORTB,5 ;信号の状態チェック GOTO WAITPBONR ;オフである→WAITPBONRに飛んで右をチェック ;この段階で3回目のチェックでも左信号がオンであることが確認できている CALL LSCLONL ;左コイルの通電開始 CALL LSFIREL ;左信号のオフを待って左気筒を点火する ;この段階で左信号はオフになっている ;カウントアップ用タイマをゼロセットする MOVLW B'00000000' ;T1カウンタの初期値0をWにセット MOVWF T1L ;WからT1Lに0を保存 MOVWF T1H ;WからT1Hに0を保存 GOTO NORMR ;右気筒の通常点火モードへ飛び、右信号のオンを待つ ;**************************************************************** ;**************************************************************** ;連続回転時に左信号のオンまでをカウントアップし、タイミングを計算する。 ;左信号のオンからはカウントダウンして、左コイルの通電や点火をコントロールする部分。 NORML INCFSZ T1L,1 ;T1Lを+1する GOTO PCLOSEL ;桁上がりしていれば次を実行して上位を+1する INCF T1H,1 ;桁上がりした時だけT1Hを+1して以下の判断を行う ;上位のみの判断だけど、とりあえずこれで行ってみる。 MOVLW D'20' ;Wに4817相当の数を代入 SUBWF T1H,0 ;W=T1H-20 19→20の瞬間が分岐点 BTFSS STATUS,C ;T1Hの方が小さければC=0(ボロー有り)なので次を実行する GOTO PCLOSEL ;(T1H<20)1330rpm以上である→ノーマルカウントへ GOTO WAITPBONL ;(T1H≧20)1330rpm未満である→もう一度左の単純オンオフへ戻る PCLOSEL ;通常モードで信号オンからディレイ計算まで NOP ;1サイクル4.4us NOP NOP NOP NOP BTFSS PORTB,5 ;左信号がオンになるのを待つ GOTO NORML ;オンで無ければNORMに戻る ぐるぐる回る ;このタイミングで左信号がオンになっている CALL CALC ;ドエル待ちが無く直ぐに通電開始する部分 INSTCLL ;ドエル待ち無しで直ぐにポイントを閉じる部分 BSF PORTA,3 ;信号が0になったらPORTA,3に1を出力して左コイルの通電開始 ;連続回転時に、先読みカウントダウンして点火する部分 LOOP1L ;通常点火の部分 1サイクル4.4us BTFSS PORTB,5 ;信号の状態チェック オンならT2-1のカウントダウンへ GOTO FIREL ;既にオフである→直ぐに左気筒点火へ ;T2から-1していく MOVF T2L,1 ;自分に自分を転送して0かどうかチェック BTFSC STATUS,Z ;下位桁が0かどうかチェック DECF T2H,1 ;下位桁が0なら上位からも1を引いておく DECF T2L,1 ;下位から1を引く ;全部の桁が0であるかチェック MOVF T2L,W IORWF T2H,W BTFSS STATUS,Z ;全部0ならZ=1になる→次を実行しない GOTO LOOP1L FIREL BCF PORTA,3 ;T2は0である→PORTA,3に0を出力して左気筒点火 ;左気筒点火後に左上死点を通過する部分 POPENL ;通常のタイミングで上死点を通過する部分 BTFSC PORTB,5 ;信号がオフになるまで待つ 単なる上死点通過 GOTO POPENL ;ぐるぐる回って待機 MOVLW B'00000000' ;信号がオフになったら、T1を0リセットして MOVWF T1L ;WからT1Lに0を保存 MOVWF T1H ;WからT1Hに0を保存 GOTO NORMR ;右気筒コントロールへ飛ぶ ;**************************************************************** ;連続回転時に右信号のオンまでをカウントアップし、タイミングを計算する。 ;右信号のオンからはカウントダウンして、右コイルの通電や点火をコントロールする部分。 NORMR INCFSZ T1L,1 ;T1Lを+1する GOTO PCLOSER ;桁上がりしていれば次を実行して上位を+1する INCF T1H,1 ;桁上がりした時だけT1Hを+1して以下の判断を行う ;上位のみの判断だけど、とりあえずこれで行ってみる。 MOVLW D'20' ;Wに5120相当の数を代入 SUBWF T1H,0 ;W=T1H-20 19→20の瞬間が分岐点 BTFSS STATUS,C ;T1Hの方が小さければC=0(ボロー有り)なので次を実行する GOTO PCLOSER ;(T1H<20)1330rpm以上である→ノーマルカウントへ GOTO WAITPBONR ;(T1H≧20)1330rpm未満である→もう一度左の単純オンオフへ戻る PCLOSER ;通常モードで信号オンからディレイ計算まで NOP ; 1サイクル4.4us NOP NOP NOP NOP BTFSS PORTB,4 ;右信号がオンになるのを待つ GOTO NORMR ;オンで無ければNORMRに戻る ぐるぐる回る ;このタイミングで右信号がオンになっている CALL CALC ;ドエル待ちが無く直ぐに通電開始する部分 INSTCLR ;ドエル待ち無しで直ぐにポイントを閉じる部分 BSF PORTA,2 ;信号が0になったらPORTA,2に1を出力して右コイルの通電開始 ;連続回転時に、先読みカウントダウンして点火する部分 LOOP1R ;通常点火の部分 1サイクル4.4us BTFSS PORTB,4 ;信号の状態チェック オンならT2-1のカウントダウンへ GOTO FIRER ;既にオフである→直ぐに左気筒点火へ ;T2から-1していく MOVF T2L,1 BTFSC STATUS,Z DECF T2H,1 DECF T2L,1 ;全部の桁が0であるかチェック MOVF T2L,W IORWF T2H,W BTFSS STATUS,Z ;全部0ならZ=1になる→次を実行しない GOTO LOOP1R FIRER BCF PORTA,2 ;0である→PORTA,2に0を出力して左気筒点火 ;右気筒点火後に右上死点を通過する部分 POPENR ;通常のタイミングで右上死点を通過する部分 BTFSC PORTB,4 ;信号がオフになるまで待つ 単なる上死点通過 GOTO POPENR ;ぐるぐる回って待機 MOVLW B'00000000' ;信号がオフになったら、T1を0リセットして MOVWF T1L ;WからT1Lに0を保存 MOVWF T1H ;WからT1Hに0を保存 GOTO NORML ;左気筒コントロールへ飛ぶ ;**************************************************************** ;**************************************************************** ;以下はサブルーチン ;**************************************************************** ;**************************************************************** ;時間稼ぎのサブルーチン、ドエル制御に使う TIMER MOVLW D'62' ;0.1msのタイマ MOVWF TDH LOOP NOP DECFSZ TDH,1 GOTO LOOP RETURN ;**************************************************************** ;低速時にドエルタイムを設定し、カウントダウンしながら右コイルの通電開始までを行う。 LSCLONR MOVLW D'130' ;TDDカウンタの初期値130(212-130=8.2ms)をWにセット MOVWF TDDH ;WからTDDに130を保存 LSDWELR ;TDD待ちの後に通電開始する部分 CALL TIMER ;時間待ちタイマ DECFSZ TDDH,1 ;通電開始までのタイマTDDを-1する GOTO LSDWELR ;0でない→LSDWELに戻る BSF PORTA,2 ;0である→PORTA,2に1を出力して右コイル通電開始 RETURN ;**************************************************************** ;低速時にドエルタイムを設定し、カウントダウンしながら左コイルの通電開始までを行う。 LSCLONL MOVLW D'130' ;TDDカウンタの初期値130(212-130=8.2ms)をWにセット MOVWF TDDH ;WからTDDに130を保存 LSDWELL ;TDD待ちの後に通電開始する部分 CALL TIMER ;時間待ちタイマ DECFSZ TDDH,1 ;通電開始までのタイマTDDを-1する GOTO LSDWELL ;0でない→LSDWELに戻る BSF PORTA,3 ;0である→PORTA,3に1を出力して左コイル通電開始 RETURN ;**************************************************************** ;極低速で右信号がオンからオフになったら直ぐに右気筒に点火する部分 LSFIRER ;単純に信号のオフを待つ部分 BTFSC PORTB,4 ;信号の状態チェック GOTO LSFIRER ;オンである→LSFIRERに戻る NOP ;1回目オフである BTFSC PORTB,4 ;信号の状態チェック GOTO LSFIRER ;オンである→LSFIRERに戻る NOP ;2回目オフである BTFSC PORTB,4 ;信号の状態チェック GOTO LSFIRER ;オンである→LSFIRERに戻る BCF PORTA,2 ;3回目もオフである→PORTA,2に0を出力して右気筒点火 RETURN ;**************************************************************** ;極低速で左信号がオンからオフになったら直ぐに左気筒に点火する部分 LSFIREL ;単純に信号のオフを待つ部分 BTFSC PORTB,5 ;信号の状態チェック GOTO LSFIREL ;オンである→LSFIRELに戻る NOP ;1回目オフである BTFSC PORTB,5 ;信号の状態チェック GOTO LSFIREL ;オンである→LSFIRELに戻る NOP ;2回目オフである BTFSC PORTB,5 ;信号の状態チェック GOTO LSFIREL ;オンである→LSFIRELに戻る BCF PORTA,3 ;3回目もオフである→PORTA,3に0を出力して左気筒点火 RETURN ;**************************************************************** ;以下で進角に必要な諸定数を算出しておく CALC MOVF T1L,0 MOVWF T2L ;今のT1LをT2Lに保存しておく、T2は180度相当の時間 MOVF T1H,0 MOVWF T2H ;今のT1HをT2Hに保存しておく、T2は180度相当の時間 BCF STATUS,C ;キャリービットをクリヤ RRF T1H,1 ;1/2にする、T1は90度相当の時間 RRF T1L,1 ;1/2にする、T1は90度相当の時間 BCF STATUS,C ;キャリービットをクリヤ RRF T1H,1 ;1/2にする、T1は45度相当の時間 RRF T1L,1 ;1/2にする、T1は45度相当の時間 MOVF T1H,0 MOVWF T45H ;今のT1HをT45Hに保存しておく MOVF T1L,0 MOVWF T45L ;今のT1LをT45Lに保存しておく BCF STATUS,C ;キャリービットをクリヤ RRF T1H,1 ;1/2にする、T1は22.5度相当の時間 RRF T1L,1 ;1/2にする、T1は22.5度相当の時間 MOVF T1H,0 MOVWF T22H ;今のT1HをT22Hに保存しておく MOVF T1L,0 MOVWF T22L ;今のT1LをT22Lに保存しておく BCF STATUS,C ;キャリービットをクリヤ RRF T1H,1 ;1/2にする、T1は11.2度相当の時間 RRF T1L,1 ;1/2にする、T1は11.2度相当の時間 MOVF T1H,0 MOVWF T11H ;今のT1HをT11Hに保存しておく MOVF T1L,0 MOVWF T11L ;今のT1LをT11Lに保存しておく BCF STATUS,C ;キャリービットをクリヤ RRF T1H,1 ;1/2にする、T1は5.6度相当の時間 RRF T1L,1 ;1/2にする、T1は5.6度相当の時間 MOVF T1H,0 MOVWF T5H ;今のT1HをT5Hに保存しておく MOVF T1L,0 MOVWF T5L ;今のT1LをT5Lに保存しておく ;変化する部分の進角を計算する UNDER45 MOVLW D'135' ;Wに固定値の135(391-256)を代入 MOVWF TNL ;135をTNLに転送 MOVF T11L,0 ;T11LをWに代入 SUBWF TNL,1 ;TNL=135-T11L MOVLW D'1' ;Wに固定値の1を代入 数字が大きければ進角率が大 MOVWF TNH ;1をTNHに転送 MOVF T11H,0 ;T11HをWに代入 BTFSS STATUS,C ;下位桁で繰り下がりが有るかチェック INCF T11H,0 ;繰り下がりが有れば引く方のT11Hを1増やしておく SUBWF TNH,1 ;TNH=1-T11H ;最大進角を計算する OVER45 MOVFW T22L ;WにT22Lを代入 MOVWF TMAXL ;TMAXL=T22L MOVF T5L,0 ;WにT5Lを代入 ADDWF TMAXL,1 ;TMAXL=TMAXL+T5L MOVFW T22H ;WにT22Hを代入 MOVWF TMAXH ;TMAXH=T22H MOVF T5H,0 ;WにT5Hを代入 BTFSC STATUS,C ;下位桁で桁上がりが無ければ次は飛ばす INCF T5H,0 ;桁上がりが有る→T5Hを1増やしておく ADDWF TMAXH,1 ;TMAXH=TMAXH+T5 ;最大進角かどうかの判断 MOVFW TNH ;WにTNHを代入 SUBWF TMAXH,0 ;W=TMAXH-TNH BTFSS STATUS,C ;TNHの方が大きければC=0なので次を実行する GOTO LIMIT ;最大進角を制限する計算へ飛ぶ ;次は同じかTNHが小さいとき BTFSS STATUS,Z ;TNH=TMAXHならZ=1なので次を実行しないでその先を実行する GOTO NCALC ;はっきりとTNHが小さい→NCALC ;次は上位桁が同じ時に下位桁を比べるところ MOVFW TNL ;WにTNLを代入 SUBWF TMAXL,0 ;W=TMAXL-TNL BTFSS STATUS,C ;TNLの方が大きければC=0なので次を実行する GOTO LIMIT ;最大進角を制限する計算へ飛ぶ NCALC MOVF TNL,0 ; SUBWF T2L,1 ;T2L=T2L-TNL MOVF TNH,0 ; BTFSS STATUS,C ;下位桁で繰り下がりが有るかチェック INCF TNH,0 ;繰り下がりが有れば引く方のTNHを1増やしておく SUBWF T2H,1 ;T2H=T2H-TNH GOTO T2FIX ; LIMIT MOVF TMAXL,0 ; SUBWF T2L,1 ;T2L=T2L-TMAXL MOVF TMAXH,0 ; BTFSS STATUS,C ;下位桁で繰り下がりが有るかチェック INCF TMAXH,0 ;繰り下がりが有れば引く方のTMAXHを1増やしておく SUBWF T2H,1 ;T2H=T2H-TMAXH T2FIX ;T2を1/2にする BCF STATUS,C ;キャリービットをクリヤ RRF T2H,1 ;1/2にする RRF T2L,1 ;1/2にする ;T2OLDを1/2にする BCF STATUS,C ;キャリービットをクリヤ RRF T2OLDH,1 ;1/2にする RRF T2OLDL,1 ;1/2にする ;両者を足して平均化する MOVF T2OLDL,0 ;WにT2OLDLを代入 ADDWF T2L,1 ;T2L=T2L+T2OLDL MOVF T2OLDH,0 ;WにT2OLDHを代入 BTFSC STATUS,C ;下位桁で桁上がりが無ければ次は飛ばす INCF T2OLDH,0 ;桁上がりが有る→T2OLDHを1増やしておく ADDWF T2H,1 ;T2H=T2H+T2OLDH ;現T2を次のために旧データとして残しておく MOVFW T2L ;現データを旧データに保管しておく。 MOVWF T2OLDL ; MOVFW T2H ; MOVWF T2OLDH ; ;以下は計算に必要な時間を一律引く MOVLW D'10' ;計算にかかる時間を一律で引いておく SUBWF T2L,1 ;T2L=T2L-10 BTFSS STATUS,C ;下位桁で繰り下がりが有るかチェック DECF T2H,0 ;繰り下がりが有ればT2Hから1引いておく RETURN ;**************************************************************** END