RS232cで信頼性の有る通信@
PIC16F84を使った通信

RS232cなどで通信中にノイズなどが入った場合、まったく違った値を
受け取ってしまいます
そこで、プロトコルみたいな物を作って信頼性の有る通信をしてみたいと
思います



■プロトコルを考えるにあたって、

マイコンの容量が小さいため、なるべくメモリを使わない方がいい
高ノイズ状態でも、信頼性のある通信が行えるようにしたい
ノードIDを付ける事により、複数台のマイコンと通信できるようにしたい

■以上を踏まえてパケットのビットアサインを考える



0ビット目から2ビット目までをデータとしました、
ここは自由にデータを入れられる領域とします

3ビット目から6ビット目までをノードIDとしました
ここにパケットを渡したいノードのノードIDを入れる事により
目的のノードと一対一で通信ができます

7ビット目を0固定としました
パケットのビットを反転した場合この部分が1になります
通信時に通常のパケットを送信後、続いて反転したパケットを送信することにより
受信側が通信の信頼性を確認できます




■ダイアグラムを考える



一回の通信に対して
送信側から受信側に対してパケットとそのパケットの反転情報を送信します
その後、受信側でパケットが正しいと判断できた場合は、そのままパケットを
送信側に対して送り返します。

送信側が送信したパケットと同一のパケットが返ってきたことを確認できた時点で
送信が完了したとします。




ノイズなどによりパケット、もしくは反転情報が破壊された場合においては
受信側は全くアクションを起こさず無視するものとします。




■テスト用Windowsプログラムを作る
プロトコルの内容は決まりましたのでテスト用のWindowsプログラムを
作りたいと思います

まあ、タダ単にRS232cで文字列を送信して、その後、文字列を受信して
16進で表示するだけの単純なプログラムです。

#include <stdio.h>
#include "RS232c.h" //このヘッダーを取り込みます。

int main(int argc, char* argv[])
{
	RS232c rs;
	rs.Connect("COM1",
		300,
		8,
		NOPARITY,
		ONESTOPBIT,
		RTS_CONTROL_DISABLE,
		DTR_CONTROL_DISABLE,
		1000,
		1000   
		);  //接続します

	unsigned char data[5]="";
	data[0]=0x5A;
	data[1]=0xA5;
	
	rs.Send((char*)data); //文字列を送信 Send(送信文字列)

	char w[100];
	rs.Read(w,100);  //文字列の受信 Read(char配列,読み込む文字数)
	//もしくは、
	//rs.Read_CRLF(w,99); //最後にCRLFが付くまで受信 Read_CRLF(char配列,配列サイズ)
	for(int i=0;i<5;i++)
	printf("0x%x\n",(unsigned char)w[i]);
	//クローズする必要はありません、オブジェクトが破棄された時、クローズされます
	getchar();
	return 0;
}

ソースのみダウンロード VisualC++ 6.0


上記プログラムの送信する文字列を生成する所に値を入れて
任意のパケットを作り出します

	data[0]=0x5A;←ココ
	data[1]=0xA5;←ココ

▼テスト用のWindowsプログラムの動作確認

前回作成したRS232c送受信のPICのソフトをPIC16F84に書き込んで
RS232cケーブルで接続してWindowsプログラムを走らせて見ます


c:\>■■■.exe
0x5a
0x5a
0xa5
0xa5
0xa5

Windowsプログラムは正しく動作していることが確認できました




■前回作成したRS232c送受信のPICソフトを修正する

第一段階の変更として、パケットと反転情報を確認して、正しいパケットなら
返信するように修正したいと思います

変更のイメージとして、
RS232cの受信部分で、7ビット目を受信した後に、受信した値の7ビット目を見て
パケットか、それとも反転したパケットかを判断させ、
パケットの場合にはバッファに格納します
反転したパケットの場合には、そのパケット反転させて、バッファと比較をします
バッファと同一のもので有る場合には、受信データとして扱います


;自作プロトコル受信のためのメモリ
TRUST_BUF		equ	0x16
TRUST_DATA	equ	0x17


▲最初にバッファと確認後の値を格納しておくメモリを確保します


;----------------------------------------------------------------------
;自作プロトコル受信のための操作
;----------------------------------------------------------------------
READ_TRUST_INIT
		MOVFW	READ_COUNTER	;WレジスタにFレジスタを代入
		SUBLW	0x01		;Wレジスタから値を引く
		BNZ	READ_TRUST_END	;結果が0以外ならジャンプ
READ_TRUST_START
		;受信バッファの7ビット目が0ならばデータ、1ならばミラー
		BTFSC	READ_BUF,7	;指定ビットがゼロならスキップ
		goto	READ_TRUST_MIRROR	;ジャンプ
READ_TRUST_DATA
		;データのため、バッファに退避させる
		MOVFW	READ_BUF		;WレジスタにFレジスタを代入
		MOVWF	TRUST_BUF		;FレジスタにWレジスタを代入
		goto	READ_TRUST_END	;ジャンプ;
