ソースコード解説_1(Excelでシリアル通信-5)

Excelからシリアル通信を実現してみようという連載の5回目です。前回の記事はこちらになります。

hirocom777.hatenadiary.org

前回はExcelと通信モニターでデータを送受信してみました。実際に送受信できるようになると、面白くなってきますね。

今回はLoopBackTestToolのソースコードを解説します。

実際のコード

それでは実際のコードを見てみます。

入力対応

まずは入力対応です。Topシートに記述されていて、実行ボタンに割り当てられています。

'ループバックテスト実行
Public Sub Execute()
  Me.Range("Receive_Data").Value = _
    LoopBackTest(Me.Range("Port_No").Value, Me.Range("Send_Data").Value)
  Me.Range("Send_Data").Value = ""
End Sub

標準モジュールに記述されているファンクションプロシージャ「LoopBackTest」に、ポート番号と送信データを引数で渡しています。受信したデータが返り値になって、シート上に表示されます。

ループバックテスト(前半)

標準モジュールのファンクションプロシージャ「LoopBackTest」の内容前半です。指定されたポートの初期設定を実行します。コマンドの詳細については次回に説明します。

'ループバックテスト
Public Function LoopBackTest(ByVal comPort As String, ByVal sendData As String) As String
Dim lngResult As Long
Dim lngHandle As Long

  'ポートオープン処理
  comPort = "\\.\" & comPort
  lngHandle = CreateFile(comPort, GENERIC_READ Or GENERIC_WRITE, _
                  0&, 0&, OPEN_EXISTING, 0&, 0&)
                  
  'バッファの設定
  lngResult = SetupComm(lngHandle, 2048, 2048)
  
  'バッファのクリア
  lngResult = PurgeComm(lngHandle, PURGE_TXCLEAR)
  lngResult = PurgeComm(lngHandle, PURGE_RXCLEAR)
  
  '通信設定
  fDCB.BaudRate = 9600
  fDCB.Parity = 0
  fDCB.ByteSize = 8
  fDCB.StopBits = 1

  lngResult = SetCommState(lngHandle, fDCB)
  
  'タイムアウト1秒に設定
  fCOMMTIMEOUTS.ReadIntervalTimeout = 1000
  fCOMMTIMEOUTS.ReadTotalTimeoutMultiplier = 1000
  fCOMMTIMEOUTS.ReadTotalTimeoutConstant = 1000
  fCOMMTIMEOUTS.WriteTotalTimeoutMultiplier = 1000
  fCOMMTIMEOUTS.WriteTotalTimeoutConstant = 1000
  lngResult = SetCommTimeouts(lngHandle, fCOMMTIMEOUTS)
  Application.Wait TimeSerial(Hour(Now()), Minute(Now()), Second(Now()) + 3)

ボートをオープンしてからバッファーの設定とクリア、通信条件の設定、タイムアウト時間の設定をしています。通信条件はArduino標準にあわせてあります。

ループバックテスト(後半)

続いて後半です。実際の送受信を実施します。

  '送受信開始
  'データ送信
  If sendData <> "" Then
    Dim writeData() As Byte
    writeData = StrConv(sendData, vbFromUnicode)
    Dim writeBytes As Long
    writeBytes = UBound(writeData) + 1
    
    '送信実行
    Call WriteFile(lngHandle, writeData(0), writeBytes, lngResult, 0)
  End If
  Application.Wait TimeSerial(Hour(Now()), Minute(Now()), Second(Now()) + 1)
  
  '返信データ受信
  Call ClearCommError(lngHandle, lngResult, fCOMSTAT)
  If 0 < fCOMSTAT.cbInQue Then
    '受信データ確認
    Dim readByte As Long
    readByte = fCOMSTAT.cbInQue
    ReDim readData(readByte - 1) As Byte
    Call ReadFile(lngHandle, readData(0), readByte, lngResult, 0)
    LoopBackTest = StrConv(readData, vbUnicode)
  End If

  'ポートクローズ
  CloseHandle lngHandle
End Function

送信データがある場合には、データを変換して送信を実施します。Unicodeの文字列データをバイト形式の配列にして送信しています。 続いて受信データを確認してデータがある場合には、受信を実施します。受信データは送信と逆に、バイト形式の配列で受信して、文字列データに変換します。 一連の動作が完了するとポートをクローズします。

次回もソースコード解説

如何でしょうか。今回は動作部分の解説を行いました。次回は使用しいるダイナミック リンク ライブラリ (DLL) の参照、その他の宣言について解説しようと思います。お楽しみに!!!