シリアル通信(RS-232C)を制御する

外部機器や簡単な通信をするのに昔はRS-232Cがよく使われました。 さすがに今はUSBにほとんど移行したのですが RS-232Cは現在でも簡単な機器制御に使われます。 (ドライバが要らないし、WindowsにAPIが用意されてるので簡単なので) ということで、RS-232Cを用いたシリアル通信を行ってみます。 (プログラムはページの一番下でダウンロードできます。)

全 体 の 流 れ

(送信側)
@シリアルポートの初期設定(タイムアウトや通信速度など)
A送信文字列を送信する
B受信モード
C受信文字列を受信したら表示する。


(受信側)
@シリアルポートの初期設定(タイムアウトや通信速度など)
A受信モード
B受信文字列を受信したら表示する
C返答の文字列を送信する



シリアルポートの初期化

シリアルポートの初期化は次のような流れで行います。
@CloseHandle(21)でポートを強制クローズ
ACreateFile()関数でポートをオープンする
BDCB構造体を用いて、通信方式を設定する
CCOMMTIMEOUTS構造体を用いて、タイムアウトを設定する

Example

Public Function Init_Comm(ByVal lpCommPort As String) As Long
'シリアルポートの初期化処理
'lpCommPort:オープンするポートの名前(COM1,COM2,...)
'(戻り値):ポートのハンドル
Dim hCom As Long
Dim lpDCB As DCB, timeOut As COMMTIMEOUTS

Call CloseHandle(21)
hCom = CreateFile(lpCommPort, GENERIC_READ Or GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0)
If hCom <> -1 Then
     'DCBを読み込む(ポートに設定されている標準設定を読み込む)
     Call GetCommState(hCom, lpDCB)
     With lpDCB
         .BaudRate = 9600
         .ByteSize = 8
         .DCBflags = &H3001
         .Parity = 0
         .StopBits = 0
     End With
     'DCBを設定する
     Call SetCommState(hCom, lpDCB)
    
     'タイムアウトを設定する
     With timeOut
         .ReadIntervalTimeout = 1000             'タイムアウトの時間
         .ReadTotalTimeoutMultiplier = 0         '一文字あたりの時間
         .ReadTotalTimeoutConstant = 1000        '受信の定数時間
         .WriteTotalTimeoutMultiplier = 0        '一文字あたりの時間
         .WriteTotalTimeoutConstant = 1000       '送信の定数時間
     End With
     Call SetCommTimeouts(hCom, timeOut)
End If
Init_Comm = hCom

送信の方法

送信には2つの方法があります。
WriteFile()関数を使う方法とTransmitCommChar()関数を使う方法です。
WriteFile()関数は複数の文字列を送信する場合に使います。
一方、TransmitCommChar()関数は1文字しか送れません。
しかし、TransmitCommChar()関数は確実に1文字を送ってくれます。
WriteFile()関数の場合、一度バッファリングされますが、TransmitCommChar()関数は
直接シリアルポートに送るようです。
TransmitCommChar()関数は、WriteFile()関数ができなかったときにやってみてください。
今回はWriteFile()関数を使います。

Example

Public Function Data_Tx(ByVal hCom As Long, ByVal lpString As String) As Long
'データをシリアルポートに送信する
'hCom:シリアルポートのハンドル
'temp_byte:送信するデータ(1バイト)
Dim wData() As Byte, wLen As Long, dLen As Long

wData() = StrConv(lpString, vbFromUnicode)
wLen = LenB(StrConv(lpString, vbFromUnicode))
Call ClearCommBreak(hCom)
Data_Tx = WriteFile(hCom, wData(0), wLen, dLen, 0)

外部機器や簡単な通信をするのに昔はRS-232Cがよく使われました。
さすがに今はUSBにほとんど移行したのですが
RS-232Cは現在でも簡単な機器制御に使われます。
(ドライバが要らないし、WindowsにAPIが用意されてるので簡単なので)
ということで、RS-232Cを用いたシリアル通信を行ってみます。
(プログラムはページの一番下でダウンロードできます。)

受信の方法

受信には受信専用の関数もある(確かあったはず)のですが、
それはWin3.1の頃の話なので、一般的にはReadFile()関数を使います。
@FlashFileBuffer(21)でポートの中のバッファを削除
Aバイト列のバッファを用意
BReadFile()関数を用いて受信する
C受信できなかったらBでもう一回

Example

Public Function Data_RX() As String
'データを受信する
Dim rc As Long, Cnt As Long, Buffer() As Byte, lData As Long, temp As String

If CancelFlag = False Then
     Buffer() = String(lpReadData_Parameters.BufferSize, 32)
     Cnt = 0
     'Call FlushFileBuffers(param)
     Do While (rc < 1) And (Cnt < 10) 'リトライ10回
         rc = ReadFile(param, Buffer(0), lpReadData_Parameters.BufferSize, lData, ByVal 0&)
         Cnt = Cnt + 1
     Loop
     If rc > 0 Then
         '受信したとき、受信データを文字列に変換
         Data_RX = StrConv(LeftB(Buffer(), lData), vbUnicode)
     End If
End If

ざっとこんな感じです。 これ以上、長い解説は疲れるので、とりあえずここでやめます。 ケーブルは「クロスケーブル」で行ってください。 「ストレートケーブル」では上手くできませんので、あしからず。 それではがんばってみてください。