READ_TRUST_MIRROR
		;ミラーデータの受信
		COMF	READ_BUF,0	;Fレジスタを反転しWレジスタへ転送
		SUBWF	TRUST_BUF,0	;Wレジスタから値を引く
		BNZ	READ_TRUST_END	;結果が0以外ならジャンプ
		;受信データが正しいことを確認
		MOVFW	TRUST_BUF		;WレジスタにFレジスタを代入
		MOVWF	TRUST_DATA	;FレジスタにWレジスタを代入
		;受信データを返信する
		MOVFW	TRUST_BUF		;WレジスタにFレジスタを代入
		MOVWF	SEND_BUF		;FレジスタにWレジスタを代入
READ_TRUST_END


▲受信部分を上記のように変更しました。

あと、画面には無いですけど、メインループの中でポートBにTRUST_DATAの内容が
出力されるように変更しました




■動作確認
PICにプログラムを書き込みRS232cでパソコンと接続してテスト用Windowsプログラムを
実行します

テスト用プログラムの送信データを以下のように変更しました

	data[0]=0x7F;
	data[1]=0x80;←0x7Fの反転データ

実際に動作させて見ると


c:\>■■■.exe
0x7f
0x0
0x0
0x0
0x0


正しくパケットと反転情報が確認されてパケットが返信されています


ポートBを確認すると0x7FにLEDが点灯していることが確認できます
(左側がLSB)


次に破壊されたパケットを送信してみます
テスト用プログラムの送信データを以下のように変更しました

	data[0]=0x7F;
	data[1]=0x81;←破壊された反転データ

実際に動作させて見ると


c:\>■■■.exe
0x0
0x0
0x0
0x0
0x0


応答文も返ってきませんですし、LEDも変化がありませんでした

これで正しく動作していることが確認できました




■ノードID対応
第二段階の修正としてノードIDに対応させたいと思います



;ノードID
NODE_ID		equ	0x18

▲最初にノードIDのためのメモリを確保します


		;ノードIDの設定 ID * 0x08は左に3ビットシフトさせるため
		MOVLW	0x01*0x08		;Wレジスタに値を代入 
		MOVWF	NODE_ID		;WレジスタからFレジスタに代入


▲PICの初期化部分でノードIDを設定します 今回はIDは0x01とします


;----------------------------------------------------------------------
;自作プロトコル受信のための操作
;----------------------------------------------------------------------
READ_TRUST_INIT
		MOVFW	READ_COUNTER	;WレジスタにFレジスタを代入
		SUBLW	0x01		;Wレジスタから値を引く
		BNZ	READ_TRUST_END	;結果が0以外ならジャンプ
READ_TRUST_START
		;受信バッファの7ビット目が0ならばデータ、1ならばミラー
		BTFSC	READ_BUF,7	;指定ビットがゼロならスキップ
		goto	READ_TRUST_MIRROR	;ジャンプ
READ_TRUST_DATA
		;データのため、バッファに退避させる
		MOVFW	READ_BUF		;WレジスタにFレジスタを代入
		MOVWF	TRUST_BUF		;FレジスタにWレジスタを代入
		goto	READ_TRUST_END	;ジャンプ;
READ_TRUST_MIRROR
		;ミラーデータの受信
		COMF	READ_BUF,0	;Fレジスタを反転しWレジスタへ転送
		SUBWF	TRUST_BUF,0	;Wレジスタから値を引く
		BNZ	READ_TRUST_END	;結果が0以外ならジャンプ
		;受信データが正しいことを確認できたためノードIDを確認する
CHECK_NODE_ID
		COMF	READ_BUF,1	;Fレジスタを反転しFレジスタへ転送
		;READ_BUFにはこの時点でTRUST_BUFと同じ値が入っている
		MOVFW	NODE_ID		;WレジスタにFレジスタを代入
		XORWF	READ_BUF,1	;XORをとり結果をFレジスタに代入
		BTFSC	READ_BUF,3	;3bit目が0ならばスキップ
		goto	READ_TRUST_END	;IDが違ったため受信データを無視する
		BTFSC	READ_BUF,4	;4bit目が0ならばスキップ
		goto	READ_TRUST_END	;IDが違ったため受信データを無視する
		BTFSC	READ_BUF,5	;5bit目が0ならばスキップ
		goto	READ_TRUST_END	;IDが違ったため受信データを無視する
		BTFSC	READ_BUF,6	;6bit目が0ならばスキップ
		goto	READ_TRUST_END	;IDが違ったため受信データを無視する
CHECK_NODE_ID_END
		;IDおよび受信データが正しいことを確認
		MOVFW	TRUST_BUF		;WレジスタにFレジスタを代入
		MOVWF	TRUST_DATA	;FレジスタにWレジスタを代入
		;受信データを返信する
		MOVFW	TRUST_BUF		;WレジスタにFレジスタを代入
		MOVWF	SEND_BUF		;FレジスタにWレジスタを代入
