;-----------------------------------------------+ ; TV_IR_TX | ; Copy by Y.Matsui | ; | ; TV_IR_TX.asm | ; 38kHzキャリアのIR送信機 | ; PIC16F84-6.4MHz水晶(MC=625nS) | ; 割込=WDT要、TMR0不、RB0不、RB4〜7要 | ; リセット=>イニシャル処理=>GOTO SLP | ; 待ちWDTでSLEEPの次の命令GOTO SLP 繰り返し | ; KEYでRB4〜7の状態変化割り込み発生 | ; 割り込み処理はWDTクリア=> | ; KEYチェック=>送信=>GOTO SLP | ; | ; KEYは電源(トグル)、CH_UP、CH_DNの3つ | ; | ; 21マシンサイクル=13.13uSが38.1kHz半サイクル | ; 1bitは38.1kHzを15サイクル=393.8uS | ; 1frameはスタートbit(1)+データ(4)+反転(4) | ; 合計9bit=3544uS | ; | ; データ電源=H+LLHL+HHLH(02h) | ; データCHUP=H+LHLL+HLHH(04h) | ; データCHDN=H+LHHL+HLLH(06h) | ;-----------------------------------------------| ; (参考)受信側の処理 | ; 1bitの1/3=>131.3uSがtone3.81kHzの半サイクル | ; 受信ではTMR0=131.3uSに設定しtoneに使うととも | ; にスタートbitは常に監視、データは3回に1度 | ; 読みにいく。 | ; | ; Start 2003/5/30 Ver.0.1 | ;-----------------------------------------------+ list p=16F84 ;list directive to define processor #include ;processor specific variable definitions __CONFIG _CP_OFF & _WDT_ON & _PWRTE_ON & _HS_OSC ; read_out_OK、watch_dog_ON、power_up_OK、high_speed_X'tal ; Memory address assignment. ; ROM area assignment ;000H - 3FFH (1k byte) ; 000H ;processor reset vector ; 004H ;interrupt vector location ; RAM area assignment ;00H - 4FH (68 byte) ; 000H - 00BH ;system ; 00CH - 04FH ;useer ; ### ここからレジスタアドレスアサイン ### TX_DAT EQU 00CH ;送信データ CHK_PO EQU 00DH ;KEY_PO回数 CHK_UP EQU 00EH ;KEY_UP回数 CHK_DN EQU 00FH ;KEY_DN回数 CNT003 EQU 010H ;ソフトタイマ(KEYタイミング) A_BIT EQU 011H ;1bit幅(38k15サイクル確認 COUNT8 EQU 012H ;8bit確認レジスタ ; ### ここからラベル定義 ### ; 送信データ S_POW EQU B'00101101' ;電源 CH_UP EQU B'01001011' ;チャンネルアップ CH_DN EQU B'01101001' ;チャンネルダウン BIT_W EQU D'030' ;1bit幅の38kパルス数 ; ### ここからハードピンアサイン ### ; I/O ports assignment. ; PA.4 :no use=VSS接続 ; PA.3 :no use=VSS接続 ; PA.2 :RED_LED アクティブLow ; PA.1 :IR_LED アクティブLow ; PA.0 :PA.1とパラ接続 ; ; PB.7 :SW_電源 アクティブLow (pull_up) ; PB.6 :SW_CH_UP アクティブLow (pull_up) ; PB.5 :SW_CH_DN アクティブLow (pull_up) ; PB.4 :no use=VDD接続 ; PB.3 :no use=VDD接続 ; PB.2 :no use=VDD接続 ; PB.1 :no use=VDD接続 ; PB.0 :no use=VDD接続 ;******************************************* ORG 000H ;processor reset vector RESET ;******************************************* CALL INIT ;イニシャル処理 ;******************************************* SLP ;******************************************* ; KEY割り込み待ちの間WDT-SLEEPの繰り返し。 SLEEP ; NOP ; GOTO SLP ;wait interrupt ;******************************************* ORG 004H ;interrupt vector MAIN ;******************************************* ; RB4〜7状態変化割り込みでMAIN ; WDTをクリアする ; 割り込みの禁止 ; KEYチェック ; 送信 ; GOTO SLP ; ========================================== BCF INTCON,7 ;割り込み禁止 CLRWDT ;cleare WDT CLRF TX_DAT ;送信データクリア CLRF CHK_PO ;KEYデータクリア CLRF CHK_UP ;KEYデータクリア CLRF CHK_DN ;KEYデータクリア ;5回KEYチェックして3回オン(0)ならKEYあり CALL TM003M ;ソフトタイマ3mS CALL CHK_KY ;チェックKEY CLRWDT ;cleare WDT CALL TM003M ;ソフトタイマ3mS CALL CHK_KY ;チェックKEY CLRWDT ;cleare WDT CALL TM003M ;ソフトタイマ3mS CALL CHK_KY ;チェックKEY CLRWDT ;cleare WDT CALL TM003M ;ソフトタイマ3mS CALL CHK_KY ;チェックKEY CLRWDT ;cleare WDT CALL TM003M ;ソフトタイマ3mS CALL CHK_KY ;チェックKEY CLRWDT ;cleare WDT MOVFW TX_DAT ;TX_DATが0なら送信 BZ END_MAIN ;しない。 CALL IR_TX ;送信処理 CLRWDT ;cleare WDT END_MAIN CALL TM003M ;ソフトタイマ3mS ;フラグのクリアは最後にやる。 ;チャタがあるため。 BCF INTCON,0 ;cleare interrupt enable BSF INTCON,7 ;割り込み許可 RETFIE ;return SLP ;END of MAIN ;******************************************* INIT ;******************************************* ; ポート方向設定(RA0〜2=>out/RA3〜4=>in/all RB=>in) ; ポートBはプルアップ指定、プリスケーラ分周(1/128) BSF STATUS,RP0 ;set page 1 MOVLW B'00000000' ;load portB i/o(all RB is output) MOVWF TRISB ;set portB i/o (TRISB) BCF STATUS,RP0 ;set page 0 MOVLW B'11111111' ;W_reg <= B'11111111' MOVWF PORTB ;set portB ; simでRBを1にするために一旦、出力にして代入する。 ; 入力では代入できないため。 BSF STATUS,RP0 ;set page 1 MOVLW B'00011000' ;load portA i/o(RA3&4 is input) MOVWF TRISA ;set portA i/o (TRISA) MOVLW B'11111111' ;load portB i/o(all RB is input) MOVWF TRISB ;set portB i/o (TRISB) MOVLW B'00001111' ;RB_pull_up,int_CLK MOVWF OPTION_REG ;priscal=WDT&1/128 BCF STATUS,RP0 ;set page 0 MOVLW B'00000111' ;W_reg <= B'00000111' MOVWF PORTA ;set portA ; MOVLW B'11111111' ;W_reg <= B'11111111' ; MOVWF PORTB ;set portB MOVLW B'10001000' ;interrupt enable,timer enable MOVWF INTCON ;send data to INTCON CLRF TX_DAT ;送信データ CLRF CHK_PO ;KEY_PO回数 CLRF CHK_UP ;KEY_UP回数 CLRF CHK_DN ;KEY_DN回数 CLRF CNT003 ;ソフトタイマ(KEYタイミング) MOVLW BIT_W ;W <= 38kパルス MOVWF A_BIT ;send data to A_BIT MOVLW D'008' ;W <= 8 MOVWF COUNT8 ;send data to COUNT8 RETURN ; ;END of INIT ;******************************************* CHK_KY ;******************************************* ; PORTB_7,6,5をチェックする。 ; 3回連続で押されていればKEYありでそのデータ ; を送信データTX_DATに代入する。 CK_POW BTFSC PORTB,7 ;PB.7=0(key_on) then skip GOTO CK_UP ;check next key CLRF CHK_UP ;クリアカウント CLRF CHK_DN ;クリアカウント INCF CHK_PO,F ;CHK_PO <= CHK_PO+1 MOVLW B'00000011' ;W <= B'00000011' XORWF CHK_PO,W ;CHK_PO xor '3' BNZ CK_END MOVLW S_POW ;送信データ(S_POW) MOVWF TX_DAT ;save TX_DAT(S_POW) GOTO CK_END ; CK_UP BTFSC PORTB,6 ;PB.6=0(key_on) then skip GOTO CK_DN ;check next key CLRF CHK_PO ;クリアカウント CLRF CHK_DN ;クリアカウント INCF CHK_UP,F ;CHK_UP <= CHK_UP+1 MOVLW B'00000011' ;W <= B'00000011' XORWF CHK_UP,W ;CHK_UP xor '3' BNZ CK_END MOVLW CH_UP ;CH_UP送信データ MOVWF TX_DAT ;save TX_DAT(CH_UP) GOTO CK_END ; CK_DN BTFSC PORTB,5 ;PB.5=0(key_on) then skip GOTO CK_END ; CLRF CHK_PO ;クリアカウント CLRF CHK_UP ;クリアカウント INCF CHK_DN,F ;CHK_DN <= CHK_DN+1 MOVLW B'00000011' ;W <= B'00000011' XORWF CHK_DN,W ;CHK_DN xor '3' BNZ CK_END ;no KEY MOVLW CH_DN ;CH_DN送信データ MOVWF TX_DAT ;save TX_DAT(CH_DN) CK_END RETURN ; ;END of KEY ;******************************************* TM003M ;******************************************* ; 3000uS=4800マシンサイクルのソフトウエイト ; KEYのチャタ除去に使用する。 MOVLW D'252' ;(1) MOVWF CNT003 ;(1) NOP ; NOP ; LP003 NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP DECFSZ CNT003,F ;(3+1) GOTO LP003 ;(2*2) RETURN ;(2) ;END of TM003M ;******************************************* IR_TX ;******************************************* ; 21マシンサイクル13.125uSが38.1kHzの半サイクル ; 1bitは38.1kHzを15サイクル=393.8uS ; MSB送信->38k*15cycle)*9bit) NOP ;15回繰り返す。 MOVLW B'00000111' ;W_reg <= LED_OFF MOVWF PORTA ;set portA(LED_OFF) CALL NP6 ; NOP ; NOP ; NOP ; NOP ; NOP ; NOP ; NOP ; NOP ; NOP ; MOVLW B'00000000' ;W_reg <= LED_ON MOVWF PORTA ;set portA(LED_ON) CALL NP6 ; NOP ; NOP ; NOP ; NOP ; NOP ; DECFSZ A_BIT,F ;38kHz_15cycleならスキップ GOTO IR_TX ;loop MOVLW BIT_W ;W <= 38kパルス MOVWF A_BIT ;send data to A_BIT TX_BIT ;15回繰り返す。 MOVLW B'00000111' ;W_reg <= LED_OFF MOVWF PORTA ;set portA(LED_OFF) CALL NP6 ; NOP ; NOP ; NOP ; NOP ; NOP ; NOP ; NOP ; MOVLW B'00000111' ;W_reg <= LED_OFF BTFSC TX_DAT,7 ;TX_DAT.7=0 then skip MOVLW B'00000000' ;W_reg <= LED_ON MOVWF PORTA ;set portA(LED_OFF) CALL NP6 ; NOP ; DECFSZ A_BIT,F ;38kHz_15cycle? GOTO ADJ_TM ;タイミング調整 NEXT_BIT MOVLW BIT_W ;W <= 38kパルス MOVWF A_BIT ;send data to A_BIT RLF TX_DAT,F ;C←7←...←0←C DECFSZ COUNT8,F ;8bitならスキップ GOTO TX_BIT ;loop MOVLW D'008' ;W <= 8 MOVWF COUNT8 ;send data to COUNT8 MOVLW B'00000111' ;W_reg <= LED_OFF MOVWF PORTA ;set portA(LED_OFF) RETURN ; ;END of IR_TX ;******************************************* ADJ_TM NOP ; NOP ; NOP ; GOTO TX_BIT ;loop ;******************************************* NP6 NOP NOP NOP NOP NOP NOP RETURN ;(2) ;******************************************* END ;end of all ;*******************************************