list p=16f877a #include p16f877a.inc variable env env = _BODEN_ON env &= _CP_OFF env &= _HS_OSC env &= _PWRTE_ON env &= _WDT_OFF env &= _LVP_OFF env &= _WRT_OFF env &= _CPD_OFF __config env #define LCD_DATA PORTC #define LCD_DDIR TRISC #define LCD_OUT b'10100000' #define LCD_RS PORTD,2 #define LCD_RW PORTD,1 #define LCD_E PORTD,0 #define BUSY_BIT 3 #define ROWS d'16' #define number_of_waves b'11111111' #define half_of_waves b'11000000' #define time0 b'00010100' #define time1 b'00010010' #define time2 b'00001001' #define time3 b'00111111' #define count_signal b'00001000' #define reception_signal PORTD,7 #define send_signal PORTD,6 #define sw_signal PORTD,5 cblock 0x20 CNT1 CNT2 TMP_DATA TMP_DATA_B TMP_CNT CCNT w_temp status_temp wa wa1 counter repeat_counter asmsignal comparison_signal count_asmsignal count_data0 count_data1 slave_address1 test_signal1 count_sw0 count_sw1 count_indicationdata0 count_indicationdata1 select_data signal_asmsignal1 signal_asmsignal2 signal_asmsignal3 solid_asmsignal1 solid_asmsignal2 solid_asmsignal3 data_asmsignal1 data_asmsignal2 data_asmsignal3 endc org 0x000 goto start org 0x004 ;************* ;割り込み処理 ;************* movwf w_temp movf STATUS,w movwf status_temp ;ISR Codes movf status_temp,w movwf STATUS swapf w_temp,f swapf w_temp,w retfie ;************** ;プログラム開始 ;************** start call dly_10m call dly_10m bcf STATUS,RP0 bcf STATUS,RP1 ;バンク0 clrf INTCON ;割り込み禁止 clrf PORTA ;PORTAの初期化 clrf PORTB clrf PORTC clrf PORTD clrf PORTE bsf STATUS,RP0 ;バンク1 movlw 0x07 movwf CMCON ;コンパレータを使用しない movlw LCD_OUT movwf TRISD clrf LCD_DDIR ;PORTCは全部出力 bcf STATUS,RP0 ;バンク0 bcf LCD_RS bcf LCD_RW bcf LCD_E clrf LCD_DATA clrf count_indicationdata0 clrf select_data clrf comparison_signal clrf count_asmsignal clrf count_data0 clrf count_data1 clrf signal_asmsignal1 clrf solid_asmsignal1 clrf data_asmsignal1 clrf signal_asmsignal2 clrf solid_asmsignal2 clrf data_asmsignal2 clrf signal_asmsignal3 clrf solid_asmsignal3 clrf data_asmsignal3 clrf slave_address1 clrf test_signal1 movlw b'00001111' movwf test_signal1 start_loop ;LCD起動確認用 call dly_10m call lcd_init call dly_10m movlw b'00001110' ;カーソルオフ、左から右へ call cmd_send call dly_10m clrf CCNT clrf TMP_CNT goto main start_loop2 ;2回目以降の書き込み用 movlw b'00000001' ;表示クリア call cmd_send movlw b'00000110' ;エントリーモードをセット call cmd_send movlw b'00001110' ;カーソルオフ、左から右へ call cmd_send call dly_10m clrf CCNT clrf TMP_CNT call select_test start_loop3 ;例外表示 movlw b'00000001' ;表示クリア call cmd_send movlw b'00000110' ;エントリーモードをセット call cmd_send movlw b'00001110' ;カーソルオフ、左から右へ call cmd_send call dly_10m clrf CCNT clrf TMP_CNT return main btfsc PORTD,7 goto zyushin goto main select_test incf count_indicationdata0,1 movf count_indicationdata0,0 movwf count_indicationdata1 decf count_indicationdata1,1 btfsc STATUS,Z goto str_out1 decf count_indicationdata1,1 btfsc STATUS,Z goto select_indication1 decf count_indicationdata1,1 btfsc STATUS,Z goto str_out2 decf count_indicationdata1,1 btfsc STATUS,Z goto select_indication2 decf count_indicationdata1,1 btfsc STATUS,Z goto str_out3 decf count_indicationdata1,1 btfsc STATUS,Z goto select_indication3 clrf count_indicationdata0 goto main select_indication1 movf solid_asmsignal3,w movwf select_data goto str_out4 select_indication2 movlw b'00001111' andwf data_asmsignal3,w movwf select_data goto str_out4 select_indication3 swapf data_asmsignal3 movlw b'00001111' andwf data_asmsignal3,w movwf select_data goto str_out4 str_out1 movlw b'10000000' call cmd_send clrf TMP_CNT str_out12 movf TMP_CNT,w call INIT_MSG1 addlw 0x00 btfsc STATUS,Z goto select_test call chr_out1 incf TMP_CNT,f goto str_out12 str_out2 movlw b'11000000' call cmd_send clrf TMP_CNT str_out22 movf TMP_CNT,w call INIT_MSG2 addlw 0x00 btfsc STATUS,Z goto select_test call chr_out1 incf TMP_CNT,f goto str_out22 str_out3 clrf TMP_CNT str_out32 movf TMP_CNT,w call INIT_MSG3 addlw 0x00 btfsc STATUS,Z goto select_test call chr_out1 incf TMP_CNT,f goto str_out32 str_out4 movf select_data,w call getpat call chr_out1 clrf select_data goto select_test str_out5 call start_loop3 movlw b'10000000' call cmd_send str_out52 movf TMP_CNT,w call INIT_MSG5 addlw 0x00 btfsc STATUS,Z goto main call chr_out1 incf TMP_CNT,f goto str_out52 str_out6 call start_loop3 movlw b'10000000' call cmd_send str_out62 movf TMP_CNT,w call INIT_MSG6 addlw 0x00 btfsc STATUS,Z goto main call chr_out1 incf TMP_CNT,f goto str_out62 chr_out1 call data_send incf CCNT,f movlw ROWS subwf CCNT,w btfss STATUS,Z goto chr_done1 clrf CCNT chr_done1 return INIT_MSG1 addwf PCL,1 DT "koki ",0x00 INIT_MSG2 addwf PCL,1 DT "DataA:",0x00 INIT_MSG3 addwf PCL,1 DT " DataB:",0x00 INIT_MSG5 addwf PCL,1 DT "abcdefghijklmn",0x00 INIT_MSG6 addwf PCL,1 DT "error",0x00 getpat addwf PCL,1 startdata retlw "0" retlw "1" retlw "2" retlw "3" retlw "4" retlw "5" retlw "6" retlw "7" retlw "8" retlw "9" enddata ;*************************** ;* LCDの初期化、4bitモード * ;*************************** lcd_init call dly_10m call dly_10m ;20ms待つ movlw b'00110000' ;初期化データ1 call cmd_send4 call dly_10m movlw b'00110000' ;初期化データ2 call cmd_send4 call dly_100u movlw b'00110000' ;初期化データ3 call cmd_send4 call dly_100u movlw b'00100000' ;4bitモード call cmd_send4 call dly_100u call busy_check movlw b'00101000' ;初期モード設定 call cmd_send movlw b'00000001' ;LCDをクリア call cmd_send movlw b'00000110' ;エントリーモードをセット call cmd_send return ;*************************** ;* LCDにコマンドを送出 * ;* wレジスタはコマンド * ;*************************** cmd_send nop nop movwf TMP_DATA swapf TMP_DATA,w andlw 0x0f movwf LCD_DATA bcf LCD_RW bcf LCD_RS bsf LCD_E bcf LCD_E movf TMP_DATA,w andlw 0x0f movwf LCD_DATA bcf LCD_RW bcf LCD_RS bsf LCD_E bcf LCD_E call busy_check return ;*********************************** ;* 初期化用4bit幅コマンド送出 * ;* wレジスタはコマンド(上位4bit) * ;* ビジーチェックできない期間用 * ;*********************************** cmd_send4 nop nop movwf TMP_DATA swapf TMP_DATA,w andlw 0x0f movwf LCD_DATA bcf LCD_RW bcf LCD_RS bsf LCD_E bcf LCD_E return ;********************* ;* LCDにデータを送出 * ;* wレジスタがデータ * ;********************* data_send movwf TMP_DATA swapf TMP_DATA,w andlw 0x0f movwf LCD_DATA bcf LCD_RW bsf LCD_RS bsf LCD_E bcf LCD_E movf TMP_DATA,w andlw 0x0f movwf LCD_DATA bcf LCD_RW bsf LCD_RS bsf LCD_E bcf LCD_E call busy_check return ;********************** ;* LCDビジーチェック * ;********************** busy_check bsf STATUS,RP0 movlw 0xff movwf LCD_DDIR bcf STATUS,RP0 busy_chk1 bcf LCD_RS bsf LCD_RW bsf LCD_E nop movf LCD_DATA,w andlw 0x0f movwf TMP_DATA_B bcf LCD_E nop bsf LCD_E nop bcf LCD_E btfsc TMP_DATA_B,BUSY_BIT ;BUSY_BITが1ならビジー goto busy_chk1 bcf LCD_RW bsf STATUS,RP0 ;bank1 movlw 0x00 movwf LCD_DDIR bcf STATUS,RP0 ;bank0 return dly_100u movlw 0xFA movwf CNT1 dly_100u1 decfsz CNT1,f goto dly_100u1 return dly_10m movlw 0x32 movwf CNT1 dly_10m1 call dly_1m decfsz CNT1,f goto dly_10m1 return dly_1m movlw 0xf8 movwf CNT2 dly_1m1 nop nop nop nop nop nop nop nop decfsz CNT2,f goto dly_1m1 return ;************************************************************* ;************************************************************* ; ここから下は全て ; 信号を受信し、解析する ;************************************************************* ;************************************************************* ;********************************** ;* 受信した信号を8bitに組み立てる * ;********************************** zyushin start_seception_signal call carrier_wave_off1 call wait_delay1 ;信号の真ん中をとれるように時間をずらす signal_assemble1 movlw count_signal movwf count_asmsignal signal_assemble2 btfsc reception_signal ;0ならskip bsf asmsignal,0 btfss reception_signal ;1ならskip bcf asmsignal,0 ;asmsignalに8bitを収納 rrf asmsignal,f call test_test1 decfsz count_asmsignal,1 goto carrier_wave1 rrf asmsignal,f ;C flag分 call reception_start_parity goto signal_selector ;8bitになったら収納へ carrier_wave1 call carrier_wave_off1 ;1クロック待つ goto signal_assemble2 test_test1 swapf test_signal1 btfsc test_signal1,0 ;0なら次をskip bcf PORTD,4 btfss test_signal1,0 ;1なら次をskip bsf PORTD,4 return ;********************************************** ;* start,パリティ,stop信号の確認 * ;********************************************** reception_start_parity call carrier_wave_off1 btfss reception_signal goto wait_error2 call carrier_wave_off1 return reception_stop call carrier_wave_off1 btfsc reception_signal goto wait_error2 call carrier_wave_off1 btfss reception_signal goto wait_error2 return ;********************************************** ;* 8bitに組み立てた信号を何に収納するか決める * ;********************************************** signal_selector incf count_data0,1 movf count_data0,0 movwf count_data1 decf count_data1,1 btfsc STATUS,Z goto signal_identification1 ;コマンド1へ decf count_data1,1 btfsc STATUS,Z goto solid_identification1 ;個体識別1へ decf count_data1,1 btfsc STATUS,Z goto data_identification1 ;データ信号1へ decf count_data1,1 btfsc STATUS,Z goto signal_identification2 ;コマンド2へ decf count_data1,1 btfsc STATUS,Z goto solid_identification2 ;個体識別2へ decf count_data1,1 btfsc STATUS,Z goto data_identification2 ;データ信号2へ clrf count_data0 goto main ;************************************ ;* 8bitに組み立てた信号を収納する * ;************************************ signal_identification1 movf asmsignal,w movwf signal_asmsignal1 clrf asmsignal goto signal_assemble1 solid_identification1 movf asmsignal,w movwf solid_asmsignal1 clrf asmsignal goto signal_assemble1 data_identification1 movf asmsignal,w movwf data_asmsignal1 clrf asmsignal goto wait_main signal_identification2 movf asmsignal,w movwf signal_asmsignal2 clrf asmsignal goto signal_assemble1 solid_identification2 movf asmsignal,w movwf solid_asmsignal2 clrf asmsignal goto signal_assemble1 data_identification2 movf asmsignal,w movwf data_asmsignal2 clrf asmsignal goto compare_twosignal ;********************************** ;* 受信し収納した2つの信号を比較 * ;* * ;********************************** compare_twosignal movf signal_asmsignal1,w xorwf b'00100000',w ;2回目という信号を打ち消し xorwf signal_asmsignal2,w ; btfss STATUS,Z ;演算結果が0ならサブルーチンへ ; goto wait_error movf signal_asmsignal1,w movwf signal_asmsignal3 compare_twosolid movf solid_asmsignal1,w xorwf solid_asmsignal2,w btfss STATUS,Z ;演算結果が0ならサブルーチンへ goto wait_error ; goto identification_signal1 movf solid_asmsignal1,w movwf solid_asmsignal3 compare_twodata movf data_asmsignal1,w xorwf data_asmsignal2,w btfss STATUS,Z ;演算結果が0ならサブルーチンへ goto wait_error movf data_asmsignal1,w movwf data_asmsignal3 goto start_loop2 ;************************************ ;* (仮)エラー 時間をおいてmainへ * ;************************************ wait_error clrf count_data0 call str_out5 goto main wait_error2 clrf count_data0 call str_out6 goto main ;************************************ ;* 時間をおいてmainへ * ;************************************ wait_main call wait_receive goto main ;*********************** ;* 送信するon,off信号 * ;*********************** carrier_wave_on1 ;1クロック分 movlw number_of_waves movwf counter carrier_wave_on2 bsf send_signal call wait_on bcf send_signal call wait_off decfsz counter,f goto carrier_wave_on2 return carrier_wave_off1 ;1クロック分 movlw number_of_waves movwf counter carrier_wave_off2 bcf send_signal call wait_on bcf send_signal call wait_off decfsz counter,f goto carrier_wave_off2 return ;********************* ;* wait集 * ;********************* ;********************* ;* 38kHzのためのwait * ;********************* wait_on movlw time0 movwf wa wait0 decfsz wa,1 goto wait0 return wait_off movlw time1 movwf wa wait1 decfsz wa,1 goto wait1 return ;************************ ;* 時間稼ぎのためのwait * ;************************ wait_delay1 ;半クロック分 movlw half_of_waves movwf counter wait_delay2 nop call wait_on bcf send_signal nop decfsz counter,f goto wait_delay2 return wait_receive ;1回目の信号と2回目信号の間(10bit分ぐらい) bcf send_signal movlw time3 movwf wa wait3 decfsz wa,1 goto wait3 wait4 decfsz wa1,1 goto wait3 return end