READ_TRUST_END


▲上で変更した部分に赤字の部分を追加しました
IDを識別するのには受信パケットに対してシフト済みノードIDのXORを取る事により
実現しています




■動作確認
PICにプログラムを書き込みRS232cでパソコンと接続してテスト用Windowsプログラムを
実行します

テスト用プログラムの送信データを以下のように変更しました
0x0Fは2進数で00001111であり、ノード0x01に対して0x07の値を送信することを意味します

	data[0]=0x0F;
	data[1]=~data[0];←反転データを返す

実際に動作させて見ると


c:\>■■■.exe
0xf
0x0
0x0
0x0
0x0



ポートBを確認すると0x0FにLEDが点灯していることが確認できます
(左側がLSB)

正しいノードIDが認識され、処理が行われた事が確認できました。


次に違うノードIDのパケットを送信してみます
テスト用プログラムの送信データを以下のように変更しました
0x1Fは2進数で00011111であり、ノード0x03に対して0x07の値を送信することを意味します

	data[0]=0x1F;
	data[1]=~data[0];

実際に動作させて見ると


c:\>■■■.exe
0x0
0x0
0x0
0x0
0x0


ノードIDが違うため、応答文も返ってきませんですし、LEDも変化がありませんでした
これでPICマイコンの受信部分が正しく動作していることが確認できました




■ここまでで作った全ソースコード



;---------------------------------------------------------------
	LIST      P=16F84
	#include <p16F84.inc>

	__CONFIG _CP_OFF & _HS_OSC & _PWRTE_ON & _WDT_OFF

;---------------------------------------------------------------
;アドレスに名前を付ける
;---------------------------------------------------------------
;割り込み時にレジスタを退避させるメモリ
w_temp		equ	0x0C
status_temp	equ	0x0D

;ウェイト用メモリ
wait_val1		equ	0x0E
wait_val2		equ	0x0F

;RS232c 受信用メモリ
READ_TMR		equ	0x10
READ_COUNTER	equ	0x11
READ_BUF		equ	0x12

;RS232c 送信用メモリ
SEND_TMR		equ	0x13
SEND_COUNTER	equ	0x14
SEND_BUF		equ	0x15

;自作プロトコル受信のためのメモリ
TRUST_BUF		equ	0x16
TRUST_DATA	equ	0x17

;ノードID
NODE_ID		equ	0x18

;PIC16F84では0x0Cから0x4Fまでが使用可能
;***************************************************************
;リセットベクタ
;***************************************************************
		org	0
		goto	start
;***************************************************************
;割り込みベクタ
;***************************************************************
		org	4

		;レジスタの退避
		movwf	w_temp
		movf	STATUS,w
		clrf	STATUS
		movwf	status_temp
		
		;各割り込みに対して適切なアドレスにジャンプさせる
		btfsc	INTCON,0
		goto	int0
		btfsc	INTCON,1
		goto	int1
		btfsc	INTCON,2
		goto	int2
intret
		;レジスタの復帰
		clrf	STATUS
		movf	status_temp,w
		movwf	STATUS
		swapf	w_temp,f
		swapf	w_temp,w
		retfie			;割り込みから復帰

;---------------------------------------------------------------
;RB0/INT割り込みにより実行
;---------------------------------------------------------------
int0					;RB4~RB7割り込み

		;割り込み時の処理をここに記述

		bcf	INTCON,0		;RB4~RB7割り込みフラグリセット
		goto	intret
;---------------------------------------------------------------
;RB4〜RB7割り込みにより実行
;---------------------------------------------------------------
int1					;RB0/INT割り込み

		;割り込み時の処理をここに記述

		bcf	INTCON,1		;RB0/INT割り込みフラグリセット
		goto	intret
;---------------------------------------------------------------
;タイマー割り込みにより実行
;---------------------------------------------------------------
int2		;タイマー割り込み
		;タイマーにはクロックが1/4周期で供給されるため、
		;10MHzクロックでは 1/2500000secとなる
		;1/19200 sec(52 usec)毎にタイマー割り込みを入れるために
		;減算タイマー値に256-130=0x7Eを設定
		;しかし、割り込みから、ここまでに0x0Eほどかかるため加算する
		movlw	0x7E+0x0E		;タイマー値リセット
		movwf	TMR0
		bcf	INTCON,2		;タイマー割り込みフラグリセット

		;割り込み時の処理をここに記述
;****************************************************************************
;RS232c送信処理
;****************************************************************************
SEND_START
		TSTF	SEND_BUF		;SEND_BUFがゼロかテストする
		BZ	SEND_END		;ゼロのときジャンプ

		;1/19200を32分周して1/600を作り出す
		decfsz	SEND_TMR,F	;Fレジスタを‐1して0ならスキップ
		goto	SEND_END		;ジャンプ
		MOVLW	0x1F		;Wレジスタに値を代入
		MOVWF	SEND_TMR		;WレジスタからFレジスタに代入
		;送信カウンタのセット
		TSTF	SEND_COUNTER	;SEND_COUNTERがゼロかテストする
		BNZ	SEND_COUNTER_SET_END	;ゼロ以外のときジャンプ
