【パソコンと接続】
PICとパソコンを接続して通信が出来るようになれば、いろいろな
応用範囲が考えられ、楽しさも倍増します。
ここでは、パソコンとプリンタインターフェースにより接続する方法
を説明します。
この送受信にはハンドシェイク通信方式という方法もありますが、
ここではもう少し簡単な方法を使っています。
【プリンタインターフェース接続】
パソコンのプリンタインターフェースは、DOS/V機の場合、パラレル
の双方向通信が出来るようになっています。(最近のPC98xxNXも)
そこで、このプリンタインターフェースを使って8ビットパラレルでPIC
と双方向通信をする方法を説明します。
まずパソコン側のプリンタインターフェースの詳細については、別の
ハンドシェイクのプリンタインターフェースに詳細があるのでそちらを
参照して下さい。
ここで注意が必要なことは、STROBEとBUSYの論理反転に関する
ことで、
パソコン側はSTROBEは正論理で出力され、BUSYは負論理
で入力されるが、PIC側の信号はいずれも正論理でそのまま
入出力される。
ということです。
従って、下図の様にPICとパソコンを接続した時には、この論理の
正負を意識して考えなければなりません。
【信号とタイミング】
上記接続での信号のタイミングは下図のようにします。
パソコンからデータを送信するときには、8ビットデータをまず出力
してから、STROBE信号を「1」にします。
そして、PIC側からのBUSY信号(PICのSTROBE出力)を待ち、BUSY
がもとに戻ったらSTOROBEも「0」に戻して完了し、次のデータに移り
ます。
パソコンが受信するときには、PICからのBUSY信号(PICのSTROBE
出力)を先に待ちます。
そして、BUSYを受け付けたら、STROBEを「1」にしてからデータを入力
し、続いてSTROBEを「0」に戻します。そしてPIC側からのBUSYが元に
戻ったのを確認して完了です。
【パソコン側プログラム】
パソコン側のパラレル入出力のプログラムは直接入出力命令を実行
するため、Visual C++を使ってDynamic Link Library(DLL)形式とします。
このDLLプログラムのつかり方の詳細は、「DLLプログラムの作り方」
のページを参照して下さい。
プログラムは上記タイムチャートをそのままフローにした形になって
います。
/*************************************************
* Parallel Interface Drive Program.
* This Driver includes below function by Dynamic Link
* Library(DLL) Program.
* 1. RecvD Input one Byte data by handshake protocol
* 2. SendD Output one Byte data by handshake protocol
***************************************************/
#define DllExport _declspec(dllexport) //DLL宣言
#define NOERR 0
#define BUSY -1
//Input Function by Handshake Protocol (RecvD)
DllExport short _stdcall RecvD(unsigned short port)
{unsigned databyte; unsigned state_busy;
while(state_busy !=0) { //STROBE待ち
state_busy = _inp(port+1) & 0x80;
}
_outp(port+2,0x21); //ビジー出力,入力モード
databyte = _inp(port); //データ入力(Dumy)
databyte = _inp(port); //データ入力
_outp(port+2,0); //ビジー解除、出力モード
while(state_busy ==0) { //STROBE reset待ち
state_busy = _inp(port+1) & 0x80;
}
return databyte; //入力データ返し
}
//Output Function by HandShake Protocol (SendD)
DllExport short _stdcall SendD(unsigned short port, unsigned short databyte)
{unsigned state_busy; unsigned i;
for (i=0;i<1000;i++) { //レディー待ち
state_busy = _inp(port+1) & 0x80;
if (state_busy != 0){
break;
}
}
if (state_busy == 0){ //タイムアウトエラー
return(BUSY);
}
_outp(port, databyte); //データ出力
_outp(port+2,1); //ストローブ出力
while(state_busy != 0) { //ビジー待ち
state_busy = _inp(port+1) & 0x80;
}
while(state_busy ==0) { //ビジー解除待ち
state_busy = _inp(port+1) & 0x80;
}
_outp(port+2,0); //ストローブ解除
return(NOERR);
}
【PIC側プログラム】
このパソコンと接続して通信するためのPIC側のプログラムも、上記
のフローチャートのままの流れとなっています。
送信と受信に判れていますが、基本的なことは、すべてパソコン側が
主導権をもっているということです。
つまり、パソコン側から、コマンドを受信してからしか、PIC側からは
データを送信することが出来ないということです。
(1)ポート初期化
まずはポートの入出力の設定です。
;**************************************
; ポート初期化部分
; PORT A RA3 :STROBE output
; RA4 :BUSY input
; PORT B all input/output changable
;**************************************
INITA
BSF STATUS,RP0 ;Set Page 1
MOVLW 017H ;Set PortA to receive mode
MOVWF TRISA
MOVLW 0FFH
MOVWF TRISB ;Set Portb to all input
BCF STATUS,RP0 ;Set Page 0
このあとの処理へ
(2)受信プログラム
パソコン側からのコマンドの受信部分で、このコマンドを受信
してから次の処理に移り、送信することが出来ます。
;********************************
; 受信サブルーチンプログラム
; データはCMNDに格納されて戻る
;********************************
RCVSUB
BSF STATUS,RP0 ;Set Page 1
MOVLW 0FFH ;get FF
MOVWF TRISB ;Set Portb to all input
BCF STATUS,RP0 ;Set Page 0
BCF PORTA,3 ;reset STROB
;***** BUSY待ち ****
RCVLP
BTFSC PORTA,4 ;RA4 BUSY input
GOTO RCVLP
BTFSC PORTA,4 ;確認のため再入力
GOTO RCVLP
BSF PORTA,3 ;set STROB as BUSY on
MOVF PORTB,W ;get command data
MOVWF CMND ;COMMAND save
NOP ;パルス幅の確保用
NOP
BCF PORTA,3 ;reset STROB as BUSY off
RETURN
(3)送信プログラム
1バイトのデータをパソコンへ送信するためのプログラム
です。
;************************************
; 1バイト送信サブルーチンプログラム
; During send mode RA3=STORBE output
; and RA4=BUSY input,PORTB is output
;************************************
SNDSUB
MOVWF TEMP ;save send data
BSF STATUS,RP0 ;Set Page 1
CLRF TRISB ;Set PORTB to all output
BCF STATUS,RP0 ;Set Page 0
;**** check busy ******
CKBSY
BTFSS PORTA,4 ;Test BUSY
GOTO CKBSY ;busy case
;*** Send data ***
MOVF TEMP,W ;get send data
MOVWF PORTB ;data out
NOP ;delay
BSF PORTA,3 ;set STROB
;**** wait PC input ****
WTBSY
BTFSC PORTA,4 ;wait BUSY on
GOTO WTBSY
WTRDY
BTFSS PORTA,4 ;wait BUSY off
GOTO WTRDY
BCF PORTA,3 ;reset STROB
RETURN