LIST P=12F629;PICの形式 INCLUDE P12F629.INC;Including MPLab's File ERRORLEVEL -302;302番のエラーが出ても無視する ;初期の設定 CB = _CPD_OFF;データメモリのプロテクトをしない CB &= _CP_OFF;プログラムメモリのプロテクトもしない CB &= _BODEN_ON;もし電源電圧が2ボルトを下回ったらパワーダウンする CB &= _MCLRE_OFF;No.3のピンをリセットピンとしては使用しない CB &= _PWRTE_ON;電源が入ってから動き出すまでに72ミリ秒の待機時間を作り、電圧が安定するのを待つ CB &= _WDT_OFF;定期的にリセットする機能をオフにする CB &= _XT_OSC;クリスタルを接続して動くようにする __CONFIG CB;上記「CB」に入れた設定を適用する __IDLOCS H'0100';プログラムバージョンをセット ;変数宣言 CBLOCK H'20';変数のデータを入れるメモリの位置 ;ここで変数を宣言する CNT1;ウェイトをかけるカウンタとして使用 CNT2;ウェイトをかけるカウンタとして使用 CNTA;ウェイトをかけるカウンタとして使用 CNTB;ウェイトをかけるカウンタとして使用 ;汎用一時的変数 TmpV1 TmpV2 ;シリアルポートに送る値を入れるバッファ SBuffer ;受信データを入れる変数 DATABYTE ;エラーフラグ ERRORFLAG ENDC ;--------------------------------- ORG H'0';プログラムを書き込む位置を設定 GOTO SETTING ;--------------------------------- ;プログラムメモリアドレスH'4'の場所は割り込みがあったときのスタート地点 ORG H'4';プログラムを書き込む位置を設定 ;(何もしない) RETFIE;割り込み終了 ;--------------------------------- SETTING: ;まず全ての出力ピンをLにする BANKSEL GPIO;入出力レジスタに書き込む準備 MOVLW B'00000000';Wレジスタに値を書き込む MOVWF GPIO;Wレジスタから入出力レジスタに値をコピー ;コンパレータを使用しないモードにする BANKSEL CMCON;設定レジスタに書き込む準備 MOVLW B'00000111';Wレジスタに値を書き込む MOVWF CMCON;Wレジスタから設定レジスタに値をコピー ;マイコンから出ているピンを入力として使うか出力として使うかの設定 ;PORT0=2400BPSで値を出力,PORT1=モーター1,PORT2=モーター2,PORT3=赤外線受信 BANKSEL TRISIO;設定レジスタに書き込む準備 MOVLW B'00001000' ;Wレジスタに値を書き込む(PORT 0,1,2= OUT, PORT 3 = IN) MOVWF TRISIO;Wレジスタから設定レジスタに値をコピー BANKSEL GPIO;入出力レジスタに書き込む準備 ;--------------------------------- MAIN: ;初期状態として出力モードに設定したピンをHにする MOVLW B'00000001';Wレジスタに値を書き込む(PORT0=1,PORT1=0,PORT2=0) MOVWF GPIO;Wレジスタの値を入出力レジスタに書き込む ;エラーフラグリセット MOVLW D'0' MOVWF ERRORFLAG ;スタートビット待ち CALL WAIT_STARTBIT CALL BITSET_IRCHECK_A;照合用信号エラーチェック ; ;デバッグ出力 ; BTFSC ERRORFLAG,0;エラー値が入っていなければ次の行はスキップ ; CALL DEBUGOUT_X ; BTFSC ERRORFLAG,0;エラー値が入っていなければ次の行はスキップ ; CALL DEBUGOUT_X BTFSC ERRORFLAG,0;エラー値が入っていなければ次の行はスキップ GOTO MAIN;戻る BTFSC ERRORFLAG,1;エラー値が入っていなければ次の行はスキップ GOTO MAIN;戻る ;データ取得作業 CALL BITSET_IR;1バイト分の値をTmpV1に取得 ;TmpV1の値を取得データ用変数に入れる MOVF TmpV1,W MOVWF DATABYTE CALL BITSET_IRCHECK_B;照合用信号エラーチェック ; ;デバッグ出力 ; BTFSC ERRORFLAG,0;エラー値が入っていなければ次の行はスキップ ; CALL DEBUGOUT_Y ; BTFSC ERRORFLAG,0;エラー値が入っていなければ次の行はスキップ ; CALL DEBUGOUT_Y BTFSC ERRORFLAG,0;エラー値が入っていなければ次の行はスキップ GOTO MAIN;戻る BTFSC ERRORFLAG,1;エラー値が入っていなければ次の行はスキップ GOTO MAIN;戻る ;シリアル出力作業(おまけ機能で付けておいた) SERIALOUTPUTSTATE: ;取得データをシリアルポート出力用変数に移動する MOVF DATABYTE,W IORLW D'48';シリアル出力したときに値が見やすいように、文字列の扱いにする MOVWF SBuffer CALL SERIALOUT;送信作業 ;ここにモーター制御を書く ;受信値は、送信側のGPIOの値がそのまま入っているので、値はビット1〜ビット3が変化する MOVLW B'00000001';Wレジスタに値を書き込む(シリアル出力部分は使用しないときは1にする) BTFSC DATABYTE,1;取得した値の指定ビットが0だったら次の行はスキップ IORLW B'00000010';Wレジスタに値を書上書き BTFSC DATABYTE,2;取得した値の指定ビットが0だったら次の行はスキップ IORLW B'00000100';Wレジスタに値を書上書き BTFSC DATABYTE,3;取得した値の指定ビットが0だったら次の行はスキップ IORLW B'00001000';Wレジスタに値を書上書き MOVWF GPIO;Wレジスタの値を入出力レジスタに書き込む ;100ミリ秒待機 CALL W100MILISECOND GOTO MAIN;ループ ;;デバッグ出力として「X」の文字を出力 ;;--------------------------------- ; ;取得データをシリアルポート出力用変数に移動する ;DEBUGOUT_X: ; MOVLW D'65' ; MOVWF SBuffer ; CALL SERIALOUT;送信作業 ; RETURN; 戻る ;;デバッグ出力として「Y」の文字を出力 ;;--------------------------------- ;DEBUGOUT_Y: ; ;取得データをシリアルポート出力用変数に移動する ; MOVLW D'66' ; MOVWF SBuffer ; CALL SERIALOUT;送信作業 ; RETURN; 戻る ;照合用入力信号(01010101)を受信し、エラーが無いかチェックする ;--------------------------------- BITSET_IRCHECK_A: CALL BITSET_IR;1バイト分の値をTmpV1に取得 MOVLW D'2';エラー値をセット BTFSS TmpV1,0;指定フラグが間違いでなければ次の行をスキップ IORWF ERRORFLAG,F;エラービットをセット BTFSC TmpV1,1;指定フラグが間違い出なければ次の行をスキップ IORWF ERRORFLAG,F;エラービットをセット BTFSS TmpV1,2;指定フラグが間違い出なければ次の行をスキップ IORWF ERRORFLAG,F;エラービットをセット BTFSC TmpV1,3;指定フラグが間違い出なければ次の行をスキップ IORWF ERRORFLAG,F;エラービットをセット BTFSS TmpV1,4;指定フラグが間違い出なければ次の行をスキップ IORWF ERRORFLAG,F;エラービットをセット BTFSC TmpV1,5;指定フラグが間違い出なければ次の行をスキップ IORWF ERRORFLAG,F;エラービットをセット BTFSS TmpV1,6;指定フラグが間違い出なければ次の行をスキップ IORWF ERRORFLAG,F;エラービットをセット BTFSC TmpV1,7;指定フラグが間違い出なければ次の行をスキップ IORWF ERRORFLAG,F;エラービットをセット RETURN;戻る ;照合用入力信号(10101010)を受信し、エラーが無いかチェックする ;--------------------------------- BITSET_IRCHECK_B: CALL BITSET_IR;1バイト分の値をTmpV1に取得 MOVLW D'2';エラー値をセット BTFSC TmpV1,0;指定フラグが間違いでなければ次の行をスキップ IORWF ERRORFLAG,F;エラービットをセット BTFSS TmpV1,1;指定フラグが間違い出なければ次の行をスキップ IORWF ERRORFLAG,F;エラービットをセット BTFSC TmpV1,2;指定フラグが間違い出なければ次の行をスキップ IORWF ERRORFLAG,F;エラービットをセット BTFSS TmpV1,3;指定フラグが間違い出なければ次の行をスキップ IORWF ERRORFLAG,F;エラービットをセット BTFSC TmpV1,4;指定フラグが間違い出なければ次の行をスキップ IORWF ERRORFLAG,F;エラービットをセット BTFSS TmpV1,5;指定フラグが間違い出なければ次の行をスキップ IORWF ERRORFLAG,F;エラービットをセット BTFSC TmpV1,6;指定フラグが間違い出なければ次の行をスキップ IORWF ERRORFLAG,F;エラービットをセット BTFSS TmpV1,7;指定フラグが間違い出なければ次の行をスキップ IORWF ERRORFLAG,F;エラービットをセット RETURN;戻る ;--------------------------------- BITSET_IR:;赤外線から入力された1バイト分のビットをTmpV1にセットする ;TmpWをスタートビット比較に使うので初期値をセット MOVLW B'11111111' MOVWF TmpV1 ;スタートビット待ち(時限付き) CALL WAIT_STARTBIT_LIMITED ;スタートビット MOVLW B'11111110' MOVWF TmpV2 CALL BITSET_IR_ONEBIT MOVLW D'1';ERRORFLAGがエラーのときに入れる値をここでセット BTFSC TmpV1,0;入力値が0ならば、ビットセットせずに次へ進む IORWF ERRORFLAG,F;エラービットをセット ;TmpV1にOR結合でビットをセットしていくのでTmpV1をリセット MOVLW B'11111111' MOVWF TmpV1 ;データビット0 MOVLW B'11111110' MOVWF TmpV2 CALL BITSET_IR_ONEBIT ;データビット1 MOVLW B'11111101' MOVWF TmpV2 CALL BITSET_IR_ONEBIT ;データビット2 MOVLW B'11111011' MOVWF TmpV2 CALL BITSET_IR_ONEBIT ;データビット3 MOVLW B'11110111' MOVWF TmpV2 CALL BITSET_IR_ONEBIT ;データビット4 MOVLW B'11101111' MOVWF TmpV2 CALL BITSET_IR_ONEBIT ;データビット5 MOVLW B'11011111' MOVWF TmpV2 CALL BITSET_IR_ONEBIT ;データビット6 MOVLW B'10111111' MOVWF TmpV2 CALL BITSET_IR_ONEBIT ;データビット7 MOVLW B'01111111' MOVWF TmpV2 CALL BITSET_IR_ONEBIT RETURN;戻る ;--------------------------------- BITSET_IR_ONEBIT;受信中の各ビットについて、1と0のどちらをTmpV1にセットするかを決める(ビットセットの位置はTmpV2で指定する) CALL WAIT_QUORTBIT;待機 MOVF TmpV2,W;Wレジスタに、TmpV2の値をセット BTFSS GPIO,3;入力値が1ならば、ビットセットせずに次へ進む ANDWF TmpV1,F CALL WAIT_S8BIT;待機 MOVF TmpV2,W;Wレジスタに、TmpV2の値をセット BTFSS GPIO,3;入力値が1ならば、ビットセットせずに次へ進む ANDWF TmpV1,F CALL WAIT_S8BIT;待機 MOVF TmpV2,W;Wレジスタに、TmpV2の値をセット BTFSS GPIO,3;入力値が1ならば、ビットセットせずに次へ進む ANDWF TmpV1,F CALL WAIT_S8BIT;待機 MOVF TmpV2,W;Wレジスタに、TmpV2の値をセット BTFSS GPIO,3;入力値が1ならば、ビットセットせずに次へ進む ANDWF TmpV1,F CALL WAIT_S8BIT;待機 MOVF TmpV2,W;Wレジスタに、TmpV2の値をセット BTFSS GPIO,3;入力値が1ならば、ビットセットせずに次へ進む ANDWF TmpV1,F CALL WAIT_QUORTBIT;待機 RETURN;戻る ;スタートビット待ち ;--------------------------------- WAIT_STARTBIT: BTFSC GPIO,3;入力が0になったら次の行をスキップ GOTO WAIT_STARTBIT;ループ RETURN;戻る ;スタートビット待ち(時限付きで、指定時間スタートビットが来なかった場合は勝手に処理を終了することで無限ループを防ぐ) ;--------------------------------- WAIT_STARTBIT_LIMITED: ;ウェイトの値をセット MOVLW D'255' MOVWF CNTA CALL WAIT_STARTBIT_LIMITED_A;ループ開始 RETURN;戻る WAIT_STARTBIT_LIMITED_A: MOVLW D'255' MOVWF CNTB CALL WAIT_STARTBIT_LIMITED_B;多重ループ BTFSS GPIO,3;スタートビットではない値が入っていたら次の行をスキップ RETURN ;戻る DECFSZ CNTA,F;減算して0になったら次の行をスキップ GOTO WAIT_STARTBIT_LIMITED_A;ループ RETURN;戻る WAIT_STARTBIT_LIMITED_B: BTFSS GPIO,3;スタートビットではない値が入っていたら次の行をスキップ RETURN ;戻る DECFSZ CNTB,F;減算して0になったら次の行をスキップ GOTO WAIT_STARTBIT_LIMITED_B;ループ RETURN;戻る ;--------------------------------- WAIT_S8BIT:;300bpsの1/8ビットの長さを待機 ;繰り返し回数を代入 MOVLW D'15' MOVWF CNT1 CALL WAIT26MICROSECOND;26マイクロ秒周期(約32kHzの1周期)の待機を繰り返す RETURN;サブルーチン終了 ;--------------------------------- WAIT_QUORTBIT:;300bpsの0.25ビットの長さを待機 ;繰り返し回数を代入 MOVLW D'31' MOVWF CNT1 CALL WAIT26MICROSECOND;26マイクロ秒周期(約32kHzの1周期)の待機を繰り返す RETURN;サブルーチン終了 WAIT26MICROSECOND:;26マイクロ秒周期(約32kHzの1周期) GOTO $+1;「何もしないで次の行へ進む」の意味。2サイクル。 GOTO $+1;「何もしないで次の行へ進む」の意味。2サイクル。 GOTO $+1;「何もしないで次の行へ進む」の意味。2サイクル。 GOTO $+1;「何もしないで次の行へ進む」の意味。2サイクル。 GOTO $+1;「何もしないで次の行へ進む」の意味。2サイクル。 GOTO $+1;「何もしないで次の行へ進む」の意味。2サイクル。 GOTO $+1;「何もしないで次の行へ進む」の意味。2サイクル。 GOTO $+1;「何もしないで次の行へ進む」の意味。2サイクル。 GOTO $+1;「何もしないで次の行へ進む」の意味。2サイクル。 GOTO $+1;「何もしないで次の行へ進む」の意味。2サイクル。 GOTO $+1;「何もしないで次の行へ進む」の意味。2サイクル。 GOTO $+1;「何もしないで次の行へ進む」の意味。2サイクル。 DECFSZ CNT1,F;変数CNT1の値を1減らし、もし値が0になったら、次の行の命令を飛ばす(RETURNと書いてある命令へジャンプする) GOTO WAIT26MICROSECOND;ループ RETURN;サブルーチン終了 ;シリアル出力用 ;--------------------------------- SERIALOUT: ;スタートビット CALL BIT0OUT BTFSC SBuffer,0;指定ビットが0ならば、次の行の命令を飛ばす CALL BIT1OUT BTFSS SBuffer,0;指定ビットが1ならば、次の行の命令を飛ばす CALL BIT0OUT BTFSC SBuffer,1;指定ビットが0ならば、次の行の命令を飛ばす CALL BIT1OUT BTFSS SBuffer,1;指定ビットが1ならば、次の行の命令を飛ばす CALL BIT0OUT BTFSC SBuffer,2;指定ビットが0ならば、次の行の命令を飛ばす CALL BIT1OUT BTFSS SBuffer,2;指定ビットが1ならば、次の行の命令を飛ばす CALL BIT0OUT BTFSC SBuffer,3;指定ビットが0ならば、次の行の命令を飛ばす CALL BIT1OUT BTFSS SBuffer,3;指定ビットが1ならば、次の行の命令を飛ばす CALL BIT0OUT BTFSC SBuffer,4;指定ビットが0ならば、次の行の命令を飛ばす CALL BIT1OUT BTFSS SBuffer,4;指定ビットが1ならば、次の行の命令を飛ばす CALL BIT0OUT BTFSC SBuffer,5;指定ビットが0ならば、次の行の命令を飛ばす CALL BIT1OUT BTFSS SBuffer,5;指定ビットが1ならば、次の行の命令を飛ばす CALL BIT0OUT BTFSC SBuffer,6;指定ビットが0ならば、次の行の命令を飛ばす CALL BIT1OUT BTFSS SBuffer,6;指定ビットが1ならば、次の行の命令を飛ばす CALL BIT0OUT BTFSC SBuffer,7;指定ビットが0ならば、次の行の命令を飛ばす CALL BIT1OUT BTFSS SBuffer,7;指定ビットが1ならば、次の行の命令を飛ばす CALL BIT0OUT ;ストップビット CALL BIT1OUT CALL BIT1OUT RETURN;戻る ;--------------------------------- BIT1OUT;シリアルポートへ1の値を出力 ;ピン2に1を出力 MOVLW B'00000001';Wレジスタに値を書き込む IORWF GPIO,F;Wレジスタの値を入出力レジスタに書き込む(ビット0だけ変更する) CALL W2400;ウェイト用のサブルーチンW2400を呼び出す RETURN;戻る ;--------------------------------- BIT0OUT;シリアルポートへ0の値を出力 ;ピン2に0を出力 MOVLW B'00000110';Wレジスタに値を書き込む ANDWF GPIO,F;Wレジスタの値を入出力レジスタに書き込む(ビット0だけ変更する) CALL W2400;ウェイト用のサブルーチンW2400を呼び出す RETURN;戻る ;--------------------------------- W2400:;約2400分の1秒に合わせた待機 MOVLW D'80';Wレジスタに値を代入 MOVWF CNT1;Wレジスタの値を変数CNT1に書き込む CALL W5MICROSECOND;5マイクロ秒の待機作業を、CNT1に入れた回数繰り返す RETURN;戻る ;--------------------------------- W5MICROSECOND:;5マイクロ秒の待機作業を、CNT1に入れた回数繰り返す GOTO $+1;「何もしないで次の行へ進む」の意味。2サイクル。 DECFSZ CNT1,F;変数CNT1の値を1減らし、もし値が0になったら、次の行の命令を飛ばす(RETURNと書いてある命令へジャンプする) GOTO W5MICROSECOND;ループする RETURN;サブルーチン終了 ;--------------------------------- W100MILISECOND:;1ミリ秒待機 MOVLW D'100';Wレジスタに値を代入 MOVWF CNT2;Wレジスタの値を変数CNT1に書き込む W100MILISECOND_START: ;1ミリ秒待機 MOVLW D'200';Wレジスタに値を代入 MOVWF CNT1;Wレジスタの値を変数CNT1に書き込む CALL W5MICROSECOND;5マイクロ秒の待機作業を、CNT1に入れた回数繰り返す DECFSZ CNT2,F;CNT2が0になったら次の行をスキップ GOTO W100MILISECOND_START;ループ RETURN;戻る ;--------------------------------- END