SEND_COUNTER_SET
		MOVLW	0x13+0x01		;Wレジスタに値を代入 
		MOVWF	SEND_COUNTER	;WレジスタからFレジスタに代入
SEND_COUNTER_SET_END
		DECF	SEND_COUNTER	;Fレジスタを-1する
;-----------------------------------------------------------------------
;スタートビットを立てる
;-----------------------------------------------------------------------
SEND_START_BIT
		MOVFW	SEND_COUNTER	;WレジスタにFレジスタを代
		SUBLW	0x13		;Wレジスタから値を引く
		BNZ	SEND_0_BIT	;結果が0以外ならジャンプ
		BCF	PORTA,1		;指定ビットに0を立てる
;-----------------------------------------------------------------------
;0ビット目の送信
;-----------------------------------------------------------------------
SEND_0_BIT
		MOVFW	SEND_COUNTER	;WレジスタにFレジスタを代
		SUBLW	0x11		;Wレジスタから値を引く
		BNZ	SEND_0_BIT_END	;結果が0以外ならジャンプ
		BTFSS	SEND_BUF,0	;指定ビットがゼロ以外ならスキップ
		goto	SEND_0_OFF	;ジャンプ
SEND_0_ON
		BSF	PORTA,1		;指定ビットに1を立てる
		goto	SEND_0_BIT_END
SEND_0_OFF
		BCF	PORTA,1		;指定ビットに0を立てる
SEND_0_BIT_END
;-----------------------------------------------------------------------
;1ビット目の送信
;-----------------------------------------------------------------------
SEND_1_BIT
		MOVFW	SEND_COUNTER	;WレジスタにFレジスタを代
		SUBLW	0x0F		;Wレジスタから値を引く
		BNZ	SEND_1_BIT_END	;結果が0以外ならジャンプ
		BTFSS	SEND_BUF,1	;指定ビットがゼロ以外ならスキップ
		goto	SEND_1_OFF	;ジャンプ
SEND_1_ON
		BSF	PORTA,1		;指定ビットに1を立てる
		goto	SEND_1_BIT_END
SEND_1_OFF
		BCF	PORTA,1		;指定ビットに0を立てる
SEND_1_BIT_END
;-----------------------------------------------------------------------
;2ビット目の送信
;-----------------------------------------------------------------------
SEND_2_BIT
		MOVFW	SEND_COUNTER	;WレジスタにFレジスタを代
		SUBLW	0x0D		;Wレジスタから値を引く
		BNZ	SEND_2_BIT_END	;結果が0以外ならジャンプ
		BTFSS	SEND_BUF,2	;指定ビットがゼロ以外ならスキップ
		goto	SEND_2_OFF	;ジャンプ
SEND_2_ON
		BSF	PORTA,1		;指定ビットに1を立てる
		goto	SEND_2_BIT_END
SEND_2_OFF
		BCF	PORTA,1		;指定ビットに0を立てる
SEND_2_BIT_END
;-----------------------------------------------------------------------
;3ビット目の送信
;-----------------------------------------------------------------------
SEND_3_BIT
		MOVFW	SEND_COUNTER	;WレジスタにFレジスタを代
		SUBLW	0x0B		;Wレジスタから値を引く
		BNZ	SEND_3_BIT_END	;結果が0以外ならジャンプ
		BTFSS	SEND_BUF,3	;指定ビットがゼロ以外ならスキップ
		goto	SEND_3_OFF	;ジャンプ
SEND_3_ON
		BSF	PORTA,1		;指定ビットに1を立てる
		goto	SEND_3_BIT_END
SEND_3_OFF
		BCF	PORTA,1		;指定ビットに0を立てる
SEND_3_BIT_END
;-----------------------------------------------------------------------
;4ビット目の送信
;-----------------------------------------------------------------------
SEND_4_BIT
		MOVFW	SEND_COUNTER	;WレジスタにFレジスタを代
		SUBLW	0x09		;Wレジスタから値を引く
		BNZ	SEND_4_BIT_END	;結果が0以外ならジャンプ
		BTFSS	SEND_BUF,4	;指定ビットがゼロ以外ならスキップ
		goto	SEND_4_OFF	;ジャンプ
SEND_4_ON
		BSF	PORTA,1		;指定ビットに1を立てる
		goto	SEND_4_BIT_END
SEND_4_OFF
		BCF	PORTA,1		;指定ビットに0を立てる
