RS232cで信頼性の有る通信A
PIC16F84を使った通信
前回は受信部分を作りましたので送信部分を作ります
■送信を確認するためのWindowsアプリケーションを作成
前回作成したWindowsアプリケーションを少し変更します
#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,
0,
1000
); //接続します
unsigned char data[5]="";
char c;
while(1){
c=0;
rs.Read(&c,1); //文字列の受信 Read(char配列,読み込む文字数)
if(c) printf("read 0x%x\n",(unsigned char)c);
if(c>>7){
data[0]=~c;
data[1]='\0';
rs.Send((char*)data); //文字列を送信 Send(送信文字列)
printf("send 0x%x\n",(unsigned char)data[0]);
}
}
//クローズする必要はありません、オブジェクトが破棄された時、クローズされます
return 0;
}
RS232cから一文字ずつデータを受信して先頭ビットが立っているデータを受信した場合には
そのデータを反転して送信するプログラムです
■マイコンからデータを送信するトリガーを作る
まずは、ポートAのビット2,3,4の位置の端子を100KΩでマイナス側に吊って
スイッチを取り付けました
これで、プログラムでビット2,3,4のスイッチの状態を読み取れます
▼前回作成したプログラムのメインループを修正して
スイッチの変化をそのまま送信できるようにしたいと思います
;PORTAの2,3,4ビット目が変化した時、送信処理を行うために使用するメモリ
PA_NEW equ 0x19
PA_OLD equ 0x1A
▲以上のメモリを使いポートの変化を読み取りたいと思います
main
MOVFW PORTA ;FレジスタからWレジスタに代入
ANDLW 0x1C ;11100でアンドを取る
MOVWF PA_NEW ;WレジスタからFレジスタに代入
SUBWF PA_OLD,0 ;FレジスタからWレジスタを引く
BZ main ;結果が0のときジャンプ
;-------------------------------------
;送信中の場合は待機するループ
;-------------------------------------
SEND_WAIT
TSTF SEND_BUF ;SEND_BUFがゼロかテストする
BNZ SEND_WAIT ;ゼロ以外のときジャンプ
SEND_WAIT_END
;-------------------------------------
MOVFW PA_NEW ;FレジスタからWレジスタに代入
MOVWF PA_OLD ;WレジスタからFレジスタに代入
MOVWF SEND_BUF ;WレジスタからFレジスタに代入
goto main
ポートAのビット 2,3,4 に変化が起きた場合には、ビット2,3,4 の情報をそのまま
RS232cで送信したいと思います
上記プログラムをPICに書き込み、パソコンとRS232cで接続しました
確認用プログラムを実行して2ビット目のスイッチから順に押してみました
c:\>■■■.exe
read 0x4
read 0x8
read 0x10
▲スイッチの入力がRS232cで正しく出力されている事が確認できました
■自作プロトコル送信
main部分を次のように修正しました
main
CLRWDT ;ウォッチドックタイマとプリスケーラをクリア
;自作プロトコル受信で受け取った値をPORTBに出力する
MOVFW TRUST_DATA ;FレジスタからWレジスタに代入
MOVWF PORTB ;WレジスタからFレジスタに代入
自作プロトコル受信したデータをポートBに出力しています
今回の変更とはあまり関係がない所です
;----------------------------------------------------------------------------
;PORTA bit2,3,4が変化した場合、状態を自作プロトコル送信で送信する処理
;----------------------------------------------------------------------------
MOVLW 0x00 ;Wレジスタに値を代入
MOVWF PA_NEW ;WレジスタからFレジスタに代入
;PORTAの値を左に2シフトする
BTFSC PORTA,2 ;Fレジスタの指定ビットが0ならスキップ
BSF PA_NEW,0 ;指定ビットに1を立てる
BTFSC PORTA,3 ;Fレジスタの指定ビットが0ならスキップ
BSF PA_NEW,1 ;指定ビットに1を立てる
BTFSC PORTA,4 ;Fレジスタの指定ビットが0ならスキップ
BSF PA_NEW,2 ;指定ビットに1を立てる
送信のトリガーとなるポートAのビットを取得しています
シフト演算が無いためビット操作でシフトを行っています
;送信ノードIDを取り付ける
;ノードID+1を送信ノードIDとする
MOVFW NODE_ID ;FレジスタからWレジスタに代入
;0x08は左に3ビットシフトさせるため
ADDLW 0x01*0x08 ;Wレジスタに値を加算
IORWF PA_NEW,1 ;ORを取りFレジスタに結果を代入
取得したビット情報に送信ノードIDを取り付けています
送信ノードIDは受信ノードID+1とします
(ホストがPCのため、各々のノードに送信IDを振らないと複数のノードを識別できない)
;前回値との判定
MOVFW PA_NEW ;FレジスタからWレジスタに代入
SUBWF PA_OLD,0 ;FレジスタからWレジスタを引く
BZ main ;結果が0のときジャンプ
前回値と比較して、変化が無かった場合はラベルmainにジャンプします
;前回と比較して状態が変化したため、送信処理を行う
call SEND_WAIT ;送信完了待ち
MOVFW PA_NEW ;FレジスタからWレジスタに代入
MOVWF SEND_BUF ;送信 WレジスタからFレジスタに代入
call SEND_WAIT ;送信完了待ち
COMF PA_NEW,0 ;Fレジスタを反転してWレジスタに格納
MOVWF SEND_BUF ;送信 WレジスタからFレジスタに代入
call SEND_WAIT ;送信完了待ち
前回値と比較して差異があるため自作プロトコルでデータを送信します
;通信相手の受信成功パケットを確認する
call wait_loop ;ウエイト
call READ_WAIT ;受信完了待ち
MOVFW PA_NEW ;FレジスタからWレジスタに代入
SUBWF TRUST_BUF,0 ;FレジスタからWレジスタを引く
BNZ main ;結果が0以外のときジャンプ
;受信成功パケットの確認がとれた
MOVFW PA_NEW ;FレジスタからWレジスタに代入
MOVWF PA_OLD ;WレジスタからFレジスタに代入
受信成功パケットを確認します、受信成功パケットが受信できた場合には
前回値データを更新します
goto main
■上記プログラムをPICに書き込み、パソコンとRS232cで接続しました
確認用プログラムを実行して2ビット目のスイッチから順に押してみました
c:\>■■■.exe
read 0x10←初期状態はスイッチは何も押されていないためその旨を送信
read 0xef
send 0x10
read 0x11←2ビット目のスイッチが押された
read 0xee
send 0x11
read 0x10←何もスイッチが押されていない状態になった
read 0xef
send 0x10
read 0x12←3ビット目のスイッチが押された
read 0xed
send 0x12
read 0x10←何もスイッチが押されていない状態になった
read 0xef
send 0x10
read 0x14←4ビット目のスイッチが押された
read 0xeb
send 0x14
read 0x10←何もスイッチが押されていない状態になった
read 0xef
send 0x10
正しく動作しているようです
ちなみに、パソコンが受信完了を送信しない、もしくは受信完了のビットが違っている
場合においては、マイコンがエラーと判定して受信完了が来るまでパケットを送り続けます
■ここまでで作った全ソースコード
;---------------------------------------------------------------
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
;PORTAの2,3,4ビット目が変化した時送信処理を行うために使用するメモリ
PA_NEW equ 0x19
PA_OLD equ 0x1A
;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 0x1D
movwf TRISA ;portAをbit 11101 を入力に設定
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に切り替え
;ウオッチドックタイマは約18msでタイムアウトするため
;プリスケーラで分周して128倍の時間、約2秒にする
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レジスタに代入
MOVWF SEND_BUF ;WレジスタからFレジスタに代入
MOVWF SEND_COUNTER ;WレジスタからFレジスタに代入
;MAX3232への出力は反転しているため、最初はHiを出力しておく必要がある
BSF PORTA,1 ;指定ビットに1を立てる
;自作プロトコル受信のための初期化処理
MOVLW 0x00 ;Wレジスタに値を代入
MOVWF TRUST_BUF ;WレジスタからFレジスタに代入
MOVWF TRUST_DATA ;WレジスタからFレジスタに代入
;ノードIDの設定 ID * 0x08は左に3ビットシフトさせるため
MOVLW 0x01*0x08 ;Wレジスタに値を代入
MOVWF NODE_ID ;WレジスタからFレジスタに代入
;自作プロトコル送信のための初期化処理
MOVLW 0x00 ;Wレジスタに値を代入
MOVWF PA_OLD ;WレジスタからFレジスタに代入
main
CLRWDT ;ウォッチドックタイマとプリスケーラをクリア
;自作プロトコル受信で受け取った値をPORTBに出力する
MOVFW TRUST_DATA ;FレジスタからWレジスタに代入
MOVWF PORTB ;WレジスタからFレジスタに代入
;----------------------------------------------------------------------------
;PORTA bit2,3,4が変化した場合、状態を自作プロトコル送信で送信する処理
;----------------------------------------------------------------------------
MOVLW 0x00 ;Wレジスタに値を代入
MOVWF PA_NEW ;WレジスタからFレジスタに代入
;PORTAの値を左に2シフトする
BTFSC PORTA,2 ;Fレジスタの指定ビットが0ならスキップ
BSF PA_NEW,0 ;指定ビットに1を立てる
BTFSC PORTA,3 ;Fレジスタの指定ビットが0ならスキップ
BSF PA_NEW,1 ;指定ビットに1を立てる
BTFSC PORTA,4 ;Fレジスタの指定ビットが0ならスキップ
BSF PA_NEW,2 ;指定ビットに1を立てる
;送信ノードIDを取り付ける
;ノードID+1を送信ノードIDとする
MOVFW NODE_ID ;FレジスタからWレジスタに代入
;0x08は左に3ビットシフトさせるため
ADDLW 0x01*0x08 ;Wレジスタに値を加算
IORWF PA_NEW,1 ;ORを取りFレジスタに結果を代入
;前回値との判定
MOVFW PA_NEW ;FレジスタからWレジスタに代入
SUBWF PA_OLD,0 ;FレジスタからWレジスタを引く
BZ main ;結果が0のときジャンプ
;前回値を破壊する(送受信完了前に状態が戻った場合の対策)
MOVLW 0x00 ;Wレジスタに値を代入
MOVWF PA_OLD ;WレジスタからFレジスタに代入
;前回と比較して状態が変化したため、送信処理を行う
call SEND_WAIT ;送信完了待ち
MOVFW PA_NEW ;FレジスタからWレジスタに代入
MOVWF SEND_BUF ;送信 WレジスタからFレジスタに代入
call SEND_WAIT ;送信完了待ち
COMF PA_NEW,0 ;Fレジスタを反転してWレジスタに格納
MOVWF SEND_BUF ;送信 WレジスタからFレジスタに代入
call SEND_WAIT ;送信完了待ち
;通信相手の受信成功パケットを確認する
call wait_loop ;ウエイト
call READ_WAIT ;受信完了待ち
MOVFW PA_NEW ;FレジスタからWレジスタに代入
SUBWF TRUST_BUF,0 ;FレジスタからWレジスタを引く
BNZ main ;結果が0以外のときジャンプ
;受信成功パケットの確認がとれた
MOVFW PA_NEW ;FレジスタからWレジスタに代入
MOVWF PA_OLD ;WレジスタからFレジスタに代入
goto main
;---------------------------------------------------------------
;ウエイト
;---------------------------------------------------------------
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
;-------------------------------------
;読み出し中の場合は待機するループ
;--------------------------------------
READ_WAIT
TSTF READ_COUNTER ;READ_COUNTERがゼロかテストする
BNZ READ_WAIT ;ゼロ以外のときジャンプ
READ_WAIT_END
return
;-------------------------------------
;-------------------------------------
;送信中の場合は待機するループ
;-------------------------------------
SEND_WAIT
TSTF SEND_BUF ;SEND_BUFがゼロかテストする
BNZ SEND_WAIT ;ゼロ以外のときジャンプ
SEND_WAIT_END
return
;-------------------------------------
END
■上記マイコンと通信するWindowsアプリケーションを作成してみました
画面上のボタンを押すことでマイコンのLEDが点等し、
マイコンのスイッチを操作することにより画面に状態が表示されます。
VisualC++6.0 MFC ソースとソフト
20060919 作成
▲トップページ
>
マイコンなど