2011年1月27日木曜日

VB2008とシリアルポートとQS20H

業務でVB2008のフォームへ手入力の変わりに卓上QR
リーダーでリードした内容を解析してトスするプログ
ラムを作成

開発段階ではDENSO WAVE製 GT-10Qで行い
実行環境では同社製 QS-20Hを利用した

しかし、このQS-20HはGT-10Qに比べ、なかなかの曲者
だった。これは、そのときに学んだことを忘れない
ようメモしたもの


【卓上リーダーQS-20HとVB2008】

*** ポイント1 ***
ハンドシェイクをRTSにしないとデータが流れてこない

具体的には次のように記述(SerialPort1はオブジェクト)
  SerialPort1.Handshake = IO.Ports.Handshake.RequestToSend

この設定でGT-10Qを接続しても異常動作はしない
また、GT-10Qはハンドシェイクなしでも普通にデータ
が流れてくる


*** ポイント2 ***
QS-20Hは最初のリードこそすべてのデータが一気に取得
できるがそれ以降、一気に取得できない
そのため、行端マーク(0x0D)を見張ってやる必要がある

流れは次のようになる


シリアルポートのデータ受信イベント
  ↓
シリアルポートからデータを読み出し
  ↓
バッファを結合
  ↓
行末コード0x0Dが来ていないならイベント処理から抜ける
  ↓
行末コード0x0D来たら処理しやすいように
バッファをString型に変換


  Private recieveBuffer As Byte()

  Private Sub SerialPort1_DataReceived( _ 
                            ByVal sender As System.Object _
                          , ByVal e As System.IO.Ports.SerialDataReceivedEventArgs _
                          ) Handles SerialPort1.DataReceived

    'シリアルポートからデータ取り出し
    Dim tmpRecieveBuffer As Byte() = New Byte(SerialPort1.BytesToRead - 1) {}
    SerialPort1.Read(tmpRecieveBuffer, 0, tmpRecieveBuffer.GetLength(0))

    '受信バッファ(recieveBuffer)へ入れ込む
    If recieveBuffer Is Nothing Then
      recieveBuffer = tmpRecieveBuffer
    Else
      Dim margeRecieveBuffer As Byte() = New Byte(recieveBuffer.Length + tmpRecieveBuffer.Length - 1) {}
      recieveBuffer.CopyTo(margeRecieveBuffer, 0)
      tmpRecieveBuffer.CopyTo(margeRecieveBuffer, recieveBuffer.Length)
      recieveBuffer = margeRecieveBuffer
    End If
    '仮受信バッファの行末に0x0Dが見つからなければここで処理を抜ける
    If tmpRecieveBuffer(tmpRecieveBuffer.Length - 1) <> 13 Then
      Exit Sub
    End If

    '0x0Dが来たら扱いやすいようにシフトJISにエンコードしてString型にする。その後受信バッファはクリア
    Dim recieveData As String = System.Text.Encoding.GetEncoding("SHIFT-JIS").GetString(recieveBuffer)
    recieveBuffer = Nothing

    '==============================
    '受信データ(recieveData)を使って処理をしていく
    '==============================

  End Sub



【VB2008のシリアル通信】

VB2008のシリアル通信は別スレッドで作動するため
フォームの内容を書き換えようとした場合は、
デリゲートでやらないといけない

MSDNのサンプルからコピペしてちょっと書き換えただけなので
意味はわかっていない(悲)


Delegate Sub setTextCallback(ByRef ctrlObj As Control, ByVal value As String)
  '''
  '''フォームコントロールにテキストをセットする(デリゲート対応版)
  '''
  Private Sub setText(ByRef ctrlObj As Control, ByVal value As String)
    If ctrlObj.InvokeRequired Then
      Dim d As New setTextCallback(AddressOf setText)
      Me.Invoke(d, New Object() {ctrlObj, value})
    Else
      ctrlObj.Text = value
    End If
  End Sub

0 件のコメント:

コメントを投稿

デル株式会社

最近人気の投稿