SEND_4_BIT_END
;-----------------------------------------------------------------------
;5ビット目の送信
;-----------------------------------------------------------------------
SEND_5_BIT
		MOVFW	SEND_COUNTER	;WレジスタにFレジスタを代
		SUBLW	0x07		;Wレジスタから値を引く
		BNZ	SEND_5_BIT_END	;結果が0以外ならジャンプ
		BTFSS	SEND_BUF,5	;指定ビットがゼロ以外ならスキップ
		goto	SEND_5_OFF	;ジャンプ
SEND_5_ON
		BSF	PORTA,1		;指定ビットに1を立てる
		goto	SEND_5_BIT_END
SEND_5_OFF
		BCF	PORTA,1		;指定ビットに0を立てる
SEND_5_BIT_END
;-----------------------------------------------------------------------
;6ビット目の送信
;-----------------------------------------------------------------------
SEND_6_BIT
		MOVFW	SEND_COUNTER	;WレジスタにFレジスタを代
		SUBLW	0x05		;Wレジスタから値を引く
		BNZ	SEND_6_BIT_END	;結果が0以外ならジャンプ
		BTFSS	SEND_BUF,6	;指定ビットがゼロ以外ならスキップ
		goto	SEND_6_OFF	;ジャンプ
SEND_6_ON
		BSF	PORTA,1		;指定ビットに1を立てる
		goto	SEND_6_BIT_END
SEND_6_OFF
		BCF	PORTA,1		;指定ビットに0を立てる
SEND_6_BIT_END
;-----------------------------------------------------------------------
;7ビット目の送信
;-----------------------------------------------------------------------
SEND_7_BIT
		MOVFW	SEND_COUNTER	;WレジスタにFレジスタを代
		SUBLW	0x03		;Wレジスタから値を引く
		BNZ	SEND_7_BIT_END	;結果が0以外ならジャンプ
		BTFSS	SEND_BUF,7	;指定ビットがゼロ以外ならスキップ
		goto	SEND_7_OFF	;ジャンプ
SEND_7_ON
		BSF	PORTA,1		;指定ビットに1を立てる
		goto	SEND_7_BIT_END
SEND_7_OFF
		BCF	PORTA,1		;指定ビットに0を立てる
SEND_7_BIT_END
;-----------------------------------------------------------------------
;ストップビットの送信
;-----------------------------------------------------------------------
SEND_STOP_BIT
		MOVFW	SEND_COUNTER	;WレジスタにFレジスタを代
		SUBLW	0x01		;Wレジスタから値を引く
		BNZ	SEND_STOP_BIT_END	;結果が0以外ならジャンプ
		BSF	PORTA,1		;指定ビットに1を立てる
SEND_STOP_BIT_END
;-----------------------------------------------------------------------
;送信完了のため、送信バッファのクリア
;-----------------------------------------------------------------------
SEND_BUF_CLEAR
		TSTF	SEND_COUNTER	;SEND_COUNTERがゼロかテストする
		BNZ	SEND_END		;ゼロ以外のときジャンプ
		;送信バッファをクリアする
		MOVLW	0x00		;Wレジスタに値を代入 
		MOVWF	SEND_BUF		;WレジスタからFレジスタに代入
SEND_END
;----------------------------------------------------------------------------

;****************************************************************************
;RS232c受信処理
;****************************************************************************
;1/19200 secでタイマー割り込み
;スタートビットが立ったことを検出する
;READ_COUNTER	ビット数をカウントするメモリ
;READ_TMR	タイマー割り込みを分周するためのメモリ
COUNTSET_START
		TSTF	READ_COUNTER	;READ_COUNTERがゼロかテストする
		BNZ	COUNTSET_END	;ゼロでないときジャンプ
COUNTSET
		BTFSC	PORTA,0		;指定ビットがゼロならスキップ
		goto	COUNTSET_END	;ジャンプ
		BTFSC	PORTA,0		;指定ビットがゼロならスキップ
		goto	COUNTSET_END	;ジャンプ;
		BTFSC	PORTA,0		;指定ビットがゼロならスキップ
		goto	COUNTSET_END	;ジャンプ
		BTFSC	PORTA,0		;指定ビットがゼロならスキップ
		goto	COUNTSET_END	;ジャンプ

		MOVLW	0x12+0x01		;Wレジスタに値を代入 
		MOVWF	READ_COUNTER	;WレジスタからFレジスタに代入


COUNTSET_END

		TSTF	READ_COUNTER	;READ_COUNTERがゼロかテストする
		BZ	intret		;ゼロのときジャンプ

		;1/19200を32分周して1/600を作り出す
		decfsz	READ_TMR,F	;Fレジスタを‐1して0ならスキップ
		goto	intret		;ジャンプ
		MOVLW	0x1F		;Wレジスタに値を代入
		MOVWF	READ_TMR		;WレジスタからFレジスタに代入

		DECF	READ_COUNTER	;Fレジスタを-1する

;----------------------------------------------------------------------
;Startビットの確認
;----------------------------------------------------------------------
READ_ST_INIT
		MOVFW	READ_COUNTER	;WレジスタにFレジスタを代入
		SUBLW	0x12		;Wレジスタから値を引く
		BNZ	READ_ST_END	;結果が0以外ならジャンプ
