;***************************************************************************** ;******************* LCメーター プログラム ************************* ;***************************************************************************** ; ; PIC16F1827 ; clock:12.8MHz (クリスタル) ; Cc = 1,000pF±2% (校正用ポリフェニルサルファイドコンデンサー) ; Cs = 680pF±5% (常設ポリフェニルサルファイドコンデンサー) ; Ls = 45uH±2% (常設トロイダルコイル-自作手巻きコイル) ; FS = 890kHz±10% ???(常設のLsとCsでの発振周波数、2進数で3バイト) ; C コンデンサーの容量の単位はpFで計算する ; L コイルのインダクタンスの単位はuHで計算する ; 1/{4π^2xL(uH)xC(pF)}=2.5330255910588400x10^16(但し L=1uH,C=1pF) LIST P=PIC16F1827 INCLUDE P16F1827.INC __CONFIG _CONFIG1, _FOSC_HS & _WDTE_OFF & _PWRTE_ON & _MCLRE_ON & _CP_OFF & _CPD_OFF & _BOREN_ON & _CLKOUTEN_ON & _IESO_OFF & _FCMEN_OFF __CONFIG _CONFIG2, _WRT_OFF & _PLLEN_OFF & _STVREN_ON & _BORV_HI & _LVP_OFF ;// CONFIG1の設定 ; FOSC = HS // 高速クリスタル(OSC1, OSC2を使用する ; WDTE = OFF // ウオッチドッグタイマー無し(OFF) ; PWRTE = ON // 電源ONから64ms後にプログラムを開始する(ON) ; MCLRE = ON // 外部リセット信号を使用する(On) ; CP = OFF // プログラムメモリーを保護しない(OFF) ; CPD = OFF // データメモリーを保護しない(OFF) ; BOREN = ON // 電源電圧降下常時監視機能ON(ON) ; CLKOUTEN = ON // CLKOUTピンをクロック出力で使用する(ON) ; IESO = OFF // 外部・内部クロックの切替えでの起動はなし(OFF) ; FCMEN = OFF // 外部クロック監視しない(FCMEN_OFF) ; ;// CONFIG2の設定 ; WRT = OFF // Flashメモリーを保護しない(OFF) ; PLLEN = OFF // 動作クロックを32MHzでは動作させない(OFF) ; STVREN = ON // スタックがオーバフローやアンダーフローしたらリセットをする(ON) ; BORV = HI // 電源電圧降下常時監視電圧(2.5V)設定(HI) ; LVP = OFF // 低電圧プログラミング機能使用しない(OFF) ; PICの ピン 接続 ; RA0 17 - ; RA1 18 CalRy(キャリブレーション用リレー)) ; RA2 1 LED0(Run表示) ; RA3 2 LED1(測定中表示) ; RA4 3 - ; RA5 4 MCLR ; RA6 15 - ; RA7 16 CLKIN(12.8MHzクロック入力) ; RB0 6 SW0(キャリブレーション) ; RB1 7 SDA1(I2Cシグナル) ; RB2 8 SW1(L/C切替信号入力) ; RB3 9 SW2(LCD2行目表示切替) ; RB4 10 SCL1(I2Cクロック) ; RB5 11 - ; RB6 12 T1CKI(周波数カウンター信号入力) ; RB7 13 - ; #DEFINE SW0 PORTB,0 ; キャリブレーション #DEFINE SW1 PORTB,2 ; (L/C切替信号入力) #DEFINE SW2 PORTB,3 ; LCD2行目表示項目切替 #DEFINE CalRy PORTA,1 ; キャリブレーション用リレー #DEFINE LED0 PORTA,2 ; RUN表示LED #DEFINE LED1 PORTA,3 ; 測定中表示LED #DEFINE SSP1INT IRQ,0 ; SSP1IFの代用フラグ #DEFINE CALIRQ IRQ,1 ; キャリブレーション要求フラグ ; ; 使用タイマ(プログラムループ) ; 200mS LCDパワーオンリセット待ち ; 5mS LCD初期化ルーチン ; 1mS LCD初期化ルーチン ; 50uS LCD初期化ルーチン,書き込み待ち ; 27uS 書き込み待ち ;**************************************************** ; 変数の宣言 ;**************************************************** CBLOCK 020h ; BANK0 ; Binary→BCD変換 BYTE0,BYTE1,BYTE2,BYTE3 ; Binary整数部 0-3バイト BYTEM1,BYTEM2,BYTEM3,BYTEM4 ; Binary少数部 1-4バイト DIGITM78 ; BCD少数部78桁 DIGITM56,DIGITM34,DIGITM12 ; BCD少数部1から6桁 DIGIT01,DIGIT23,DIGIT45 ; BCD整数部1から6桁 DIGIT67,DIGIT89,DIGITAB ; BCD整数部7から12桁 DIGITCD,DIGITEF,DIGITXRA ; BCD整数部13から18桁 nDigit ; BCD整数部の桁数 SHIFT ; Shift counter TEMP ; temporary work (24) ; 周波数カウンター TM2_Count ; TM2 カウント回数 TM2_Done ; TM2 カウント完了 GateTime ; 測定時間 0=500ms, 1=1S (3)→(27) ; タイマー(LCD用) CNT1S ; 1Sカウンタ CNT200mS ; 200mSカウンタ CNT5mS ; 5mSカウンタ CNT1mS ; 1mSカウンタ CNT50uS ; 50μSカウンタ CNT27uS ; 27μSカウンタ (6)→ (33) ; 操作モード Mode ;ModeR ;bit0=0 キャリブレーション開始 ;Mode0 ;bit0=1 Waiting Loop(Ry On) ;Mode1 ;bit1=1 Calibration(1) ;MOde2 ;bit2=1 Waiting Loop(Ry Off) ;MOde3 ;bit3=1 Calibration(2) ;Mode4 ;bit4=1 Measurement ;bit6=1 Sw1 チャタリング防止中 ;bit7=1 Sw0 チャタリング防止中 (1)→(34) ; 表示モード Smode ; LCDへ表示するメニュー選択変数 ;Smode 0 ;bit0; 1= Cx 測定コンデンサー容量 ;Smode 1 ;bit1; 1= Cs 常設コンデンサー容量 ;Smode 2 ;bit2; 1= Cs 校正コンデンサー容量 ;Smode 3 ;bit3; 1= Lx 測定コイルインダクタンス ;Smode 4 ;bit4; 1= Ls 常設コイルインダクタンス ;Smode 5 ;bit5; 1= Fx 測定周波数 ;Smode 6 ;bit6; 1= Fs 常設周波数 ;Smode 7 ;bit7; 1= Fc 校正時周波数 (1)→(35) ; スイッチ LCsel ;SW1の状態を記録 ;bit0 0=L側 1=C側 (1)→(36) ; 算術計算 nX,nY,nZ ; X, Y, Zの整数部分の桁数 X0,X1,X2,X3,X4,X5,X6 ; 乗数/除数 Y0,Y1,Y2,Y3,Y4,Y5,Y6 ; 被乗数/被除数 Z0,Z1,Z2,Z3,Z4,Z5,Z6,Z7 ; 積/商の整数部分 (25)→(61) ; L/Cメーター nCs,nCc,nCx,nLs,nLx ; C,Lの整数部分の桁数 K0,K1,K2,K3 ; L/C計算の定数 (9)→(70) ENDC CBLOCK 070h ; BANK共通 ; 割込み用 IRQ ;bit0 = SSP1INT 0 = SSP1INT無し 1 = SSP1INT有り ;bit7 = CALIRQ 0 = CALIRQ無し 1 = CALRQT有り ; I2C用 I2char ; 1文字(I2C送信用) I2CBuf,I2CBufx ; I2C用バッファ I2CSNDdata ; I2C送信データ (5) ; 汎用 Buf ; 汎用バッファ、LCD表示、データ読み書き work0,work1,work2,work3 ; work TempN ; 作業用変数 Debug SmHold ; Smodeを一時的に保持 (8)→(13) iSign ; ±の符号 0=+, 1=? (1)→(14) ENDC CBLOCK 0A0h ; BANK1 ; L/Cメーター Cs0,Cs1,Cs2,Cs3 ; 常設コンデンサー容量(2進浮動小数) Cc0,Cc1,Cc2,Cc3 ; 参照コンデンサー容量(2進浮動小数) Cx0,Cx1,Cx2,Cx3 ; 測定コンデンサー容量(2進浮動小数) Ls0,Ls1,Ls2,Ls3 ; 常設コイルインダクタンス(2進浮動小数) Lx0,Lx1,Lx2,Lx3 ; 測定コイルインダクタンス(2進浮動小数) (20) Fx0,Fx1,Fx2 ; 測定時発振周波数(2進整数) Fs0,Fs1,Fs2 ; 常設発振周波数(2進整数) Fc0,Fc1,Fc2 ; 校正発振周波数(2進整数)  (9)→(29) F2s0,F2s1,F2s2,F2s3,F2s4,F2s5 ;常設Ls/Cs発振周波数の二乗 (6)→(35) F2c0,F2c1,F2c2,F2c3,F2c4,F2c5 ;常設Ls/Cs発振周波数の二乗 (6)→(41) ENDC I2LCD_ADR EQU 07Ch ; SPLC-792-I2Cのスレーブアドレス=03Eh+R/W=0 I2LCD_RSDTA EQU 040h I2LCD_RSCMD EQU 000h I2LCD_C01 EQU 080h I2LCD_C00 EQU 000h I2LCD_PwIC EQU 052h ; Icon=off, Booster=off, Cont;C5=1,C4=0 I2LCD_CONTR EQU 013h ; C5=1,C4=0,C3=0,C2=1,C1=1 ;******************************************************************************* ; ==================== プログラム1ページ目開始 ================================== ORG 0 GOTO init ; ==================== 割込み処理 =============================================== ORG 4 ; 割込みベクタ(4番地)を指定する。 ; << 割込み要因振り分け >> IntAll MOVLB 00h ; ■バンク0に切替え (1)+3(TMR2の割込みレイテンシー)=4 BTFSC PIR1,TMR2IF ; TMR2割込み? (1)=5 GOTO TM2_int ; TMR2割込み処理へ (2)=7 BTFSC INTCON,IOCIF ; 割込みはピン変化割込みか? GOTO IOC_int ; ピン変化割込みへ BTFSC INTCON,TMR0IF ; TMR0割込み? GOTO TM0_int ; TMR0割込みへ BTFSC PIR3,TMR4IF ; TMR4割込み? GOTO TM4_int ; TMR4割込みへ BTFSC PIR3,TMR6IF ; TMR6割込み? GOTO TM6_int ; TMR6割込みへ BTFSC PIR1,SSP1IF ; SSP1割込み? GOTO SSP1_int ; SSP1割込み処理へ BTFSC PIR2,BCL1IF ; MSSP(I2C)バス衝突割込み? BCF PIR2,BCL1IF ; MSSP(I2C)バス衝突割込みフラグクリア GOTO iFEXIT ; 割込みから復帰へ ; << TMR0割込み処理 >> TM0_int MOVLB 00h ;■バンク0に切替え BCF INTCON,TMR0IF ; TMR0割込みフラグクリア BCF INTCON,TMR0IE ; TMRO割込み禁止 MOVLB 01h ;■バンク1に切替え BCF OPTION_REG,TMR0CS ; TMR0停止 MOVLB 07h ;■バンク7に切替え BSF IOCBN,IOCBN2 ; RB2の立ち下がり変化割込み許可 BSF IOCBN,IOCBP2 ; RB2の立ち上がり変化割込み許可 BCF IOCBF,IOCBF2 ; RB2のピン変化割込みフラグクリア MOVLB 00h ;■バンク0に切替え BSF INTCON,IOCIE ; ピン変化割込み許可 BSF CALIRQ ; キャリブレーション要求フラグ発行 GOTO iFEXIT ; 割込みから復帰へ ; << TMR2割込み処理 >> TM2_int BCF PIR1,TMR2IF ; (1)=8 DECFSZ TM2_Count,F ; (2)=10 GOTO iFEXIT ; BCF T1CON,TMR1ON ; (1)=13 ここでTMR1のゲート閉 BCF T2CON,TMR2ON ; TMR2停止 BSF TM2_Done,0 ; 1秒経過フラグを立てる GOTO iFEXIT ; << TMR4割込み処理 >> TM4_int MOVLB 08h ;■バンク8に切替え BCF T4CON,TMR4ON ; TMR4停止 MOVLB 00h ;■バンク0に切替え BCF PIR3,TMR4IF ; TMR4割込みフラグをクリア BTFSC Mode,7 ; キャリブレーション要求か確認 GOTO m7chk ; Yesなら Rychk ; キャリブレーションRy動作時間待ち終了後の処理 BTFSC Mode,2 ; Modeは2か? GOTO opm2 ; Yesならopm2へジャンプ BTFSS Mode,0 ; Modeは0か? GOTO iFEXIT ; No??? 取り敢えず割込みを抜ける opm0 BSF Mode,1 ; Modeを1に進める GOTO iFEXIT ; 割込みから復帰 opm2 BSF Mode,3 ; Modeを3に進める GOTO iFEXIT ; 割込みから復帰 m7chk ; SW0チャタリング防止時間終了後の処理 MOVLB 07h ;■バンク7に切替え BCF IOCBF,IOCBF0 ; RB0のピン変化フラグクリア MOVLB 00h ;■バンク0に切替え BTFSC SW0 ; SW0はOFFか? GOTO m7cal ; No, キャリブレーション準備へ MOVLB 07h ;■バンク7に切替え BSF IOCBN,IOCBN0 ; RB0のSw0立ち下がり)変化受付許可 BSF IOCBP,IOCBP0 ; RB0のSW0復帰(立ち上がり)変化受付許可 BSF INTCON,IOCIE ; ピン変化割込み許可 GOTO iFEXIT ; 割込みから復帰 ; キャリブレーション準備 m7cal MOVLB 07h ;■バンク7に切替え BSF IOCBN,IOCBN0 ; RB0のSw0立ち下がり)変化受付許可 BSF IOCBP,IOCBP0 ; RB0のSW0復帰(立ち上がり)変化受付許可 BSF INTCON,IOCIE ; ピン変化割込み許可 MOVLB 00h ;■バンク0に切替え BSF CALIRQ ; ャリブレーション要求フラグ発行 GOTO iFEXIT ; 割込みから復帰 ; << TMR6割込み処理 >> TM6_int ; SW2チャタリング防止時間終了後の処理 MOVLB 08h ;■バンク8に切替え BCF T6CON,TMR6ON ; TMR6停止 MOVLB 00h ;■バンク0に切替え BTFSC SW2 ; SW2はOffか? GOTO S2on ; NoならS2on処理へ MOVLB 07h ;■バンク7に切替え S2off BSF IOCBP,IOCBP3 ; RB3のSW2復帰(立ち上がり)変化受付許可 BCF IOCBN,IOCBN3 ; RB3のSw2押下げ(立ち下がり)変化受付禁止 GOTO S2exit ; 割込みから復帰 S2on ; Smode処理=次の表示モードへ BCF STATUS,C ; STATUS,Cをクリア(RLFで不用ビット防止) BTFSC Smode,7 ; Smode7の場合Smode1へ戻すため BSF STATUS,C ; STATUS,Cを立てて RLF Smode,F ; 次のモードに進める ; 復帰処理 MOVLB 07h ;■バンク7に切替え BSF IOCBN,IOCBN3 ; RB3のSw2押下げ(立ち下がり)変化受付許可 BCF IOCBP,IOCBP3 ; RB3のSW2復帰(立ち上がり)変化受付禁止 S2exit MOVLB 00h ;■バンク0に切替え BCF PIR3,TMR6IF ; TMR6割込みフラグをクリア BSF INTCON,IOCIE ; ピン変化割込み許可 GOTO iFEXIT ; 割込みから復帰 ; << ピン変化割込み処理 >> IOC_int BCF INTCON,IOCIE ; ピン変化割込み禁止 MOVLB 07h ;■バンク7に切替え BTFSC IOCBF,IOCBF3 ; ピン変化はRB3か? GOTO IOC_RB3 ; Yes BTFSC IOCBF,IOCBF2 ; ピン変化はRB2か? GOTO IOC_RB2 ; Yes ; Sw0(キャリブレーション)のピン変化割込み IOC_RB0 BCF IOCBN,IOCBN0 ; RB0の立ち下がり変化割込み禁止 BCF IOCBN,IOCBP0 ; RB0の立ち上がり変化割込み禁止 BCF IOCBF,IOCBF0 ; RB0のピン変化割込みフラグクリア MOVLB 00h ;■バンク0に切替え BSF Mode,7 ; キャリブレーション要求を記録 ; チャタリング防止タイマースタート MOVLB 08h ;■バンク8に切替え CLRF TMR4 ; TMR4を0にリセット BSF T4CON,TMR4ON ; TMR4スタート GOTO iFEXIT ; 割込みから復帰 ; Sw1(L/C切替)のピン変化割込み IOC_RB2 BCF IOCBN,IOCBN2 ; RB2の立ち下がり変化割込み禁止 BCF IOCBN,IOCBP2 ; RB2の立ち上がり変化割込み禁止 BCF IOCBF,IOCBF2 ; RB2のピン変化割込みフラグクリア ; チャタリング防止タイマースタート MOVLB 00h ;■バンク0に切替え MOVLW d'70' ; TMR0に70をセット MOVWF TMR0 ; TMR0=(1/12800)*4*188*256=15.04ms BCF INTCON,TMR0IF ; TMR0割込みフラグクリア BSF INTCON,TMR0IE ; TMRO割込み許可 MOVLB 01h ;■バンク1に切替え BSF OPTION_REG,TMR0CS ; TMR0スタート GOTO iFEXIT ; 割込みから復帰 ; Sw2(LCD二行目表示切替)のピン変化割込み IOC_RB3 MOVLB 07h ;■バンク7に切替え BCF IOCBN,IOCBN3 ; RB3の立ち下がり変化割込み禁止 BCF IOCBN,IOCBP3 ; RB3の立ち上がり変化割込み禁止 BCF IOCBF,IOCBF3 ; RB3のピン変化割込みフラグクリア ; チャタリング防止タイマースタート MOVLB 08h ;■バンク8に切替え CLRF TMR6 ; TMR6を0にリセット BSF T6CON,TMR6ON ; TMR6スタート GOTO iFEXIT ; 割込みから復帰 ; << SSP割込み処理 >> SSP1_int BSF SSP1INT ; SSP1INT有り BCF PIR1,SSP1IF ; SSP1IFクリア ; << 割込み復帰処理 >> iFEXIT MOVLB 00h ;■バンク0に切替え RETFIE ; 割込み許可にしてリターン ; ==================== 初期処理 ================================================ init ; << ポートのアナログ/ディジタル設定 1=input 0=output>> MOVLB 03h ;■バンク3に切替え3 CLRF ANSELA ; A/D-A使用しない MOVLW b'00000000' ; A/D-B使用しない MOVWF ANSELB ; ; << ポートの入出力設定 1=input 0=output>> MOVLB 01h ;■バンク1に切替え MOVLW b'10100000' ; RA7はクロック入力、RA5はMCLR 他は出力に設定 MOVWF TRISA MOVLW b'01011111' ; RBは1,4(I2C通信用)でRB6(カウンター入力 )でRB0,2,3は(SW)入力、他は出力 MOVWF TRISB MOVLB 00h ;■バンク0に切替え ; << 割込みの設定 >> ; 全体割込み設定 BCF INTCON,IOCIE ; ピン変化割込み許可 BSF INTCON,PEIE ; 周辺装置割込み許可 BSF INTCON,GIE ; 全割り込み許可 MOVLB 07h ;■バンク7に切替え ; SW0 BSF IOCBN,IOCBN0 ; RB0のSw0押し下げ(立ち下がり)変化受付許可 BSF IOCBN,IOCBP0 ; RB0のSw0復帰(立ち上がり)変化受付許可 ; SW1 BSF IOCBN,IOCBN2 ; RB2のSw1押し下げ(立ち下がり)変化受付許可 BSF IOCBN,IOCBP2 ; RB0のSw1復帰(立ち上がり)変化受付許可 ; SW2 BSF IOCBN,IOCBN3 ; RB3のSw2押し下げ(立ち下がり)変化受付許可 BSF IOCBN,IOCBN3 ; RB3のSw2復帰(立ち下がり)変化受付許可 MOVLB 00h ;■バンク0に切替え ; << I2C通信の設定 >> ; 速度、モード MOVLB 04h ;■バンク4へ切替え MOVLW b'10000000' ; 低速度モードOffに設定する(100kHz) MOVWF SSP1STAT MOVLW b'00101000' ; SDA1,SCL1はI2Cで使用する。 MOVWF SSP1CON1 ; マスターモードに設定。クロック=FOSC/(4*(SSP1ADD+1)) MOVLW d'31' ; 約100kbps 12.8/(4*(31+1)) MOVWF SSP1ADD ; ピン設定 ; TRISB参照 ; BSF WPUB,1 ; PortB,1をウィークプルアップ ; BSF WPUB,4 ; PortB,4をウィークプルアップ ; 割込みフラグクリア MOVLB 00h ;■バンク0に切替え BCF SSP1INT ; SSP割込みフラグクリア BCF PIR1,SSP1IF ; SSP1IFクリア BCF PIR2,BCL1IF ; MSSP(I2C)バス衝突割り込みをクリア MOVLB 04h ;■バンク4へ切替え BCF SSP1CON1,WCOL ; 衝突フラグクリア ; 割込み MOVLB 01h ;■バンク1へ切替え BSF PIE1,SSP1IE ; SSP(I2C)割り込みを許可する BSF PIE2,BCL1IE ; MSSP(I2C)バス衝突割り込みを許可する ; << タイマーの設定 >> ; TMR0設定(SW1用タイマー) MOVLW d'70' ; 70→(実行時には256-70=186+2=198)を MOVWF TMR0 ; TMR0に設定、従い198カウントでオーバーフローする MOVLB 01h ;■バンク1に切替え MOVLW b'00101111' ; OPTIONレジスタの設定 プリスケーラは256倍 MOVWF OPTION_REG ; RBPU:0, INTDG=0, TMR0CS:1, TOSE=0 ,PSA:1 ,PS2-PS0:111 ; TMROの割り込みは4x188x256/12800000=15.04mS毎になる ; TMR0CS=0に設定すればTMR0スタートとなる BCF INTCON,TMR0IE ; TMRO割込み禁止 BCF INTCON,TMR0IF ; TMR0割込みフラグクリア ; TMR1設定(周波数カウンター) MOVLB 00h ;■バンク0に切替え MOVLW b'10000100' ; CLK=T1CKI, T1CKPS=1:1, T1OSCEN=0, T1SYNC=1, TMR1ON=0 MOVWF T1CON BCF PIR1,TMR1IF ; TMR1割込みフラグをリセット MOVLB 01h ;■バンク1に切替え BCF PIE1,TMR1IE ; TMR1割込み禁止 ; TMR2設定(周波数カウンター用の50mSタイマー) MOVLB 00h ;■バンク0に切替え CLRF TMR2 ; TMR2クリア MOVLW b'01001011' ; POSTS=10, TMR2=Off, PRES=64 MOVWF T2CON ; T2CONに設定 MOVLW d'249' ; PR2=249 TMR2=(1/12800)*4*250*10*64=50ms MOVWF PR2 BCF PIR1,TMR2IF ; TMR2割込みフラグをリセット MOVLB 01h ;■バンク1に切替え BSF PIE1,TMR2IE ; TMR2割込み許可 ; TMR4設定(モード制御/キャリブレーション用15mSタイマー) MOVLB 08h ;■バンク8に切替え MOVLW b'01011010' ; PRES=12, TMR4=Off, POSTS=16 MOVWF T4CON ; T4CONに設定 MOVLW d'249' ; PR4=249 TMR4=(1/12800)*4*250*12*16=15ms MOVWF PR4 MOVLB 00h ;■バンク0に切替え BCF PIR3,TMR4IF ; TMR4割込みフラグをリセット MOVLB 01h ;■バンク1に切替え BSF PIE3,TMR4IE ; TMR4割込み許可 ; TMR6設定(SW2表示切替用15mSタイマー) MOVLB 08h ;■バンク8に切替え MOVLW b'01011010' ; PRES=12, TMR6=Off, POSTS=16 MOVWF T6CON ; T6CONに設定 MOVLW d'249' ; PR6=249 TMR6=(1/12800)*4*250*12*16=15ms MOVWF PR6 MOVLB 00h ;■バンク0に切替え BCF PIR3,TMR6IF ; TMR6割込みフラグをリセット MOVLB 01h ;■バンク1に切替え BSF PIE3,TMR6IE ; TMR6割込み許可 ; << 初期値設定 >> ; L/C計算式の定数(=2.5330255910588400x10^16~=2^54.5) ; 24bitのみデータを割り当てる MOVLB 00h ;■バンク0に切替え MOVLW b'01011001' MOVWF K3 MOVLW b'11111101' MOVWF K2 MOVLW b'11000101' MOVWF K1 MOVLW b'00011001' MOVWF K0 ; 参照用コンデンサーの容量(1000pF=2^9.97) MOVLB 01h ;■バンク1に切替え MOVLW b'11111010' ; 1000の上位88ビット MOVWF Cc3 CLRF Cc2 ; 残りは全て0 CLRF Cc0 ; 残りは全て0 CLRF Cc1 ; 残りは全て0 MOVLB 00h ;■バンク0に切替え MOVLW d'10' ; 整数部10桁 MOVWF nCc ; 周波数カウンターの設定 MOVLB 00h ;■バンク0に切替え BCF GateTime,0 ; TMR1ゲート時間500mSに設定 ;スイッチとリレーの設定 BSF LCsel,0 ; 測定対象はあらかじめC測定 BTFSS SW1 ; SW1はC測定か? BCF LCsel,0 ; NoならL測定に設定変更 BCF CalRy ; キャリブレーション用リレーはオフ ;LEDの設定 BSF LED0 ; LED0は点灯 BSF LED1 ; LED1は消灯 ; 割込みフラグクリア CLRF IRQ ; 割込みフラグクリア BCF CALIRQ ; キャリブレーション要求フラグクリア CLRF Debug ;******************************************************************************* ;************************ ************************************** ;************************ メイン処理 ************************************** ;************************ ************************************** ;******************************************************************************* Pre ; 準備 I2C初期化、LCD初期化、モード初期化 MOVLB 00h ;■バンク0に切替え CLRF Mode ; Modeクリア(=モードR) CALL I2LCD_init ; LCD 初期化 BCF LED1 ; LED1消灯 CALL IniDisp ; 初期メッセージ表示 CLRF Smode Main ; C/L測定をモード別に処理 BTFSC Mode,4 GOTO Md4 ; モード4:Cx/Lx測定 BTFSC Mode,3 GOTO Md3 ; モード3:常設Ls*Csの発振周波数測定 BTFSC Mode,2 GOTO Md2 ; モード2:キャリブレーションリレーOff待ち BTFSC Mode,1 GOTO Md1 ; モード1:校正Ls*(Cs+Cc)の発振周波数Fc測定 BTFSC Mode,0 GOTO Md0 ; モード0:キャリブレーションリレーOn待ち ;******************************************************************* ;*** モードR:(キャリブレーション開始) ; キャリブレーションRyOn→TMR4起動/停止=(RyOn待ち完了)→モード1に進む ; キャリブレーションリレーOn MdR ; モードR動作 BCF LED1 ; LED1を消灯 BSF CalRy ; キャリブレーションリレーOn MOVLB 08h ;■バンク8に切替え CLRF TMR4 ; TMR4を0にリセット BSF T4CON,TMR4ON ; TMR4スタート MOVLB 00h ;■バンク0に切替え CALL CalDisp ; キャリブレーション中を表示 BSF Mode,0 ; Modeを0に進める ;******************************************************************* ;*** モード00キャリブレーションリレーOn待ち Md0 GOTO Main ;******************************************************************* ;*** モード1: 校正Ls*(Cs+Cc)の発振周波数Fc測定 ; →RyをOff&TMR4起動 ; →Fc測定、自乗を求める Md1 CALL wait200ms BSF GateTime,0 ; 測定時間1S S CALL FQcounter0 ; 校正周波数測定BYTE0-2が測定周波数 ; CALL Fc BCF CalRy ; キャリブレーション用リレーOff MOVLB 08h ;■バンク8に切替え CLRF TMR4 ; TMR4を0にリセット BSF T4CON,TMR4ON ; TMR4スタート ; キャリブレーション校正周波数をFCに保存 MOVLB 0x00 ;■バンク0に切替え MOVLW LOW Fc0 ; Fc=2^19.8 MOVWF FSR0L MOVLW HIGH Fc0 MOVWF FSR0H CALL FQcopy CALL SQRX24 ; 整数24ビット掛け算。積は(X)に保存される BSF Mode,2 ; Modeを2に進める ;******************************************************************* ;*** モード2:キャリブレーションリレーOff待ち Md2 GOTO Main ;******************************************************************* ;*** モード3:常設Ls*Csの発振周波数測定 ; 発振周波数 →  ; →Fc自乗と、2.533*10^16/F22を計算する Md3 BSF GateTime,0 ; 測定時間1S CALL FQcounter0 ; BYTE0-2が測定周波数 ; CALL Fs ; 常設周波数をFSに保存 Md301 MOVLW LOW Fs0 ; Fs0のアドレスを MOVWF FSR0L ; FSR0に設定 MOVLW HIGH Fs0 MOVWF FSR0H CALL FQcopy ; 常設周波数をFSに保存 ; LsとCsによる発振周波数(FS)の2乗((F2S)を計算する F2S=2^38.6 CALL SQRY24 ; 整数24ビット掛け算 積はY0 - Y6に入る ; (Y)を(F2S)に保存 MOVLW LOW F2s0 MOVWF FSR0L MOVLW HIGH F2s0 MOVWF FSR0H MOVLW d'6' CALL COPYY ;***** Csを求める ***** ; (Fs^2/Fc^2)=Zを計算する CLRF nX ; 除数の整数部分の桁数をクリア CLRF nY ; 被除数の整数部分の桁数をクリア CALL DIVF32 ; 割り算(56bit整数→bit浮動小数点に変換後割り算)結果は(Z)に入る MOVF nZ,W ; 商の整数部分の桁数を MOVWF nX ; nX(除数の整数部分の桁数)にコピーする ; Z-1を計算し除数(X)に入れる CALL SUB1 ; Zから1を引き結果を(X)に入れる ; Ccの値を被除数(Y)に入れる MOVLW LOW Cc0 MOVWF FSR0L MOVLW HIGH Cc0 MOVWF FSR0H MOVLW d'4' CALL COPY2Y ; Cs=Cc/(Z-1)を計算する MOVF nCc,W ; Ccの整数部分の桁数を MOVWF nY ; 被除数の整数部分の桁数に入れる CALL DIVFX32 ; 割り算(24bit浮動小数点同志の割り算)結果は(Z)に入る MOVF nZ,W ; 商の整数部分の桁数を MOVWF nCs ; Cs(常設コンデンサーの整数部分の桁数)に保存する ; (Z)商を(Cs)常設コンデンサーに入れる MOVLW LOW Cs0 MOVWF FSR0L MOVLW HIGH Cs0 MOVWF FSR0H MOVLW d'4' CALL COPYZ ; Lsを求める ; S=2.533*10^16/F2Sを計算する MOVLW LOW F2s0 ; F2sの値を除数(X)に入れる MOVWF FSR0L MOVLW HIGH F2s0 MOVWF FSR0H MOVLW d'6' CALL COPY2X CALL COPYK ; 乗数K(2.3..x10^16=2^54.5)を被除数Yにコピーする CLRF nX ; 除数の整数部分の桁数をクリア CLRF nY ; 被除数の整数部分の桁数をクリア CALL DIVF32 ; 割り算(32bit浮動小数点) ; 商を(Y)被除数にコピー MOVLW LOW Z0 ; Y0=2~15.9 MOVWF FSR0L MOVLW HIGH Z0 MOVWF FSR0H MOVF nZ,W ; 商の整数部分の桁数を(55-38=17位) MOVWF nY ; nYに保存 MOVLW d'4' CALL COPY2Y ; Csの値を(X)にコピーする MOVLW LOW Cs0 MOVWF FSR0L MOVLW HIGH Cs0 MOVWF FSR0H MOVF nCs,W MOVWF nX MOVLW d'4' CALL COPY2X ; (S)/Cs=Zを計算する CALL DIVFX32 ; 割り算(24bit浮動小数点) MOVF nZ,W ; 商の整数部分の桁数を MOVWF nLs ; nLsに保存する ; 商をLsに保存する MOVLW LOW Ls0 MOVWF FSR0L MOVLW HIGH Ls0 MOVWF FSR0H MOVLW d'4' CALL COPYZ ; LCD表示をクリアし、Mode4に進む CALL I2LCD_clear ; LCDをクリア BSF Mode,4 ; Modeを4に進める ;******************************************************************* ;*** モード4:Cx/Lx測定 Md4 ; キャリブレーション要求フラグが発行されていたらMainへジャンプ BTFSS CALIRQ ; キャリブレーション要求フラグ発行されているか GOTO Md400 ; No, 測定続行 BCF CALIRQ ; Yes, CALIRQクリア CLRF Mode ; Modeをクリア GOTO Main ; Mainへジャンプ ; 周波数を測定 Md400 BSF LED1 ; LED1(測定中)を点灯 BSF GateTime,0 ; 測定時間1S CALL FQcounter0 ; BYTE0-2が測定周波数 ; CALL Fx ; 測定周波数をFxに保存 MOVLW LOW Fx0 MOVWF FSR0L MOVLW HIGH Fx0 MOVWF FSR0H CALL FQcopy ; 測定周波数をFxに保存 ; Fxが低い場合の処理 Md400a CALL FxCHK ; 測定周波数1024Hz BTFSC WREG,0 ; 以上か GOTO RDisp1 ; NoならRDisp1へジャンプ ; FxとFsの大小を比較する Md401 MOVLW LOW Fs0 ; Fsを(X)にコピー MOVWF FSR0L MOVLW HIGH Fs0 MOVWF FSR0H MOVLW d'3' CALL COPY2X CALL SUB24 ; FsとFxを比較する BTFSC iSign,0 ; Fs >= Fx か GOTO Md402 ; NoならMd402へ ; Fs >= FxなのでLsとCs+Cxによる発振周波数(Fx)の2乗の積を(X)に入れF2sを(Y)に設定 CALL SQRX24 ; Yes MOVLW LOW F2s0 ; F2sを MOVWF FSR0L MOVLW HIGH F2s0 MOVWF FSR0H MOVLW d'6' CALL COPY2Y ; (Y)に設定 GOTO Md403 ; Fs=Fxなら(Fs^2/Fx^2)=Z を Fs= BYTEなら iSign=0 ; ; X < BYTEなら iSign=1 SUB24 MOVF BYTE0,W SUBWF X0,W ; X0-BYTE0 MOVF BYTE1,W SUBWFB X1,W ; X1-BYTE1 MOVF BYTE2,W SUBWFB X2,W ; X2-BYTE2 BCF iSign,0 ; iSign,0=0(X<=BYTE) BTFSC STATUS,C ; 引き算の結果は負(X7 MOVWF work1 ;>7 then W+3 else W MOVF work1,W MOVLW 30h ;W+30 ADDWF work1,W MOVWF TEMP BTFSC TEMP,7 ;Test W+30>7* MOVWF work1 ;>70 then W+30 else W MOVF work1,W RETURN ;********3バイトの2進少数をBCDに変換 **************** ; This routine refers some Math-application notes. ; 有効桁数は小数点4桁目で、0.0001±0.000015 (1に対して0.0015%) MCONV1 MOVLW d'24' ;Shift bit counter MOVWF SHIFT ;shift 16 times CLRF DIGITM12 ;clear BCD CLRF DIGITM34 CLRF DIGITM56 CLRF DIGITM78 MLOOP LSRF BYTEM1,F ;shift BYTE to DIGIT RRF BYTEM2,F RRF BYTEM3,F RRF DIGITM12,F RRF DIGITM34,F RRF DIGITM56,F RRF DIGITM78,F MOVF DIGITM12,W ;DIGITM12 adjust TO BCD CALL MADJBCD MOVWF DIGITM12 MOVF DIGITM34,W ;DIGITM34 adjust to BCD CALL MADJBCD MOVWF DIGITM34 MOVF DIGITM56,W ;DIGITM56 adjust to BCD CALL MADJBCD MOVWF DIGITM56 MOVF DIGITM78,W ;DIGITM78 adjust to BCD CALL MADJBCD MOVWF DIGITM78 DECFSZ SHIFT,F ;end check GOTO MLOOP ;adjust to BCD RETURN ;**** Each digit adjust to BCD **** MADJBCD MOVWF work1 ;save MOVLW 003h ; BTFSC work1,3 ;Test Bit3 SUBWF work1,F ;Bit3=1 then W-3h MOVLW 030h ; BTFSC work1,7 ;Test bit7 SUBWF work1,F ;Bit7=1 then W-30h MOVF work1,W RETURN ;***************** 少数を含む4バイトの2進数をBCDに変換 ************************* ; FSR0 ; 指定データの最下位バイトのアドレス ; nZ ; 指定データの整数部分の桁数 ; nDigit ; BCD変換されたデータの整数部分の桁数 ; DIGIT01-9A ; BCD変換されたデータの整数部分1桁から10桁 ; DIGITM12-M78 ; BCD変換されたデータの少数1桁から8桁 ; TempN ; ワーク変数 B2BCD Dcomp MOVF nZ,W ; 整数部分ビット数を MOVWF TempN ; ワークに保存 ; 指定データをBYTEM3からBYTEM1に保存 MOVIW FSR0++ MOVWF BYTEM4 MOVIW FSR0++ MOVWF BYTEM3 MOVIW FSR0++ MOVWF BYTEM2 MOVIW FSR0++ MOVWF BYTEM1 ; 整数部分をクリアする CLRF BYTE0 CLRF BYTE1 CLRF BYTE2 CLRF BYTE3 ; 左シフトして整数部分を合わせる MOVF TempN,W ; 整数部分ビット数は BTFSC STATUS,Z ; 0か? GOTO Cconv ; Yesならシフト無しでBCD変換へ BCloop LSLF BYTEM4,F ; Noなら必要回数左シフトして RLF BYTEM3,F ; 整数部分のビット数を RLF BYTEM2,F ; 合わせる RLF BYTEM1,F RLF BYTE0,F RLF BYTE1,F RLF BYTE2,F RLF BYTE3,F DECFSZ TempN,F ; TempNを一つ減らすと0か?(シフト完了) GOTO BCloop ; No Cconv CALL MCONV1 ; Yes, Binary少数部分をBCD少数に変換 CALL CONV1 ; 整数部分をBCD整数に変換 RETURN ;******************* BCDの整数部分の桁数を調べる ************************* ; nDigit→BCDの整数部分の桁数 整数が*.***X10^nの場合nDigit=n+1 ; 制限 nDigit(BCDの整数部分桁数)は16以下(nDigit<=16) NDGchk MOVLW LOW DIGIT89 ;} MOVWF FSR1L ;} FSR1にDIGIT89の番地を設定 MOVLW HIGH DIGIT89 ;} MOVWF FSR1H ;} MOVLW d'10' ; 整数部分の桁数初期値は16を MOVWF nDigit ; nDigitに入れる Ngloop MOVIW 0[FSR1] ; DIGITEFから(16-nDigit)若い番地DIGITをWREGに設定 ANDLW 0xf0 ; 上位4ビットは BTFSS STATUS,Z ; 0か? RETURN ; NO DECF nDigit,F ; Yseなら桁数を1減らす。 MOVIW FSR1-- ; サイドDIGITを設定し番地を1つ若くする ANDLW 0x0f ; 下位4ビットは BTFSS STATUS,Z ; 0か? RETURN ; No DECFSZ nDigit,F ; Yseなら桁数を1減らす。結果桁数0か? GOTO Ngloop ; Noならループを続ける RETURN ; Yes ;**************** BCDの整数部分の桁数を調べ左詰めにする ************************* ; nDigi ; BCDの整数部分の桁数 整数が*.***X10^nの場合nDigit=n+1 ; 制限 ; nDigit(BCDの整数部分桁数)は16以下(nDigit<=16) ; BCDバイト数 ; 整数部分8バイト、小数部分4バイト合計12バイト ; 有効バイト数 ; 変換前の2進数は4バイトなので、BCDでは5バイト、桁跨りの場合6バイト ; ; 但し、整数部分0バイトの場合は少数4バイトが有効バイト数 DigPack CLRF DIGITXRA ; オーバーフローをクリア MOVLW LOW DIGIT89 ;} MOVWF FSR1L ;} FSR1にDIGIT89の番地を設定 MOVLW HIGH DIGIT89 ;} MOVWF FSR1H ;} MOVLW d'10' ; 整数部分の桁数初期値は10を MOVWF nDigit ; nDigitに入れる G0chk MOVIW 0[FSR1] ; DIGITの ANDLW 0xf0 ; 上位4ビットは BTFSS STATUS,Z ; 0か? GOTO DGpack ; NO DECF nDigit,F ; Yseなら桁数を1減らす。結果桁数0か? MOVIW 0[FSR1] ; DIGITをWREGに取り出し、番地を下の桁に移す ANDLW 0x0f ; 下位4ビットは BTFSC STATUS,Z ; 0か? GOTO nZchk ; YesならnZchkへ CALL Shift4L ; No 4回左シフトして左に詰める GOTO DGpack ; DGpackへジャンプ nZchk DECF FSR1,F ; DECFSZ nDigit,F ; 桁数を1減らす。結果桁数0か? GOTO G0chk ; Noならループを続ける ; BCDの上位3バイトをDGITEEFからの3バイトに移す ; FSR1は初め現在のDIGIT** 終わり現在のDIGIT** - 4番地 ; FSR0は初めDIGITEF    終わりDIGIT89 DGpack MOVLW LOW DIGITEF ;} MOVWF FSR0L ;} FSR1にDIGITEFの番地を設定 MOVLW HIGH DIGITEF ;} MOVWF FSR0H ;} MOVLW d'3' MOVWF TempN Dlp MOVIW FSR1-- MOVWI FSR0-- DECFSZ TempN,F GOTO Dlp ; C測定でnDigitが4の場合は6桁目、その他の場合は5桁目を四捨五入する MOVF Smode,W ; 表示モードを SUBLW 0x04 ; 4(bit3=1)から引けばC*なら結果は正又は0 (StC=1) BTFSS STATUS,C ; C*表示中か? GOTO Round5 ; No(L*)ならRound5へジャンプ MOVF nDigit,W ; nDigitは SUBLW d'4' ; 4 BTFSS STATUS,Z ; か? GOTO Round5 ; NoならRound5へジャンプ Round6 MOVF DIGITAB,W ; Yes 5,6桁目をWREGに入れる ADDLW 0x0b ; 上から6桁目に11を足す BTFSS STATUS,DC ; 3bitからのオーバーフローがあるか RETURN ; Noなら6桁目は4以下なので戻る ADDLW 0x60 ; Yesなら5桁目に6を足して BTFSC STATUS,C ; オーバーフローしないか? GOTO Rupchk ; No(オーバーフローした)ならRupchiへジャンプ ADDLW 0xA0 ; Yesなら10を足して、5桁目を元に戻して MOVWF DIGITAB ; DIGITABを上書きする RETURN Round5 MOVF DIGITAB,W ; 5,6桁目をWREGに入れる ADDLW 0xb0 ; 上から5桁目に11を足す BTFSS STATUS,C ; 7bitからのオーバーフローがあるか RETURN ; Noなら5桁目は4以下なので戻る Rupchk MOVWF DIGITAB ; DIGITABを上書きする ADDFSR 0,2 ; FSR0はDIGITCD番地を指定 MOVLW d'2' MOVWF TempN Ruloop MOVIW FSR0++ MOVWF work0 INCF work0,F ; DIGITCD/EFに1加える MOVLW 0x06 ; 0x06を ADDWF work0,F ; DIGITCD/EFに1加える BTFSC STATUS,DC ; 3bitからのオーバーフローがあるか GOTO R4u ; Yes SUBWF work0,F ; NoならDIGICD/TEFを元に戻す MOVF work0,W MOVWI -1[FSR0] ; DIGITCD/EFに保存 RETURN R4u MOVLW 0x60 ; 0x60を ADDWF work0,F ; DIGITCD/DFに1加える BTFSC STATUS,C ; 7bitからのオーバーフローがあるか GOTO R4l ; Yes SUBWF work0,F ; NoならDIGICD/TEFを元に戻す MOVF work0,W MOVWI -1[FSR0] ; DIGITCD/EFに保存 RETURN R4l MOVF work0,W MOVWI -1[FSR0] ; DIGITCD/EFに保存 DECFSZ TempN,F ; TenmNを1減らすと0か GOTO Ruloop ; No BSF DIGITXRA,0 ; オーバーフローを1にする INCF nDigit,F ; 桁数を1増やす LSRF DIGITXRA,F ;} RRF DIGITEF,F ;}1桁繰り下げる RRF DIGITCD,F ;} RRF DIGITAB,F ;} RETURN ;**************** BCDを左に4回シフトする ************************* ; nDigit ; BCDの整数部分の桁数 整数が*.***X10^nの場合nDigit=n+1 ; 制限 ; nDigit(BCDの整数部分桁数)は16以下(nDigit<=16) ; FSR1 ; シフトするBCDの最上位桁の番地 ; シフト桁数 ; 3バイト Shift4L MOVLW d'3' MOVWF TempN MOVIW FSR1-- ; 現在のFSR1指定の変数をWREGに取り出す(上位4ビットは0) SWAPF WREG,W ; 下位4ビットと上位4ビットを入れ替えて MOVWF work1 ; work1に保存 S4loop MOVF work1,W ; work1をWREGに取り出して ANDLW 0xf0 ; 下位4ビットを0にクリアし MOVWF work0 ; work0に保存 MOVIW FSR1-- ; FSR1で指定した次の変数をWREGに取り出し(FSR1は2番地先になる) SWAPF WREG,W ; 下位4ビットと上位4ビットを入れ替えて MOVWF work1 ; work1に保存 ANDLW 0x0f ; WREGの上位4ビットを0にして IORWF work0,W ; work0とORをとればWREGは前の変数の下位4ビット+現在の変数の上位4ビットになる MOVWI 2[FSR1] ; FSR1が現在示している番地より2番地前の変数に保存 DECFSZ TempN,F ; 繰り返し回数を1減らしたら0か GOTO S4loop ; Noならループを繰り返す ADDFSR 1,0x04 ; YesならFSR1の番地を元に戻す RETURN ;***************** I2C 通信 ************************************************** ;================= I2C 初期化=================== I2C_init ; i2c初期化 MOVLB 04h ;■バンク4へ切替え MOVLW b'00000000' ; 高速度モードに設定する(400kHz) MOVWF SSP1STAT MOVLW b'00101000' ; SDA1,SCL1はI2Cで使用する。 MOVWF SSP1CON1 ; マスターモードに設定。クロック=FOSC/(4*(SSP1ADD+1)) MOVLW d'11' ; 約384kbps 18.432/(4*(11+1)) MOVWF SSP1ADD MOVLB 01h ;■バンク1へ切替え ; MOVLW b'00010010' ; IORWF TRISB,F ; PortB4,1は入力残りは以前の設定通り MOVLB 07h ;■バンク7へ切替え CLRF IOCBF MOVLB 01h ;■バンク1へ切替え BSF PIE1,SSP1IE ; SSP(I2C)割り込みを許可する BSF PIE2,BCL1IE ; MSSP(I2C)バス衝突割り込みを許可する MOVLB 00h ;■バンク0へ切替え RETURN ;================= I2C スタート=================== I2C_start ; i2cにスタートを出力 MOVLB 04h ;■バンク4へ切替え I2C_start1 BCF SSP1CON1,WCOL ; 衝突フラグクリア BTFSC SSP1CON1,WCOL BRA I2C_start1 ; 衝突がなくなるまでループ BSF SSP1CON2,SEN ; スタート発行 BCF SSP1INT ; SSP1INTクリア i2c_start_sen1 BTFSC SSP1CON2,SEN GOTO i2c_start_sen1 MOVLB 00h ;■バンク0へ切替え RETURN ;================= I2C 再スタート=================== I2c_restart ; i2cに再スタートを出力 BCF SSP1INT ; SSP1INTクリア MOVLB 04h ;■バンク4へ切替え BSF SSP1CON2,RSEN ; 再スタート出力 i2c_restart_rsen BTFSS SSP1CON2,RSEN BRA i2c_restart_rsen ; RSENがクリアされるまでループ MOVLB 00h ;■バンク0へ切替え RETURN ;================= I2C 1バイト送信=================== I2C_write ; 1byte出力 MOVWF I2char BCF SSP1INT ; SSP1INTクリア MOVLB 04h ;■バンク4へ切替え MOVF I2char,W MOVWF SSP1BUF ; 書き込みデータをセット i2c_transmit_if BTFSC SSPCON2,BF ; バッファーは空になったか? GOTO i2c_transmit_if ; 空になるまでループ継続 i2c_write_OK BTFSS SSP1INT ; SSP1INT発生したか? GOTO i2c_write_OK ; SSP1INTをクリアするまでループ MOVLB 00h ;■バンク0へ切替え RETURN ;================= I2C にSTOPを出力=================== I2C_stop ; i2cにSTOPを出力 BCF SSP1INT ; SSP1INTクリア MOVLB 04h ;■バンク4へ切替え BSF SSP1CON2,PEN ; ストップ出力 i2c_stop_pen ; BCF SSP1CON2,PEN BTFSC SSP1CON2,PEN BRA i2c_stop_pen ; 出力が完了するまでループ BCF SSP1INT ; SSP1INTクリア MOVLB 00h ;■バンク0へ切替え RETURN ;================= I2LCD初期化 ================================ I2LCD_init MOVLW 038h ; Function Set(8bit 2line) CALL I2LCD_command MOVLW 039h ; Function Set(set extention mode) CALL I2LCD_command MOVLW 014h ; Internal OSC frequency CALL I2LCD_command MOVLW b'01110011' ; Contrast set CALL I2LCD_command MOVLW b'01010110' ; Booster/ICON/Contrast control CALL I2LCD_command MOVLW b'01101100' ; Follower control CALL I2LCD_command CALL wait200ms MOVLW 038h ; Function Set(cancel extention mode) CALL I2LCD_command MOVLW 01h ; Clear Display CALL I2LCD_command CALL wait1ms MOVLW 0Ch ; Display On CALL I2LCD_command RETURN ;================= LCD表示をクリアする =================== I2LCD_clear MOVLW 01h ; Clear Display CALL I2LCD_command CALL wait1ms RETURN ;================= LCDのカーソル位置を先頭に戻す ========= I2LCD_home MOVLW 02h CALL I2LCD_command CALL wait1ms RETURN ;================= LCDのカーソル位置を2行目の先頭に ===== I2LCD_2line MOVLW 0C0h CALL I2LCD_command RETURN ;================= LCDのカーソル位置を右に一つシフトする ===== I2LCD_curSR MOVLW 014h CALL I2LCD_command RETURN ;================= LCDのカーソル位置を左に一つシフトする ===== I2LCD_curSL MOVLW 010h CALL I2LCD_command RETURN ;================= スペースをI2CBuf個付ける ======================= I2LCD_nBlank MOVWF I2CBuf i2rP MOVLW ' ' CALL I2LCD_write DECFSZ I2CBuf,F GOTO i2rP RETURN ;================= LCDのディスプレイをONにする ========= I2LCD_on MOVLW 0Ch CALL I2LCD_command RETURN ;================= LCDのディスプレイとカーソルをONにする == I2LCD_on_cur MOVLW 0Eh CALL I2LCD_command RETURN ;================= LCDのディスプレイをOFFにする ======= I2LCD_off MOVLW 08h CALL I2LCD_command RETURN ;=============== LCD画面を左に1文字分シフトする ================= I2LCD_Lshift MOVLW 018h CALL I2LCD_command RETURN ;=============== LCD画面を右に1文字分シフトする ================= I2LCD_Rshift MOVLW 01Ch CALL I2LCD_command RETURN ;=============== LCDにデータを1バイド送信する =================== I2LCD_write MOVWF I2CSNDdata CALL I2C_start MOVLW I2LCD_ADR CALL I2C_write MOVLW I2LCD_C00+I2LCD_RSDTA CALL I2C_write MOVF I2CSNDdata,w CALL I2C_write CALL I2C_stop CALL wait27us RETURN ;=============== LCDにコマンドを1バイド送信する =================== I2LCD_command MOVWF I2CSNDdata CALL I2C_start MOVLW I2LCD_ADR CALL I2C_write MOVLW I2LCD_C00+I2LCD_RSCMD CALL I2C_write MOVF I2CSNDdata,w CALL I2C_write CALL I2C_stop CALL wait27us RETURN ;================= I2LCDの表示アドレスを設定 ===================== I2LCD_ddram IORLW b'10000000' CALL I2LCD_command RETURN ;================= I2LCDコントラスト変更(0?63) ================================ I2LCD_cont MOVWF I2CBuf ; コントラストデータ(5ビット) ANDLW 003h ; 下位3ビットを MOVWF I2CBufx ; I2CBufxに格納 MOVLW 039h ; Function Set CALL I2LCD_command MOVF I2LCD_CONTR,W ; 元のコントラストデータの ANDLW 0F8h ; 上位5ビットに IORWF I2CBufx,W ; 新しい下位3ビットを足して MOVWF I2LCD_CONTR ; コントラストデータを更新 CALL I2LCD_command ; I2LCDにコントラストデータを送信 MOVF I2CBuf,W ; 入力コントラストデータの SWAPF I2CBuf,W ; 上位 ANDLW 003h ; 2ビットを取り出して MOVWF I2CBufx ; I2CBufxに格納 MOVF I2LCD_PwIC,W ; 元のパワー/アイコン/コントラストデータの ANDLW 0FCH ; 上位6ビットに IORWF I2CBufx,W ; 新しい上位2ビットを足して MOVWF I2LCD_PwIC ; パワー/アイコン/コントラストデータを更新 CALL I2LCD_command ; I2LCDにパワー/アイコン/コントラストデータを送信 RETURN ;================= 変数を液晶に16進表示する=================== I2LCD_Hex MOVWF I2CBuf SWAPF I2CBuf,W CALL I2LCD_Hexs MOVF I2CBuf,W CALL I2LCD_Hexs RETURN ;================= 液晶の16進キャラクターに変換=================== I2LCD_Hexs ANDLW 0x0F ;下位4ビット ADDLW -d'10' BTFSC STATUS,C ADDLW 007h ADDLW 03Ah CALL I2LCD_write RETURN ;*********************** タイマー ************************** ;================= 1S WAIT ================================ wait1s MOVLW d'5' MOVWF CNT1S wait1s_loop CALL wait200ms DECFSZ CNT1S,F GOTO wait1s_loop RETURN ;================= 200mS WAIT ================================ wait200ms MOVLW d'40' MOVWF CNT200mS wait200ms_loop CALL wait5ms DECFSZ CNT200mS,F GOTO wait200ms_loop RETURN ;================= 5mS WAIT ================================= wait5ms MOVLW d'100' MOVWF CNT5mS wait5ms_loop CALL sw50us DECFSZ CNT5mS,F GOTO wait5ms_loop RETURN ;================= 1mS WAIT ================================= wait1ms ;0.05*20+(2+2+1)*.0003125)=1.001563ms MOVLW d'20' MOVWF CNT1mS wait1ms_loop CALL sw50us DECFSZ CNT1mS,F GOTO wait1ms_loop RETURN ;================= 50μS WAIT ===================== wait50us ; 1サイクル(4クロック):0.3125μS ; 50μS=0.3125μS×160サイクル ; 2+4+3*50+2+2=160 MOVLW d'51' ;1 BRA $+4 sw50us MOVLW d'50' NOP NOP MOVWF CNT50uS ;1 wait50us_loop DECFSZ CNT50uS,F ;1(2) GOTO wait50us_loop ;2 RETURN ;2 ;================= 27μS WAIT =============================== wait27us ; 1サイクル(4クロック)::0.3125μS ; 27μS=0.3125μS×86.4サイクル → 87サイクル(27.1875uS) ; 2+4+3*26+2+1=87 MOVLW d'27' ;1 MOVWF CNT27uS ;1 wait27us_loop DECFSZ CNT27uS,F ;1(2) GOTO wait27us_loop ;2 NOP RETURN ;2 ;******************************************************************************* END