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作成
▲トップページ
>
マイコンなど