READ_ST_START
		BTFSC	PORTA,0		;指定ビットがゼロならスキップ
		goto	READ_ST_ERR	;ジャンプ
		BTFSC	PORTA,0		;指定ビットがゼロならスキップ
		goto	READ_ST_ERR	;ジャンプ;
		;StartREADが立っている事を確認
		goto	READ_0_END	;ジャンプ;
READ_ST_ERR
		;StartREADが立っていない ノイズであるため受信処理をリセット
		MOVLW	0x00		;Wレジスタに値を代入 
		MOVWF	READ_COUNTER	;WレジスタからFレジスタに代入
READ_ST_END
;----------------------------------------------------------------------
;0ビット目の取得
;----------------------------------------------------------------------
READ_0_INIT
		MOVFW	READ_COUNTER	;WレジスタにFレジスタを代入
		SUBLW	0x10		;Wレジスタから値を引く
		BNZ	READ_0_END	;結果が0以外ならジャンプ
READ_0_START
		BTFSC	PORTA,0		;指定ビットがゼロならスキップ
		goto	READ_0_ON		;ジャンプ
		BTFSC	PORTA,0		;指定ビットがゼロならスキップ
		goto	READ_0_ON		;ジャンプ;
READ_0_OFF
		BCF	READ_BUF,0	;指定ビットに0を立てる
		goto	READ_0_END	;ジャンプ;
READ_0_ON
		BSF	READ_BUF,0	;指定ビットに1を立てる
READ_0_END
;----------------------------------------------------------------------
;1ビット目の取得
;----------------------------------------------------------------------
READ_1_INIT
		MOVFW	READ_COUNTER	;WレジスタにFレジスタを代入
		SUBLW	0x0E		;Wレジスタから値を引く
		BNZ	READ_1_END	;結果が0以外ならジャンプ
READ_1_START
		BTFSC	PORTA,0		;指定ビットがゼロならスキップ
		goto	READ_1_ON		;ジャンプ
		BTFSC	PORTA,0		;指定ビットがゼロならスキップ
		goto	READ_1_ON		;ジャンプ;
READ_1_OFF
		BCF	READ_BUF,1	;指定ビットに0を立てる
		goto	READ_1_END	;ジャンプ;
READ_1_ON
		BSF	READ_BUF,1	;指定ビットに1を立てる
READ_1_END
;----------------------------------------------------------------------
;2ビット目の取得
;----------------------------------------------------------------------
READ_2_INIT
		MOVFW	READ_COUNTER	;WレジスタにFレジスタを代入
		SUBLW	0x0C		;Wレジスタから値を引く
		BNZ	READ_2_END	;結果が0以外ならジャンプ
READ_2_START
		BTFSC	PORTA,0		;指定ビットがゼロならスキップ
		goto	READ_2_ON		;ジャンプ
		BTFSC	PORTA,0		;指定ビットがゼロならスキップ
		goto	READ_2_ON		;ジャンプ;
READ_2_OFF
		BCF	READ_BUF,2	;指定ビットに0を立てる
		goto	READ_2_END	;ジャンプ;
READ_2_ON
		BSF	READ_BUF,2	;指定ビットに1を立てる
READ_2_END
;----------------------------------------------------------------------
;3ビット目の取得
;----------------------------------------------------------------------
READ_3_INIT
		MOVFW	READ_COUNTER	;WレジスタにFレジスタを代入
		SUBLW	0x0A		;Wレジスタから値を引く
		BNZ	READ_3_END	;結果が0以外ならジャンプ
READ_3_START
		BTFSC	PORTA,0		;指定ビットがゼロならスキップ
		goto	READ_3_ON		;ジャンプ
		BTFSC	PORTA,0		;指定ビットがゼロならスキップ
		goto	READ_3_ON		;ジャンプ;
READ_3_OFF
		BCF	READ_BUF,3	;指定ビットに0を立てる
		goto	READ_3_END	;ジャンプ;
READ_3_ON
		BSF	READ_BUF,3	;指定ビットに1を立てる
READ_3_END
;----------------------------------------------------------------------
;4ビット目の取得
;----------------------------------------------------------------------
READ_4_INIT
		MOVFW	READ_COUNTER	;WレジスタにFレジスタを代入
		SUBLW	0x08		;Wレジスタから値を引く
		BNZ	READ_4_END	;結果が0以外ならジャンプ
READ_4_START
		BTFSC	PORTA,0		;指定ビットがゼロならスキップ
		goto	READ_4_ON		;ジャンプ
		BTFSC	PORTA,0		;指定ビットがゼロならスキップ
		goto	READ_4_ON		;ジャンプ;
READ_4_OFF
		BCF	READ_BUF,4	;指定ビットに0を立てる
		goto	READ_4_END	;ジャンプ;
