; ; NEC フォーマットで 8 bit の信号が来たときにデコードする回路 ; ; by T. Yabu ; ; 2009.8.31 初版作成 ; #define PIC819 ;#define PIC84A #ifdef PIC819 LIST P=PIC16F819 INCLUDE P16F819.INC __CONFIG _HS_OSC & _WDT_OFF & _PWRTE_ON & _CP_OFF & _BODEN_ON & _MCLR_ON & _LVP_OFF #endif #ifdef PIC84A LIST P=PIC16F84A INCLUDE P16F84A.INC __CONFIG _HS_OSC & _WDT_OFF & _PWRTE_ON & _CP_OFF #endif ; BODEN ブラウンアウト検出 ON 有効 / OFF 無効 ; 電源電圧が下がったときにリセットするか否か ; MCLR_ON Master Clear ピンを使用/使用しない ; LVP Low Voltage Program 有効/無効 ; CP Code Protect ; CPD EEPROM の読み出しプロテクト cblock 0x20 c1,c2,c3 buf count,i endc ;--------- 初期設定 ---------- ifdef PIC819 banksel INTCON clrf INTCON ; 割り込み禁止 banksel ADCON1 movlw B'00000110' ; PORTA は全てデジタル入力 movwf ADCON1 endif banksel TRISA movlw B'00011111' ; PORTA は全て入力 movwf TRISA movlw B'00000000' ; PORTB は全て出力 movwf TRISB banksel PORTB movlw B'00000000' ; 最初は 0 を出力 movwf PORTB ;------ ループ開始点------ ; ; 受光素子の出力は反転することに注意 ; 無信号時は 1 を出力 ; banksel PORTA LOOP_TOP ; ヘッダである 9 ms の 0 を検出する L1 call FIND_ZERO ; 0 の長さをカウントする movlw D'0' movwf count L2 call DELAY_100us incf count,F btfss PORTA,1 ; 1 が来たなら 80 より大きいかチェックする goto L2 movlw D'80' ; 80 より大きいかどうか比較する subwf count,W ; Wreg = count - Wreg ; 結果が正または 0 のとき C が立つ btfss STATUS,C goto L1 call FIND_ZERO ; 8 bit 読み込んで buf に入れる ; 1 の長さが 0 か 1 を表す movlw D'8' movwf i clrf buf L22 ; 1 の時間をカウントする call FIND_ONE movlw D'0' movwf count L3 call DELAY_100us incf count ; count が 20 を超えたら何らかのエラーが発生したと考えられるので、 ; 処理を中断する movlw D'20' subwf count,W ; Wreg = count - Wreg ; 結果が正または 0 のとき C が立つ btfsc STATUS,C goto LOOP_TOP ; 0 が来るまで待つ btfsc PORTA,1 goto L3 ; count の大きさにより 0 か 1 かを判断する movlw D'10' subwf count,W ; Wreg = count - 10 ; 結果が正または 0 のとき C が立つ btfss STATUS,C goto SHORT LONG rlf buf bsf buf,0 goto CONT SHORT rlf buf bcf buf,0 CONT decfsz i,F goto L22 movf buf,W movwf PORTB goto LOOP_TOP ;------ 0 を見つける ------ FIND_ZERO btfsc PORTA,1 goto FIND_ZERO return ;------ 1 を見つける ------ FIND_ONE btfss PORTA,1 goto FIND_ONE return ;--------- ディレイ ----------- ; ; PIC のディレイの考え方 ; ; 4 クロックで 1 サイクル ; 10M のとき 1 サイクルは 0.4 us ; 20M のとき 1 サイクルは 0.2 us ; ; MOV, NOP : 1 サイクル ; DECFSZ : 通常 1 サイクル。次の goto と合わせると 3 サイクル ; LOOP を抜けるときは、次の命令を NOP にするので 2 サイクル ; GOTO, RETURN, CALL : 2 サイクル ; ; ループを 100 回まわる場合、最後の 1 回のみ GOTO では ; なく NOP になるので、-1 サイクルとなる。 ; 上位のルーチンと合わせて 100 us のディレイを作る ; 上位のルーチンが単純なループのとき ; call, decfsz, goto で 5 サイクル ; ; このルーチンは 2 + 164 * 3 - 1 + 2 = 495 サイクル DELAY_100us movlw D'164' movwf c1 LOOP_100us decfsz c1,F goto LOOP_100us return END