; 内部クロック 8MHz ; MCLR必要 LIST P=PIC16F88 INCLUDE "P16F88.INC" __CONFIG _CONFIG1,_CP_OFF & _WDT_OFF & _PWRTE_ON & _INTRC_IO & _BODEN_ON & _LVP_OFF & _CPD_OFF & _DEBUG_OFF radix dec ; NOLIST ERRORLEVEL 2 ; ;***** CONST ***** ; W100US EQU 65 ; 165 :CPUCLK = 20MHz ; 81 :CPUCLK = 10MHz ; 65 :CPUCLK = 8MHz ; 31 :CPUCLK = 4MHz LCDPORT EQU PORTB ; Select LCD Port LCD_RS EQU 3 ; Select Port Bit for LCD RS LCD_E EQU 0 ; Select Port Bit for LCD_E ; ; ;***** User RAM Area ***** ; CBLOCK 0x20 lcdTim0 lcdTim1 lcdTmp0 lcdTmp1 CNT1 CNT2 CNT3 CNT4 CNT5 RA6SW RA6SWT swn1 swnow ; EQU 0x28 swnow2 ; EQU 0x29 RA1valH ; EQU 0x34 ; A/D変換の一時退避 上位16bit RA1valL ; EQU 0x35 ; 下位 16bit RA0valH RA0valL RA2valH RA2valL RA4valH RA4valL RA0addH ; 16回平均化 一時保管用 RA0addL ; RA1addH ; RA1addL ; RA2addH ; RA2addL ; RA4addH ; RA4addL ; RA0inpH ; サンプリング終了して RA0inpL ; LCD表示するための保存用 RA1inpH RA1inpL RA2inpH RA2inpL RA3inpH RA3inpL RA4inpH RA4inpL RA0count ; 平均化用カウンター RA1count ; RA2count ; RA4count ; inpH ; 10bitの上位 inpL ; 10bitの下位 tmpH tmpL tmp2count ; テンポラリー BatRelay AccRelay EngStartT EngStartCT EngStCountH EngStCountL EngStTimer2 EngStTimer1 AccLowHi AccTimer1 AccTimer2 BatTimer1 BatTimer2 RA6Timer1 RA6Timer2 octtmp ; 共通一時使用変数 octtmp2 ; 共通一時使用変数 s83 s84 s85 s86 s8B s8C s8D s8E sC3 sC4 sC5 sC6 sC9 sCC a89 a8A a8B a8C a8D aC7 aC8 aCA aCC srlc1 ; カウンタ(サブルーチンで使用) srwk1 ; 一時余り格納場所(サブルーチンで使用) out5 ;10進格納場所(5バイト) out4 out3 out2 out1 ;〜下位 dec_top: ;間接アクセス用ラベル endc ;********************************************************************** ; ; ここからプログラム開始 ; ;********************************************************************** ; EEPROM初期データー ORG 0x2100 DE 0x00,0x00,0x00,0x00,0x00 ORG 0x000 ; processor reset vector ; 初期設定 call initA call initB call initC call initD call initEEPROMRead call initLCDA call LCDN1CLR call SW_INPUT call RA2_KIJYUN call RA4_SUB ; メインのプログラム loop_top call RA1_ACC call ACC_HIKAKU ; call RA6_SW_ONOFF ; どっちか好きなほうを使う call RA6_SW_XOR ; call RA1_ACC call ACC_HIKAKU call RA2_KIJYUN call RA1_ACC call ACC_HIKAKU call RA4_SUB call RA1_ACC call ACC_HIKAKU call EEPROMRead call RA1_ACC call ACC_HIKAKU call ENGSTART call RA1_ACC call ACC_HIKAKU call SA_LCD call RA1_ACC call ACC_HIKAKU call RA0_BATT ; call BAT_HIKAKU call RA1_ACC call ACC_HIKAKU call ENGSTART_LCD call RA1_ACC call ACC_HIKAKU call RA1_LCD call LoopCount goto loop_top ;************************************************************************ ; ; ここから下はサブルーチン ; ;************************************************************************ ;************************************************************** ; ; STBY BATT RELAY / ACC RELAY LCD表示ルーチン ; ;************************************************************** SA_LCD movf RA6SW,W ; SWが 1画面目か? btfsc STATUS,Z goto SA_LCD_FIN ; RA6SW=1だったとき、何もしないで終了 nextCC movf AccRelay,W addlw 0x30 movwf tmpH xorwf sCC,W btfsc STATUS,Z goto nextC9 movlw 0xCC call lcd_Cmd movf tmpH,W movwf sCC call lcd_Dat nextC9 movf BatRelay,W addlw 0x30 movwf tmpH xorwf sC9,W btfsc STATUS,Z goto SA_LCD_FIN movlw 0xC9 call lcd_Cmd movf tmpH,W movwf sC9 call lcd_Dat SA_LCD_FIN return ;************************************************************** ; ; ACC電圧比較ルーチン ; ; RA1 ACC電圧 ; RA2 切り替え電圧 ; の比較 ; ; RA1 >= RA2 だったら ACC RELAY ON ; RA1 < RA2 だったら 数秒後 ACC RELAY OFF ; ; RA1 < RA2 の立下りで BAT RELAY ON ; 数秒後 BAT RELAY OFF ; ;************************************************************** ACC_HIKAKU movf RA1valH,W movwf tmpH movf RA1valL,W movwf tmpL movf RA2valL,W subwf tmpL,W ; ACC - 比較 -> W ; >=0 で C=1 btfsc STATUS,C goto aHIKAKUH ; 下位は繰り下がり無し movf tmpH,W btfsc STATUS,Z goto aHIKUI ; 元から上位が 0なので低い decf tmpH,F ; 下位が繰り下がりありなので上位を -1 aHIKAKUH movf RA2valH,W subwf tmpH,W ; ACC - 比較 -> W ; >=0 で C=1 btfsc STATUS,C goto aTAKAI ; 上位も繰り下がり無し ACC > 比較 aHIKUI movf AccLowHi,W ; 前回の値をロード btfsc STATUS,Z goto aHIKUI1 ; 前回も 0のとき ; ACC LOWになって 1回だけ流れる AccLowHi=1のとき movlw D'0' movwf AccLowHi ; ACC LOWでも ACC RELAYは 1のときのみ movf AccRelay,W btfsc STATUS,Z goto aHIKUI05 ; AccLowHi=1で AccRelay=1のとき movlw D'1' movwf BatRelay ; BAT RELAY FLAG bsf PORTB,2 ; BAT RELAY ON aHIKUI05 movlw D'50' ; Batタイマー初期値セット movwf BatTimer2 movlw D'18' movwf BatTimer1 goto ACC_HIKAKU_FIN aHIKUI1 ; ACC LOWのカウントダウン中 movf AccTimer1,W btfss STATUS,Z goto ACC_HIKAKU_FIN ; カウントダウン中 何もせず終了 movf AccRelay,W ; 前回の値をロード btfsc STATUS,Z goto aHIKUI3 ; 前回も 0のとき ; ACC LOWの 5秒後に 1回だけ流れる movlw D'0' movwf AccRelay bcf PORTB,1 ; ACC RELAY OFF bcf PORTA,7 ; 液晶バックライト OFF ;内部クロック設定 100 1MHz ; bsf STATUS,RP0 ; bsf OSCCON,IRCF2 ; bcf OSCCON,IRCF1 ; bcf OSCCON,IRCF0 ; bcf STATUS,RP0 aHIKUI3 ; ACC LOWになって 5秒後に毎回流れる部分 goto ACC_HIKAKU_FIN ; ACC HIGHの時 aTAKAI movf AccLowHi,W btfss STATUS,Z goto aTAKAI2 ; 前回も高かったとき ; ACC HIGHになって 1回だけ流れる ; movlw D'0' ; movwf BatRelay movlw D'1' movwf AccRelay ; トリガーを 1 movwf AccLowHi ; bcf PORTB,2 ; BAT RELAY OFF bsf PORTB,1 ; ACC RELAY ON bsf PORTA,7 ; 液晶バックライト ON ;内部クロック設定 111 = 8MHz ; bsf STATUS,RP0 ; bsf OSCCON,IRCF2 ; bsf OSCCON,IRCF1 ; bsf OSCCON,IRCF0 ; bcf STATUS,RP0 aTAKAI2 ; ACC HIGHになって毎回流れる movlw D'100' movwf AccTimer2 movlw D'18' movwf AccTimer1 goto ACC_HIKAKU_FIN ACC_HIKAKU_FIN ; BAT RELAYの処理 movf BatRelay,W btfsc STATUS,Z goto aBat_FINISH ; BatRelay=0だったら終わり ; Bat Relay ON時の処理 movf BatTimer1,W btfss STATUS,Z goto aBat_FINISH aBat1 ; Bat RELAY ONになって数秒後 movlw D'0' movwf BatRelay ; トリガーを 1 bcf PORTB,2 ; Bat RELAY OFF aBat_FINISH ; BAT電圧のモニター ; EngStart回数のカウントに使う ; ; RA0 > RA2の立ち上がりからカウントし、 ; 1秒後も同じ条件だったら EngStartTを 1 BAT_HIKAKU movf RA0valH,W movwf tmpH movf RA0valL,W movwf tmpL movf RA2valL,W subwf tmpL,W ; BAT - 比較 -> W ; >=0 で C=1 btfsc STATUS,C goto bHIKAKUH ; 下位は繰り下がり無し movf tmpH,W btfsc STATUS,Z goto bHIKUI ; 元から上位が 0なので低い decf tmpH,F ; 下位が繰り下がりありなので上位を -1 bHIKAKUH movf RA2valH,W subwf tmpH,W ; ACC - 比較 -> W ; >=0 で C=1 btfsc STATUS,C goto bTAKAI ; 上位も繰り下がり無し ACC > 比較 bHIKUI ; カウントダウン中 movf EngStTimer1,W btfss STATUS,Z goto BAT_HIKAKU_FIN ; カウントダウン中 何もせず終了 ; カウントダウン終了 ; その時 BatRelay=1かどうかを確認 ; =0 だったらカウント無効にする movf BatRelay,W btfsc STATUS,Z goto BAT_HIKAKU_FIN ; BatRelay=0だったら終わり movlw D'1' movwf EngStartCT ; カウントダウン終了Tセット goto BAT_HIKAKU_FIN bTAKAI movlw D'10' ; EngStタイマー初期値セット movwf EngStTimer2 movlw D'18' movwf EngStTimer1 movf EngStartCT,W btfsc STATUS,Z goto BAT_HIKAKU_FIN ; BAT電圧 LOW -> カウントダウン終了 -> HIGHになって 1回目 ; EngStartTを 1にする movlw D'1' movwf EngStartT movlw D'0' movwf EngStartCT BAT_HIKAKU_FIN return ;************************************************** ; ; ループ全体で作る長時間カウンター ; ;************************************************** LoopCount ; 全体のループから Bat2 movf BatTimer2,W btfsc STATUS,Z goto Bat1 decf BatTimer2,F ; ゼロになって無かったら -1 goto Acc2 Bat1 movlw D'50' movwf BatTimer2 ; 初期値に戻す movf BatTimer1,W btfss STATUS,Z decf BatTimer1,F ; ゼロでない時 -1 Acc2 movf AccTimer2,W btfsc STATUS,Z goto Acc1 decf AccTimer2,F goto Eng2 Acc1 movlw D'100' movwf AccTimer2 ; 初期値に戻す movf AccTimer1,W btfss STATUS,Z decf AccTimer1,F ; ゼロでない時 Eng2 movf EngStTimer2,W btfsc STATUS,Z goto Eng1 decf EngStTimer2,F goto RA6SWTimer2 Eng1 movlw D'10' movwf EngStTimer2 ; 初期値に戻す movf EngStTimer1,W btfss STATUS,Z decf EngStTimer1,F ; ゼロでない時 RA6SWTimer2 movf RA6Timer2,W btfsc STATUS,Z goto RA6SWTimer1 decf RA6Timer2,F goto LoopCount_FIN RA6SWTimer1 movlw D'2' movwf RA6Timer2 ; 初期値に戻す movf RA6Timer1,W btfss STATUS,Z decf RA6Timer1,F ; ゼロでない時 LoopCount_FIN return RA6_SW_ONOFF ;************************************************************** ; ; RA6 SWの取り込み ; こっちは押したら ON、はなしたら OFF ; ;************************************************************** SW_INPUT btfss PORTA,6 goto SW_ON ; bit6 SETされてたら ON SW_OFF call wt10us ; 10us wait btfss PORTA,6 goto SW_FINISH ; 反転してたらチャタリング、終了 movf RA6SW,W btfss STATUS,Z ; Z=0 RA6SW=1 N-1は SWON? goto SW_FINISH ; SWそのまま、戻る goto on2off SW_ON call wt10us ; 10us wait btfsc PORTA,6 goto SW_FINISH ; 反転、チャタリング、終了 movf RA6SW,W btfsc STATUS,Z ; Z=1 RA6SW=0 N-1 は SWOFF? goto SW_FINISH ; SWそのまま、戻る goto off2on on2off movlw D'1' movwf RA6SW ; 1セット movlw D'1' movwf RA6SWT ; SW変更トリガーセット call initLCDA ; 2画面目を表示 call LCDN1CLR goto SW_FINISH off2on movlw D'0' movwf RA6SW ; 0セット movlw D'1' ; movwf RA6SWT ; SW変更トリガーセット call initLCDB ; 1画面目表示 call LCDN1CLR SW_FINISH return RA6_SW_XOR ;************************************************************** ; ; RA6 SWの取り込み ; こっちのサブルーチンは、RA6 ONになっていたら SWの状態を ; 反転する ; ;************************************************************** xSW_INPUT ; RA6Timer1が 0でない時は、チャタリング表示防止のため ; ルーチン通さない movf RA6Timer1,W btfss STATUS,Z goto xSW_FINISH ; SW押されてるか btfsc PORTA,6 goto xSW_FINISH ; タイマーの値を初期値に movlw D'2' movwf RA6Timer2 movlw D'100' movwf RA6Timer1 xSW_ON movlw D'1' movwf RA6SWT ; SW変更トリガーセット movf RA6SW,W btfsc STATUS,Z goto xSWN1_0 movlw D'0' ; N-1が 1だった場合 movwf RA6SW call initLCDB ; 1画面目表示 call LCDN1CLR goto xSW_FINISH xSWN1_0 movlw D'1' movwf RA6SW call initLCDA ; 2画面目を表示 call LCDN1CLR xSW_FINISH return ;************************************************************** ; ; ENG START回数カウントルーチン ; BAT電圧の上がったところのトリガー ; EngStartT が 1になっていたら ; EngStCountH,Lを +1して EEPROMルーチン呼び出す ; ;************************************************************** ENGSTART movf EngStartT,W ; BAT電圧の立ち上がったときセットされている btfsc STATUS,Z goto ENGSTART_FIN ; EngStartT=0だったとき、何もしないで終了 movlw D'0' movwf EngStartT ; トリガーフラグはクリアー movlw D'1' addwf EngStCountL,F ; +1する btfsc STATUS,C incf EngStCountH,F ; 繰り上がり movf EngStCountL,W movwf inpL movf EngStCountH,W movwf inpH call EEPROMWrite ENGSTART_FIN return ;************************************************************** ; ; EEPROM読み出しルーチン ; RA6SWTが 1になっていたら、毎回読み込む必要も無いけど ; EEPROMから値を読み出して EngStCountXへ書き込む ; ;************************************************************** EEPROMRead movf RA6SWT,W ; SWを 2画面目にしたか? btfsc STATUS,Z goto EEPROMRead_FIN ; RA6SWT=0だったとき、何もしないで終了 movlw D'0' movwf RA6SWT bcf STATUS,RP0 bcf STATUS,RP1 movlw 0x01 bsf STATUS,RP1 movwf EEADR bsf STATUS,RP0 bsf EECON1,RD bcf STATUS,RP0 movf EEDATA,W bcf STATUS,RP1 movwf EngStCountH movlw 0x02 bsf STATUS,RP1 movwf EEADR bsf STATUS,RP0 bsf EECON1,RD bcf STATUS,RP0 movf EEDATA,W bcf STATUS,RP1 movwf EngStCountL EEPROMRead_FIN bcf STATUS,RP0 bcf STATUS,RP1 return ;************************************************************** ; ; EEPROM書き込みルーチン ; ; inpHと inpLに値を入れこのルーチンを流すと ; EEADR 1,2に書き込みを行う ; ;************************************************************** EEPROMWrite bcf STATUS,RP0 bcf STATUS,RP1 movlw 0x01 bsf STATUS,RP1 movwf EEADR bcf STATUS,RP1 movf inpH,W bsf STATUS,RP1 movwf EEDATA bsf STATUS,RP0 bsf EECON1,WREN movlw 055H movwf EECON2 movlw 0AAH movwf EECON2 bsf EECON1,WR ELoop1 btfsc EECON1,WR goto ELoop1 bcf STATUS,RP1 bcf STATUS,RP0 movlw 0x02 bsf STATUS,RP1 movwf EEADR bcf STATUS,RP1 movf inpL,W bsf STATUS,RP1 movwf EEDATA bsf STATUS,RP0 bsf EECON1,WREN movlw 055H movwf EECON2 movlw 0AAH movwf EECON2 bsf EECON1,WR ELoop2 btfsc EECON2,WR goto ELoop2 bcf STATUS,RP1 bcf STATUS,RP0 return ;************************************************************** ; ; ENG START回数 LCD表示ルーチン ; ;************************************************************** ENGSTART_LCD movf RA6SW,W ; SWが 2画面目か? btfss STATUS,Z goto ENGSTART_LCD_FIN ; RA6SW=0だったとき、何もしないで終了 movf EngStCountH,W movwf inpH movf EngStCountL,W movwf inpL call hexdec16 nexta89 movf out5,W addlw 0x30 movwf out5 xorwf a89,W btfsc STATUS,Z goto nexta8A movlw 0x89 call lcd_Cmd movf out5,W movwf a89 call lcd_Dat nexta8A movf out4,W addlw 0x30 movwf out4 xorwf a8A,W btfsc STATUS,Z goto nexta8B movlw 0x8A call lcd_Cmd movf out4,W movwf a8A call lcd_Dat nexta8B movf out3,W addlw 0x30 movwf out3 xorwf a8B,W btfsc STATUS,Z goto nexta8C movlw 0x8B call lcd_Cmd movf out3,W movwf a8B call lcd_Dat nexta8C movf out2,W addlw 0x30 movwf out2 xorwf a8C,W btfsc STATUS,Z goto nexta8D movlw 0x8C call lcd_Cmd movf out2,W movwf a8C call lcd_Dat nexta8D movf out1,W addlw 0x30 movwf out1 xorwf a8D,W btfsc STATUS,Z goto ENGSTART_LCD_FIN movlw 0x8D call lcd_Cmd movf out1,W movwf a8D call lcd_Dat ENGSTART_LCD_FIN return RA0_BATT ;***************************************************** ; RA0 バッテリー電圧 ;***************************************************** ; ADCON0 10000 ; ADCS1,0 10 Fosc/32 ; CHS2,1,0 000 CH0 RA0 ; ; ADCON1 10100000 ; ADFM 1 右詰 ; ADCS2 0 ; VCFG1,0 10 VREF+ AVss movlw B'10000001' movwf ADCON0 movlw B'10100000' bsf STATUS,RP0 movwf ADCON1 bcf STATUS,RP0 call wt10us call wt10us call wt10us call wt10us call wt10us bsf ADCON0,GO ; A/D変換スタート RA0adloop btfsc ADCON0,GO goto RA0adloop ; 変換終了してなかったら loop bcf STATUS,RP1 bcf STATUS,RP0 ; bank0 movf ADRESH,W ; 上位 movwf RA0valH bsf STATUS,RP0 movf ADRESL,W ; 下位は BANK1 bcf STATUS,RP0 movwf RA0valL ; ; --------------- A/D 変換ここまで ; サンプリング 64回 ; 16bit加算 ; RA0addX = RA0addX+RA0VALx ; movf RA0valL,W ; 下位 addwf RA0addL,F btfsc STATUS,C incf RA0addH,F ; 下位がケタ上がり 上位を 1加算 movf RA0valH,W addwf RA0addH,F ; カウンターが 0になったかの判断 decfsz RA0count,F goto RA0_FINISH ; カウンターが 0で無いので、処理せず次へ ; サンプリング終了 movlw D'64' movwf RA0count ; カウンター初期値へ戻す ; 下位の bit2で四捨五入 bit2 = 00000100 ; 下位の bit5で四捨五入 bit2 = 00100000 btfss RA0addL,4 ; bit5が setだったら次を jump goto RA0_0 ; bit2=0の場合 繰り上げない ; 1足す処理 最初繰上げのケタだけ設定した後 ; 16bit加算 ; RA0addX = RA0addX+RA0VALx ; movlw B'00000000' movwf tmpH movlw B'00100000' movwf tmpL ; 繰り上げるケタだけをセット addwf RA0addL,F btfsc STATUS,C incf RA0addH,F ; 下位がケタ上がり 上位を 1加算 movf tmpH,W addwf RA0addH,F RA0_0 ; ; 64回加算したので 6回右シフトして液晶処理 ; Max 1023で 20.48V表示のため bcf STATUS,C ; 1回目 rrf RA0addH,F ; 右シフトは上位から rrf RA0addL,F bcf STATUS,C rrf RA0addH,F rrf RA0addL,F bcf STATUS,C rrf RA0addH,F rrf RA0addL,F bcf STATUS,C rrf RA0addH,F rrf RA0addL,F bcf STATUS,C rrf RA0addH,F rrf RA0addL,F movf RA0addH,W movwf inpH ; 変換用シンボルへ入れる movf RA0addL,W movwf inpL ; movlw D'0' movwf RA0addH ; 0に戻す movwf RA0addL RA0_1 ; RA6SWが 0 1画面目だったら電圧の表示をする movf RA6SW ; 0だと 1画面目 btfsc STATUS,Z goto RA0_FINISH ; 1だったので電圧表示無し ; バッテリー電圧部分の液晶表示 call hexdec16 next83 ; 10のけた movf out4,W btfss STATUS,Z ; Z=1 out4が 0だったら次を NOP goto next831 next83_0 ; 0で消していい時 movlw 0x20 ; スペースを入れる movwf out4 goto next832 next831 ; 1-9のとき movf out4,W addlw 0x30 ; W + 0x30 -> W movwf out4 next832 xorwf s83,W ; 1回前表示した数値と比較 btfsc STATUS,Z ; Zフラグはゼロ = 変化なし goto next84 ; 液晶表示変更なし次へ ; 10のケタ更新 movlw 0x83 call lcd_Cmd movf out4,W ; bcd変換 10のケタ movwf s83 ; N-1保存 call lcd_Dat next84 movf out3,W ; 1のケタ addlw 0x30 ; W + 0x30 -> W movwf out3 xorwf s84,W ; 1回前表示した数値と比較 btfsc STATUS,Z ; Zフラグはゼロ = 変化なし goto next85 ; 液晶表示変更なし次へ ; 1のケタ更新 movlw 0x84 call lcd_Cmd movf out3,W ; bcd変換 1のケタ movwf s84 ; N-1保存 call lcd_Dat next85 movf out2,W ; .1のケタ addlw 0x30 ; W + 0x30 -> W movwf out2 xorwf s85,W ; 1回前表示した数値と比較 btfsc STATUS,Z ; Zフラグはゼロ = 変化なし goto next86 ; 液晶表示変更なし次へ ; .1のケタ更新 movlw 0x85 call lcd_Cmd movf out2,W ; bcd変換 0.1のケタ movwf s85 ; N-1保存 call lcd_Dat next86 movf out1,W ; .01のケタ addlw 0x30 ; W + 0x30 -> W movwf out1 xorwf s86,W ; 1回前表示した数値と比較 btfsc STATUS,Z ; Zフラグはゼロ = 変化なし goto RA0_FINISH ; 液晶表示変更なし次へ ; .01のケタ更新 movlw 0x86 call lcd_Cmd movf out1,W movwf s86 ; N-1保存 call lcd_Dat RA0_FINISH return RA1_ACC ;***************************************************** ; RA1 ACC電圧 ;***************************************************** ; ADCON0 10001 ; ADCS1,0 10 Fosc/32 ; CHS2,1,0 001 CH1 RA1 ; ; ADCON1 10100000 ; ADFM 1 右詰 ; ADCS2 0 ; VCFG1,0 10 VREF+ AVss movlw B'10001001' movwf ADCON0 movlw B'10100000' bsf STATUS,RP0 movwf ADCON1 bcf STATUS,RP0 call wt10us call wt10us call wt10us call wt10us call wt10us bsf ADCON0,GO ; A/D変換スタート RA1adloop btfsc ADCON0,GO goto RA1adloop ; 変換終了してなかったら loop bcf STATUS,RP1 bcf STATUS,RP0 ; bank0 movf ADRESH,W ; 上位 movwf RA1valH bsf STATUS,RP0 movf ADRESL,W ; 下位は BANK1 bcf STATUS,RP0 movwf RA1valL ; ; --------------- A/D 変換ここまで ; サンプリング 8回 ; 16bit加算 ; RA1addX = RA1addX+RA1VALx ; movf RA1valL,W ; 下位 addwf RA1addL,F btfsc STATUS,C incf RA1addH,F ; 下位がケタ上がり 上位を 1加算 movf RA1valH,W addwf RA1addH,F ; カウンターが 0になったかの判断 decfsz RA1count,F goto RA1_FINISH ; カウンターが 0で無いので、処理せず次へ ; 64回サンプリング終了 movlw D'64' movwf RA1count ; カウンター初期値へ戻す ; 下位の bit2で四捨五入 bit2 = 00010000 btfss RA1addL,4 ; bit2が setだったら次を jump goto RA1_0 ; bit2=0の場合 繰り上げない ; 1足す処理 最初繰上げのケタだけ設定した後 ; 16bit加算 ; RA1addX = RA1addX+RA1VALx ; movlw B'00000000' movwf tmpH movlw B'00100000' movwf tmpL ; 繰り上げるケタだけをセット addwf RA1addL,F btfsc STATUS,C incf RA1addH,F ; 下位がケタ上がり 上位を 1加算 movf tmpH,W addwf RA1addH,F RA1_0 ; ; 64回加算したので 1/32 5回右シフトして液晶処理 ; Max 1023で 20.48V表示のため bcf STATUS,C ; 1回目 rrf RA1addH,F ; 右シフトは上位から rrf RA1addL,F bcf STATUS,C rrf RA1addH,F rrf RA1addL,F bcf STATUS,C rrf RA1addH,F rrf RA1addL,F bcf STATUS,C rrf RA1addH,F rrf RA1addL,F bcf STATUS,C rrf RA1addH,F rrf RA1addL,F movf RA1addH,W movwf RA1inpH ; 保存用シンボルへ入れる movf RA1addL,W movwf RA1inpL ; movlw D'0' movwf RA1addH ; 0に戻す movwf RA1addL RA1_FINISH return RA1_LCD ;***************************************************** ; RA1 LCD表示ルーチン ;***************************************************** RA1_1 ; RA6SWが 0 1画面目だったら電圧の表示をする movf RA6SW ; 0だと 1画面目 btfsc STATUS,Z goto RA1_LCDFIN ; 1だったので電圧表示無し ; ACC電圧部分の液晶表示 movf RA1inpH,W movwf inpH movf RA1inpL,W movwf inpL call hexdec16 next8B ; 10のけた movf out4,W btfss STATUS,Z ; Z=1 out4が 0だったら次を NOP goto next8B1 next8B_0 ; 0で消していい時 movlw 0x20 ; スペースを入れる movwf out4 goto next8B2 next8B1 ; 1-9のとき movf out4,W addlw 0x30 ; W + 0x30 -> W movwf out4 next8B2 xorwf s8B,W ; 1回前表示した数値と比較 btfsc STATUS,Z ; Zフラグはゼロ = 変化なし goto next8C ; 液晶表示変更なし次へ ; 10のケタ更新 movlw 0x8B call lcd_Cmd movf out4,W ; bcd変換 10のケタ movwf s8B ; N-1保存 call lcd_Dat next8C movf out3,W ; 1のケタ addlw 0x30 ; W + 0x30 -> W movwf out3 xorwf s8C,W ; 1回前表示した数値と比較 btfsc STATUS,Z ; Zフラグはゼロ = 変化なし goto next8D ; 液晶表示変更なし次へ ; 1のケタ更新 movlw 0x8C call lcd_Cmd movf out3,W ; bcd変換 1のケタ movwf s8C ; N-1保存 call lcd_Dat next8D movf out2,W ; .1のケタ addlw 0x30 ; W + 0x30 -> W movwf out2 xorwf s8D,W ; 1回前表示した数値と比較 btfsc STATUS,Z ; Zフラグはゼロ = 変化なし goto next8E ; 液晶表示変更なし次へ ; .1のケタ更新 movlw 0x8D call lcd_Cmd movf out2,W ; bcd変換 0.1のケタ movwf s8D ; N-1保存 call lcd_Dat next8E movf out1,W ; .01のケタ addlw 0x30 ; W + 0x30 -> W movwf out1 xorwf s8E,W ; 1回前表示した数値と比較 btfsc STATUS,Z ; Zフラグはゼロ = 変化なし goto RA1_FINISH ; 液晶表示変更なし次へ ; .01のケタ更新 movlw 0x8E call lcd_Cmd movf out1,W movwf s8E ; N-1保存 call lcd_Dat RA1_LCDFIN return RA4_SUB ;***************************************************** ; RA4 SUBバッテリー電圧 ;***************************************************** ; ADCON0 10100 ; ADCS1,0 10 Fosc/32 ; CHS2,1,0 100 CH4 RA4 ; ; ADCON1 10100000 ; ADFM 1 右詰 ; ADCS2 0 ; VCFG1,0 10 VREF+ AVss movlw B'10100001' movwf ADCON0 movlw B'10100000' bsf STATUS,RP0 movwf ADCON1 bcf STATUS,RP0 call wt10us call wt10us call wt10us call wt10us call wt10us bsf ADCON0,GO ; A/D変換スタート RA4adloop btfsc ADCON0,GO goto RA4adloop ; 変換終了してなかったら loop bcf STATUS,RP1 bcf STATUS,RP0 ; bank0 movf ADRESH,W ; 上位 movwf RA4valH bsf STATUS,RP0 movf ADRESL,W ; 下位は BANK1 bcf STATUS,RP0 movwf RA4valL ; ; --------------- A/D 変換ここまで ; サンプリング 8回 ; 16bit加算 ; RA4addX = RA4addX+RA4VALx ; movf RA4valL,W ; 下位 addwf RA4addL,F btfsc STATUS,C incf RA4addH,F ; 下位がケタ上がり 上位を 1加算 movf RA4valH,W addwf RA4addH,F ; カウンターが 0になったかの判断 decfsz RA4count,F goto RA4_FINISH ; カウンターが 0で無いので、処理せず次へ ; 64回サンプリング終了 movlw D'64' movwf RA4count ; カウンター初期値へ戻す ; 下位の bit2で四捨五入 bit2 = 00000100 btfss RA4addL,4 ; bit2が setだったら次を jump goto RA4_0 ; bit2=0の場合 繰り上げない ; 1足す処理 最初繰上げのケタだけ設定した後 ; 16bit加算 ; RA4addX = RA4addX+RA4VALx ; movlw B'00000000' movwf tmpH movlw B'00100000' movwf tmpL ; 繰り上げるケタだけをセット addwf RA4addL,F btfsc STATUS,C incf RA4addH,F ; 下位がケタ上がり 上位を 1加算 movf tmpH,W addwf RA4addH,F RA4_0 ; ; 64回加算したので 1/32 5回右シフトして液晶処理 ; Max 1023で 20.48V表示のため bcf STATUS,C ; 1回目 rrf RA4addH,F ; 右シフトは上位から rrf RA4addL,F bcf STATUS,C rrf RA4addH,F rrf RA4addL,F bcf STATUS,C rrf RA4addH,F rrf RA4addL,F bcf STATUS,C rrf RA4addH,F rrf RA4addL,F bcf STATUS,C rrf RA4addH,F rrf RA4addL,F movf RA4addH,W movwf inpH ; 変換用シンボルへ入れる movf RA4addL,W movwf inpL ; movlw D'0' movwf RA4addH ; 0に戻す movwf RA4addL RA4_1 ; RA6SWが 0 1画面目だったら電圧の表示をする movf RA6SW ; 0だと 1画面目 btfsc STATUS,Z goto RA4_FINISH ; 1だったので電圧表示無し ; バッテリー電圧部分の液晶表示 call hexdec16 nextC3 ; 10のけた movf out4,W btfss STATUS,Z ; Z=1 out4が 0だったら次を NOP goto nextC31 nextC3_0 ; 0で消していい時 movlw 0x20 ; スペースを入れる movwf out4 goto nextC32 nextC31 ; 1-9のとき movf out4,W addlw 0x30 ; W + 0x30 -> W movwf out4 nextC32 xorwf sC3,W ; 1回前表示した数値と比較 btfsc STATUS,Z ; Zフラグはゼロ = 変化なし goto nextC4 ; 液晶表示変更なし次へ ; 10のケタ更新 movlw 0xC3 call lcd_Cmd movf out4,W ; bcd変換 10のケタ movwf sC3 ; N-1保存 call lcd_Dat nextC4 movf out3,W ; 1のケタ addlw 0x30 ; W + 0x30 -> W movwf out3 xorwf sC4,W ; 1回前表示した数値と比較 btfsc STATUS,Z ; Zフラグはゼロ = 変化なし goto nextC5 ; 液晶表示変更なし次へ ; 1のケタ更新 movlw 0xC4 call lcd_Cmd movf out3,W ; bcd変換 1のケタ movwf sC4 ; N-1保存 call lcd_Dat nextC5 movf out2,W ; .1のケタ addlw 0x30 ; W + 0x30 -> W movwf out2 xorwf sC5,W ; 1回前表示した数値と比較 btfsc STATUS,Z ; Zフラグはゼロ = 変化なし goto nextC6 ; 液晶表示変更なし次へ ; .1のケタ更新 movlw 0xC5 call lcd_Cmd movf out2,W ; bcd変換 0.1のケタ movwf sC5 ; N-1保存 call lcd_Dat nextC6 movf out1,W ; .01のケタ addlw 0x30 ; W + 0x30 -> W movwf out1 xorwf sC6,W ; 1回前表示した数値と比較 btfsc STATUS,Z ; Zフラグはゼロ = 変化なし goto RA4_FINISH ; 液晶表示変更なし次へ ; .01のケタ更新 movlw 0xC6 call lcd_Cmd movf out1,W movwf sC6 ; N-1保存 call lcd_Dat RA4_FINISH return RA2_KIJYUN ;***************************************************** ; RA2 切り替え比較電圧 ;***************************************************** ; ADCON0 10010 ; ADCS1,0 10 Fosc/32 ; CHS2,1,0 010 CH2 RA2 ; ; ADCON1 10100000 ; ADFM 1 右詰 ; ADCS2 0 ; VCFG1,0 10 VREF+ AVss movlw B'10010001' movwf ADCON0 movlw B'10100000' bsf STATUS,RP0 movwf ADCON1 bcf STATUS,RP0 call wt10us call wt10us call wt10us call wt10us call wt10us bsf ADCON0,GO ; A/D変換スタート RA2adloop btfsc ADCON0,GO goto RA2adloop ; 変換終了してなかったら loop bcf STATUS,RP1 bcf STATUS,RP0 ; bank0 movf ADRESH,W ; 上位 movwf RA2valH bsf STATUS,RP0 movf ADRESL,W ; 下位は BANK1 bcf STATUS,RP0 movwf RA2valL ; ; --------------- A/D 変換ここまで ; サンプリング 64 ; 16bit加算 ; RA2addX = RA2addX+RA2VALx ; movf RA2valL,W ; 下位 addwf RA2addL,F btfsc STATUS,C incf RA2addH,F ; 下位がケタ上がり 上位を 1加算 movf RA2valH,W addwf RA2addH,F ; カウンターが 0になったかの判断 decfsz RA2count,F goto RA2_FINISH ; カウンターが 0で無いので、処理せず次へ ; 8回サンプリング終了 movlw D'64 movwf RA2count ; カウンター初期値へ戻す ; 下位の bit2で四捨五入 bit2 = 00010000 btfss RA2addL,4 ; bit2が setだったら次を jump goto RA2_0 ; bit2=0の場合 繰り上げない ; 1足す処理 最初繰上げのケタだけ設定した後 ; 16bit加算 ; RA2addX = RA2addX+RA2VALx ; movlw B'00000000' movwf tmpH movlw B'00100000' movwf tmpL ; 繰り上げるケタだけをセット addwf RA2addL,F btfsc STATUS,C incf RA2addH,F ; 下位がケタ上がり 上位を 1加算 movf tmpH,W addwf RA2addH,F RA2_0 ; ; 64回加算したので 1/32 5回右シフトして液晶処理 ; Max 1023で 20.48V表示のため bcf STATUS,C ; 1回目 rrf RA2addH,F ; 右シフトは上位から rrf RA2addL,F bcf STATUS,C rrf RA2addH,F rrf RA2addL,F bcf STATUS,C rrf RA2addH,F rrf RA2addL,F bcf STATUS,C rrf RA2addH,F rrf RA2addL,F bcf STATUS,C rrf RA2addH,F rrf RA2addL,F movf RA2addH,W movwf inpH ; 変換用シンボルへ入れる movf RA2addL,W movwf inpL ; movlw D'0' movwf RA2addH ; 0に戻す movwf RA2addL RA2_1 ; RA6SWが 0 1画面目だったら電圧の表示をする movf RA6SW ; 0だと 1画面目 btfss STATUS,Z goto RA2_FINISH ; 0だったので電圧表示無し ; バッテリー電圧部分の液晶表示 call hexdec16 nextaC7 ; 10のけた movf out4,W btfss STATUS,Z ; Z=1 out4が 0だったら次を NOP goto nextaC71 nextaC7_0 ; 0で消していい時 movlw 0x20 ; スペースを入れる movwf out4 goto nextaC72 nextaC71 ; 1-9のとき movf out4,W addlw 0x30 ; W + 0x30 -> W movwf out4 nextaC72 xorwf aC7,W ; 1回前表示した数値と比較 btfsc STATUS,Z ; Zフラグはゼロ = 変化なし goto nextaC8 ; 液晶表示変更なし次へ ; 10のケタ更新 movlw 0xC7 call lcd_Cmd movf out4,W ; bcd変換 10のケタ movwf aC7 ; N-1保存 call lcd_Dat nextaC8 movf out3,W ; 1のケタ addlw 0x30 ; W + 0x30 -> W movwf out3 xorwf aC8,W ; 1回前表示した数値と比較 btfsc STATUS,Z ; Zフラグはゼロ = 変化なし goto nextaCA ; 液晶表示変更なし次へ ; 1のケタ更新 movlw 0xC8 call lcd_Cmd movf out3,W ; bcd変換 1のケタ movwf aC8 ; N-1保存 call lcd_Dat nextaCA movf out2,W ; .1のケタ addlw 0x30 ; W + 0x30 -> W movwf out2 xorwf aCA,W ; 1回前表示した数値と比較 btfsc STATUS,Z ; Zフラグはゼロ = 変化なし goto nextaCC ; 液晶表示変更なし次へ ; .1のケタ更新 movlw 0xCA call lcd_Cmd movf out2,W ; bcd変換 0.1のケタ movwf aCA ; N-1保存 call lcd_Dat nextaCC movf out1,W ; .01のケタ addlw 0x30 ; W + 0x30 -> W movwf out1 xorwf aCC,W ; 1回前表示した数値と比較 btfsc STATUS,Z ; Zフラグはゼロ = 変化なし goto RA2_FINISH ; 液晶表示変更なし次へ ; .01のケタ更新 movlw 0xCB call lcd_Cmd movf out1,W movwf aCC ; N-1保存 call lcd_Dat RA2_FINISH return initEEPROMRead bcf STATUS,RP0 bcf STATUS,RP1 movlw 0x01 bsf STATUS,RP1 movwf EEADR bsf STATUS,RP0 bsf EECON1,RD bcf STATUS,RP0 movf EEDATA,W bcf STATUS,RP1 movwf EngStCountH movlw 0x02 bsf STATUS,RP1 movwf EEADR bsf STATUS,RP0 bsf EECON1,RD bcf STATUS,RP0 movf EEDATA,W bcf STATUS,RP1 movwf EngStCountL bcf STATUS,RP0 bcf STATUS,RP1 return LCDN1CLR ;*************************************************************** ; ; SW切り替えて画面が変わったときだけ N-1の値を全てクリアーする ; ;*************************************************************** movlw H'FF' movwf s83 movwf s84 movwf s85 movwf s86 movwf s8B movwf s8C movwf s8D movwf s8E movwf sC3 movwf sC4 movwf sC5 movwf sC6 movwf sC3 movwf sC9 movwf sCC movwf a89 movwf a8A movwf a8B movwf a8C movwf a8D movwf aC7 movwf aC8 movwf aCA movwf aCC LCDN1FIN return initA bcf STATUS,RP1 bcf STATUS,RP0 ; bank0 clrf PORTA clrf PORTB clrwdt bsf STATUS,RP0 ; bank1 bsf OPTION_REG,7 movlw B'00000000' ; 0 = Output movwf TRISB movlw B'01111111' ; 1 = input movwf TRISA bcf STATUS,RP0 ; bank0 clrf PORTB ;内部クロック設定 111 = 8MHz bsf STATUS,RP0 bsf OSCCON,IRCF2 bsf OSCCON,IRCF1 bsf OSCCON,IRCF0 ; movlw B'01110000' ; movwf OSCCON bcf STATUS,RP0 ; bank0 return initB bsf STATUS,RP0 movlw B'00011111' ; AN0-AN4間で Analog入力 movwf ANSEL bcf STATUS,RP0 return initC ; ; 定数領域のクリアー movlw D'64' movwf RA0count ; BAT movwf RA1count ; ACC movwf RA2count ; 切り替え movwf RA4count ; SUB movlw D'100' movwf AccTimer2 movlw D'50' movwf BatTimer2 movlw D'18' movwf BatTimer1 movwf AccTimer1 movlw D'0' movwf RA6Timer1 movlw D'0' movwf RA6Timer2 movlw D'0' movwf RA0addH movwf RA0addL movwf RA1addH movwf RA1addL movwf RA2addH movwf RA2addL movwf RA4addH movwf RA4addL movwf inpL movwf inpH movlw D'0' movwf BatRelay movwf AccLowHi movwf AccRelay movwf RA6SWT movlw D'1' return initD call lcd_Init ; ;【Control Commandの一覧表】 ; Commnad DB7 6 5 4 3 2 1 0 説 明 ;Clear Display 0 0 0 0 0 0 0 1 全消去、CursorはHomeへ ;Cursor At Home 0 0 0 0 0 0 1 * 表示内容は変化なし ;Entry Mode Set 0 0 0 0 0 1 I/D S I/D=Increment/Decrement ; S=With Display Shift ;Display On/Off 0 0 0 0 1 D C B D=Display C=Cursor B=Blink ;Cursor/Dislay Shift 0 0 0 1 S/CR/L * * S/C=Display/Cursor R/L=Right/Left ;Function Set 0 0 1 DL N F * * DL=8/4Bit N=2/1Line F=Large/Small ;CGRAM Address Set 0 1 CCRAM Address Character Generator RAM ;DDRAM Address Set 1 L DDRAM Address Display RAM L=Line ;Busy Flag/Adrs Read BF Address BF=Busy Flag ;Data Write 8 Bits Data CGRAM/DDRAM Common ;Data Read 8 Bits Data CGRAM/DDRAM Common ; movlw B'00000110' call lcd_Cmd movlw B'00001100' call lcd_Cmd return initLCDA ; ; 液晶表示 ; 通常時の表示 ; ; 0123456789ABCDEF ; +---------------- ; 8|BAT ACC ; C|SUB S A movlw 0x80 call lcd_Cmd movlw "B" call lcd_Dat movlw "A" call lcd_Dat movlw "T" call lcd_Dat movlw " " call lcd_Dat movlw " " call lcd_Dat movlw " " call lcd_Dat movlw " " call lcd_Dat movlw " " call lcd_Dat movlw "A" call lcd_Dat movlw "C" call lcd_Dat movlw "C" call lcd_Dat movlw " " call lcd_Dat movlw " " call lcd_Dat movlw " " call lcd_Dat movlw " " call lcd_Dat movlw " " call lcd_Dat movlw 0xC0 call lcd_Cmd movlw "S" call lcd_Dat movlw "U" call lcd_Dat movlw "B" call lcd_Dat movlw " " call lcd_Dat movlw " " call lcd_Dat movlw " " call lcd_Dat movlw " " call lcd_Dat movlw " " call lcd_Dat movlw "B" call lcd_Dat movlw " " call lcd_Dat movlw " " call lcd_Dat movlw "A" call lcd_Dat movlw " " call lcd_Dat movlw " " call lcd_Dat movlw " " call lcd_Dat movlw " " call lcd_Dat return initLCDB ; ; 液晶表示 ; SW ON時の表示 ; ; 0123456789ABCDEF ; +---------------- ; 8|EngStart ; C|Thresh . movlw 0x80 call lcd_Cmd movlw "E" call lcd_Dat movlw "n" call lcd_Dat movlw "g" call lcd_Dat movlw "S" call lcd_Dat movlw "t" call lcd_Dat movlw "a" call lcd_Dat movlw "r" call lcd_Dat movlw "t" call lcd_Dat movlw " " call lcd_Dat movlw " " call lcd_Dat movlw " " call lcd_Dat movlw " " call lcd_Dat movlw " " call lcd_Dat movlw " " call lcd_Dat movlw " " call lcd_Dat movlw " " call lcd_Dat movlw 0xC0 call lcd_Cmd movlw "T" call lcd_Dat movlw "h" call lcd_Dat movlw "r" call lcd_Dat movlw "e" call lcd_Dat movlw "s" call lcd_Dat movlw "h" call lcd_Dat movlw " " call lcd_Dat movlw " " call lcd_Dat movlw " " call lcd_Dat movlw "." call lcd_Dat movlw " " call lcd_Dat movlw " " call lcd_Dat movlw "V" call lcd_Dat movlw " " call lcd_Dat movlw " " call lcd_Dat movlw " " call lcd_Dat return ; ; ;---------------------------------------- ;- LCD Initial operation - ;- Use call lcd_Init - ;---------------------------------------- ; lcd_Init bcf LCDPORT,LCD_RS bcf LCDPORT,LCD_E movlw 150 ; 15mS wait call waitOpe movlw B'00110000' call lcd_Out movlw 50 ; 5mS wait call waitOpe movlw B'00110000' call lcd_Out call wt100us movlw B'00110000' call lcd_Out call wt100us movlw B'00100000' call lcd_Out call wt100us movlw B'00101000' call lcd_Cmd movlw B'00001000' call lcd_Cmd movlw B'00000001' call lcd_Cmd movlw 17 ; 1.7mS wait call waitOpe return ; ; ; ;---------------------------------------- ;- COMMAND to LCD operation - ;- Use movlw COMMAND - ;- call lcd_Cmd - ;- DATA to LCD operation - ;- Use movlw DATA - ;- call lcd_Dat - ;---------------------------------------- ; lcd_Cmd ; Command to LCD bcf LCDPORT,LCD_RS goto lcd_Out4 lcd_Dat ; Data to LCD bsf LCDPORT,LCD_RS lcd_Out4 movwf lcdTmp1 ; Entry :w = Command or Data movlw B'11110000' andwf lcdTmp1,w call lcd_Out swapf lcdTmp1,f movlw B'11110000' andwf lcdTmp1,w call lcd_Out call wt100us return ; ; ; ;---------------------------------------- ;- 4bit DATA to LCD operation - ;- Use movlw B'????0000' - ;- call lcd_Out - ;---------------------------------------- ; lcd_Out movwf lcdTmp0 movlw B'00001111' andwf LCDPORT,f movf lcdTmp0,w iorwf LCDPORT,f bsf LCDPORT,LCD_E nop bcf LCDPORT,LCD_E return ; ; ; waitOpe ; Wait operation movwf lcdTim1 ; Wait time = W * 100uS waitOp1 call wt100us decfsz lcdTim1,f goto waitOp1 return ; ; ; wt100us ; 100uS wait operation movlw W100US movwf lcdTim0 wt100u1 decfsz lcdTim0,f goto wt100u1 return ; wt10us ; 10us wait operation nop ; 10MHzだと 1サイクル 0.4μsなので nop ; 25サイクル実行すると 10μsとなる nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop return ; ; 長時間用のタイマー ; ;100μsec DLYS movlw W100US MOVWF CNT1 TM_1 DECFSZ CNT1,F GOTO TM_1 NOP RETURN ;2msec DLY2m DLYM MOVLW d'21' MOVWF CNT2 TM_2 CALL DLYS DECFSZ CNT2,F GOTO TM_2 RETURN ;5msec DLY5m DLYL MOVLW d'51' MOVWF CNT3 TM_3 CALL DLYS DECFSZ CNT3,F GOTO TM_3 RETURN DLY20m MOVLW d'200' MOVWF CNT3 DLY20m_1 CALL DLYS DECFSZ CNT3,F GOTO DLY20m_1 RETURN DLY100m MOVLW d'20' MOVWF CNT4 DLY100m_1 CALL DLYL DECFSZ CNT4,F GOTO DLY100m_1 RETURN ;1sec WAIT1SEC MOVLW d'201' MOVWF CNT4 TM_4 CALL DLYL DECFSZ CNT4,F GOTO TM_4 RETURN hexdec16: ;16ビット(2バイト)数値を10進数5桁のBCD値に変換する ;引き数は inpH(上位),inpL(下位) の2バイト ;結果は out5,out4,out3,out2,out1 に得られる。 ;右の out1 が下位の数になる ;使用変数宣言の際に out1 の下で、ラベル名 dec_top: を記述しておくこと。 ;------------------------------ hexdec16 での使用変数 ;inpH ds 1 ; 変換したい値(16ビット。変換後は壊れる) ;inpL ds 1 ;〜下位 ;out5 ds 1 ;10進格納場所(5バイト) ;out4 ds 1 ;out3 ds 1 ;out2 ds 1 ;out1 ds 1 ;〜下位 ;dec_top: ;間接アクセス用ラベル ;srlc1 ds 1 ; カウンタ(サブルーチンで使用) ;srwk1 ds 1 ; 一時余り格納場所(サブルーチンで使用) ;------------------------------ ; ;使用例 ; movlw 0ffh ;ffffh=65535 ; movwf inpH ; movlw 0ffh ; movwf inpL ; call hexdec16 ; ;------------------------------ movlw dec_top ;格納場所初期値 movwf 4h ;4h=fsr call devide ;最下位変換 call devide call devide call devide call devide ;最上位変換 return devide: ;÷10サブルーチン (10で除算) movlw 16 ;16ビットくり返し movwf srlc1 clrf srwk1 devide0: bcf 3h,0 ;キャリフラグのクリア rlf inpL,1 rlf inpH,1 rlf srwk1,1 movlw 11110110b addwf srwk1,0 btfsc 3h,0 movwf srwk1 btfsc 3h,0 incf inpL,1 decfsz srlc1,1 goto devide0 decf 4h,1 ;4h=fsr movf srwk1,0 movwf 0h ;余り (0h=indirect) return hex2oct: ; ; 自作 10bit A/Dから OCTAL 4ケタ変換 ; out5は常に 0 ; BCD 4〜1に 0〜7の数字が入る ; 元の数字は inpHと inp Lに入れておく ; movlw B'00000111' ; 1のケタ andwf inpL,W movwf out1 ; 1のケタ保存 movlw B'00111000' ; 10のケタ andwf inpL,W movwf octtmp ; 一時保存 rrf octtmp,1 ; 1bit右 octtmpへ上書き rrf octtmp,1 ; 1bit右 octtmpへ上書き rrf octtmp,1 ; 1bit右 octtmpへ上書き movlw B'00000111' ; 1のケタのみ andwf octtmp,W ; 必要なところだけ mask movwf out2 ; 10のケタ保存 movlw B'11000000' ; 100のケタ andwf inpL,W movwf octtmp ; 一時保存 rrf octtmp,1 ; 1bit右 octtmpへ上書き rrf octtmp,1 ; 1bit右 octtmpへ上書き rrf octtmp,1 ; 1bit右 octtmpへ上書き rrf octtmp,1 ; 1bit右 octtmpへ上書き rrf octtmp,1 ; 1bit右 octtmpへ上書き rrf octtmp,1 ; 1bit右 octtmpへ上書き movlw B'00000001' ; 100のケタ andwf inpH,W movwf octtmp2 ; 一時保存 rlf octtmp2,1 ; 1bit左 octtmp2へ上書き rlf octtmp2,1 ; 1bit左 octtmp2へ上書き movlw B'00000100' ; 必要なところだけ mask andwf octtmp2,W iorwf octtmp,W ; さっき計算した下 2bitと orする movwf out3 ; 100のケタ保存 movlw B'00001110' ; 1000のケタ andwf inpH,W movwf octtmp ; 一時保存 rrf octtmp,1 ; 1bit右 octtmpへ上書き movlw B'00000111' ; 必要なところだけ mask andwf octtmp,W movwf out4 ; 1000のケタ保存 movlw B'01110000' ; 10000のケタ andwf inpH,W movwf octtmp ; 一時保存 rrf octtmp,1 ; 1bit右 octtmpへ上書き rrf octtmp,1 ; 1bit右 octtmpへ上書き rrf octtmp,1 ; 1bit右 octtmpへ上書き rrf octtmp,1 ; 1bit右 octtmpへ上書き movlw B'00000111' ; 必要なところだけ mask andwf octtmp,W movwf out5 ; 10000ケタ目は常にゼロ return END