READ_4_ON
		BSF	READ_BUF,4	;指定ビットに1を立てる
READ_4_END
;----------------------------------------------------------------------
;5ビット目の取得
;----------------------------------------------------------------------
READ_5_INIT
		MOVFW	READ_COUNTER	;WレジスタにFレジスタを代入
		SUBLW	0x06		;Wレジスタから値を引く
		BNZ	READ_5_END	;結果が0以外ならジャンプ
READ_5_START
		BTFSC	PORTA,0		;指定ビットがゼロならスキップ
		goto	READ_5_ON		;ジャンプ
		BTFSC	PORTA,0		;指定ビットがゼロならスキップ
		goto	READ_5_ON		;ジャンプ;
READ_5_OFF
		BCF	READ_BUF,5	;指定ビットに0を立てる
		goto	READ_5_END	;ジャンプ;
READ_5_ON
		BSF	READ_BUF,5	;指定ビットに1を立てる
READ_5_END
;----------------------------------------------------------------------
;6ビット目の取得
;----------------------------------------------------------------------
READ_6_INIT
		MOVFW	READ_COUNTER	;WレジスタにFレジスタを代入
		SUBLW	0x04		;Wレジスタから値を引く
		BNZ	READ_6_END	;結果が0以外ならジャンプ
READ_6_START
		BTFSC	PORTA,0		;指定ビットがゼロならスキップ
		goto	READ_6_ON		;ジャンプ
		BTFSC	PORTA,0		;指定ビットがゼロならスキップ
		goto	READ_6_ON		;ジャンプ;
READ_6_OFF
		BCF	READ_BUF,6	;指定ビットに0を立てる
		goto	READ_6_END	;ジャンプ;
READ_6_ON
		BSF	READ_BUF,6	;指定ビットに1を立てる
READ_6_END
;----------------------------------------------------------------------
;7ビット目の取得
;----------------------------------------------------------------------
READ_7_INIT
		MOVFW	READ_COUNTER	;WレジスタにFレジスタを代入
		SUBLW	0x02		;Wレジスタから値を引く
		BNZ	READ_7_END	;結果が0以外ならジャンプ
READ_7_START
		BTFSC	PORTA,0		;指定ビットがゼロならスキップ
		goto	READ_7_ON		;ジャンプ
		BTFSC	PORTA,0		;指定ビットがゼロならスキップ
		goto	READ_7_ON		;ジャンプ;
READ_7_OFF
		BCF	READ_BUF,7	;指定ビットに0を立てる
		goto	READ_7_END	;ジャンプ;
READ_7_ON
		BSF	READ_BUF,7	;指定ビットに1を立てる
READ_7_END
;----------------------------------------------------------------------
;自作プロトコル受信のための操作
;----------------------------------------------------------------------
READ_TRUST_INIT
		MOVFW	READ_COUNTER	;WレジスタにFレジスタを代入
		SUBLW	0x01		;Wレジスタから値を引く
		BNZ	READ_TRUST_END	;結果が0以外ならジャンプ
READ_TRUST_START
		;受信バッファの7ビット目が0ならばデータ、1ならばミラー
		BTFSC	READ_BUF,7	;指定ビットがゼロならスキップ
		goto	READ_TRUST_MIRROR	;ジャンプ
READ_TRUST_DATA
		;データのため、バッファに退避させる
		MOVFW	READ_BUF		;WレジスタにFレジスタを代入
		MOVWF	TRUST_BUF		;FレジスタにWレジスタを代入
		goto	READ_TRUST_END	;ジャンプ;
READ_TRUST_MIRROR
		;ミラーデータの受信
		COMF	READ_BUF,0	;Fレジスタを反転しWレジスタへ転送
		SUBWF	TRUST_BUF,0	;Wレジスタから値を引く
		BNZ	READ_TRUST_END	;結果が0以外ならジャンプ
		;受信データが正しいことを確認できたためノードIDを確認する
CHECK_NODE_ID
		COMF	READ_BUF,1	;Fレジスタを反転しFレジスタへ転送
		;READ_BUFにはこの時点でTRUST_BUFと同じ値が入っている
		MOVFW	NODE_ID		;WレジスタにFレジスタを代入
		XORWF	READ_BUF,1	;XORをとり結果をFレジスタに代入
		BTFSC	READ_BUF,3	;3bit目が0ならばスキップ
		goto	READ_TRUST_END	;IDが違ったため受信データを無視する
		BTFSC	READ_BUF,4	;4bit目が0ならばスキップ
		goto	READ_TRUST_END	;IDが違ったため受信データを無視する
		BTFSC	READ_BUF,5	;5bit目が0ならばスキップ
		goto	READ_TRUST_END	;IDが違ったため受信データを無視する
		BTFSC	READ_BUF,6	;6bit目が0ならばスキップ
		goto	READ_TRUST_END	;IDが違ったため受信データを無視する
CHECK_NODE_ID_END
		;IDおよび受信データが正しいことを確認
		MOVFW	TRUST_BUF		;WレジスタにFレジスタを代入
		MOVWF	TRUST_DATA	;FレジスタにWレジスタを代入
		;受信データを返信する
		MOVFW	TRUST_BUF		;WレジスタにFレジスタを代入
		MOVWF	SEND_BUF		;FレジスタにWレジスタを代入
READ_TRUST_END

;		COMF	PORTB,1		;Fレジスタを反転
		goto	intret		;ジャンプ
;***************************************************************
;スタート
;***************************************************************
start
;---------------------------------------------------------------
;ポートの設定
;---------------------------------------------------------------
		clrf	PORTA
		clrf	PORTB
		bsf	STATUS,5		;ページを1に切り替え
		movlw	0x01
		movwf	TRISA		;portAをbit 1 を入力に設定
		movlw	0x00
		movwf	TRISB		;portBを出力に設定
		bcf	STATUS,5		;ページを0に切り替え

;---------------------------------------------------------------
;RB0/INT割り込みの設定
;---------------------------------------------------------------
		bsf	STATUS,5		;ページを1に切り替え
		bcf	OPTION_REG,6	;RB0のエッジ設定は立ち上がり
		bcf	STATUS,5		;ページを0に切り替え
;		bsf	INTCON,4		;RB0/INT割り込み発生許可
;---------------------------------------------------------------
;RB4〜RB7割り込みの設定
;---------------------------------------------------------------
;		bsf	INTCON,3		;RB4〜RB7割り込み発生許可
;---------------------------------------------------------------
;タイマー割り込みの設定
;---------------------------------------------------------------
		movlw	0x00		;タイマー値リセット
		movwf	TMR0
		bsf	STATUS,5		;ページを1に切り替え
		bsf	OPTION_REG,0	;PS0	プリスケーラの設定
		bsf	OPTION_REG,1	;PS1	
		bsf	OPTION_REG,2	;PS2	
		bsf	OPTION_REG,3	;PSA	プリスケーラをTMRで使用する場合は0,WDTで使用する場合は1
		bcf	OPTION_REG,5	;T0CS	タイマ0の入力先 1でRA4ピン入力,0でクロック1/4入力
		bcf	STATUS,5		;ページを0に切り替え
		bsf	INTCON,5		;タイマ割り込み発生許可
;---------------------------------------------------------------
;割り込みの開始
;---------------------------------------------------------------
		bsf	INTCON,7		;割り込み許可

;***************************************************************
;メイン
;***************************************************************
APP_INIT
		;所定の変数を初期化しておかないと起動時に意図しない動作をする可能性がある
		MOVLW	0x00		;Wレジスタに値を代入 
		MOVWF	READ_BUF		;WレジスタからFレジスタに代入
		MOVLW	0x00		;Wレジスタに値を代入 
		MOVWF	SEND_BUF		;WレジスタからFレジスタに代入
		MOVLW	0x00		;Wレジスタに値を代入 
		MOVWF	SEND_COUNTER	;WレジスタからFレジスタに代入
		;MAX3232への出力は反転しているため、最初はHiを出力しておく必要がある
		BSF	PORTA,1		;指定ビットに1を立てる

		MOVLW	0x00		;Wレジスタに値を代入 
		MOVWF	TRUST_DATA	;WレジスタからFレジスタに代入
		;ノードIDの設定 ID * 0x08は左に3ビットシフトさせるため
		MOVLW	0x01*0x08		;Wレジスタに値を代入 
		MOVWF	NODE_ID		;WレジスタからFレジスタに代入


main
;-------------------------------------
;読み出し中の場合は待機するループ
;--------------------------------------
;READ_WAIT
;		TSTF	READ_COUNTER	;READ_COUNTERがゼロかテストする
;		BNZ	READ_WAIT		;ゼロ以外のときジャンプ
;READ_WAIT_END
;-------------------------------------
		MOVFW	TRUST_DATA	;FレジスタからWレジスタに代入
		MOVWF	PORTB		;WレジスタからFレジスタに代入
;-------------------------------------
;送信中の場合は待機するループ
;-------------------------------------
;SEND_WAIT
;		TSTF	SEND_BUF		;SEND_BUFがゼロかテストする
;		BNZ	SEND_WAIT		;ゼロ以外のときジャンプ
;SEND_WAIT_END
;-------------------------------------

		goto	main

;		call	wait_loop
;		COMF	PORTB,1		;Fレジスタを反転


;---------------------------------------------------------------
;ウエイト
;---------------------------------------------------------------
wait_loop
		MOVLW	0x00
		MOVWF	wait_val1
wait_loop1
		MOVLW	0x00
		MOVWF	wait_val2
wait_loop2	NOP
		decfsz	wait_val2,F
		goto	wait_loop2
		decfsz	wait_val1,F
		goto	wait_loop1

		return


		END










20060917作成



▲トップページ > マイコンなど