RThresholdの場合分けをするには?

解決


モルトー山岡  2004-02-05 18:09:25  No: 111687  IP: [192.*.*.*]

こんばんは。
RThresholdを使うと、oncommイベントが発生します。
この度一つのシリアル回線で、1バイトと2バイトについて、
場合分けで受信したいと思っておりますが、可能なのでしょうか?

試しに、RThreshold=1に指定し、
oncomm内で、if  inbufferCount=1の時と2の時で場合分けしてみたのですが、
全く効果なしでした。

何か秘策をお持ちの方がおりましたら、よろしくお願いします。

編集 削除
ももんが  2004-02-06 22:22:03  No: 111688  IP: [192.*.*.*]

1バイトとか2バイトだけしか受信しないというのはどのような場合が
あるのでしょうか?
必要以上にデータを受信したくない場合、RS/CSなどのフロー制御を入れれ
ば受信側から送信側に通知することもできますが、送信側がこういった信号
を監視していなければデータの受信は止めることはできません。

常に2バイト受信すると仮定して、1バイトの時は2バイト目を捨てる
(無視する)というのなら可能だと思います。

編集 削除
岡田 之仁  2004-02-07 07:39:26  No: 111689  IP: [192.*.*.*]

最近、RS-232Cの通信の話題が多いですが・・・

今回のケースは、あくまで1バイトづつ取り込んで、それを、
一旦、バッファ(文字列)変数に蓄積し、その先頭から1バイ
トづつ切り出して、これは1バイトのデータ、これは2バイト
のデータ・・・と言う具合に判断していくしか無いはずです。

実際、プログラム書く側は、そのデータの素性が、1バイト系
データか、2バイト系データか知っているわけですから、その
非同期・同期化のバッファリングとデータ切り出し部分での、
本来のプログラミングと言うか、アルゴリズムの作成が醍醐味
のはずです。

おおまかに・・・

Option Explicit

' 通信用受信バッファ
Private gBuffer As String

Private Sub Form_Load()

    ' バッファクリア
    gBuffer = ""

    ' RS=232C初期化・オープン
    MSComm1.CommPort = 1
    MSComm1.Handshaking = comRTS
    MSComm1.InputMode = comInputModeBinary
    MSComm1.Settings = "9600,n,8,1"
    MSComm1.RThreshold = 1
    MSComm1.SThreshold = 1
    
    MSComm1.PortOpen = True
    
    ' RTSの制御有りでオープンしているので
    ' 一応、制御信号をON
    MSComm1.DTREnable = True
    MSComm1.RTSEnable = True

End Sub

Private Sub Form_Unload(Cancel As Integer)

    ' 制御信号をOFF
    MSComm1.DTREnable = False
    MSComm1.RTSEnable = False
    ' RS-232Cクローズ
    MSComm1.PortOpen = False
    
End Sub

Private Sub MSComm1_OnComm()

    Dim sz As String
    
    ' 受信イベントを判定
    If (MSComm1.CommEvent And comEvReceive) <> 0 Then
        ' 受信データの存在を確認
        If MSComm1.InBufferCount > 0 Then
            ' 受信バッファのデータ数分を取得対象とする
            MSComm1.InputLen = MSComm1.InBufferCount
            ' 受信
            sz = MSComm1.Input
            ' バッファに蓄積
            ' UNICODE系の場合、データ変換を追加しないと
            ' 正しいデータにならない・・・要注意
            gBuffer = gBuffer & sz
        End If
    End If

    ' データ判定・処理
    Call CheckData
    
End Sub

Private Sub CheckData()

    Dim sz As String
    
    ' バッファにデータがあるか判定
    If Len(gBuffer) = 0 Then
        ' 無ければ終了
        Exit Sub
    End If
    
    ' バッファにデータが無くなるまで処理
    While Len(gBuffer) > 0
        ' まずバッファから1バイト切り出し
        sz = Left$(gBuffer, 1)
        ' データの判別:1バイト系か2バイト系か?
        ' 単純な判断ですが、最終的にはもっと複雑になる
        ' はずですが・・・
        If sz = xxx Then
            ' 1バイト系データ処理
            ' (ここに、1バイト系データ処理を書く)
        
            ' 処理済みのデータを、バッファから削除
            gBuffer = Right$(gBuffer, Len(gBuffer) - 1)
        Else
            ' 取得済みのデータを、バッファから削除
            gBuffer = Right$(gBuffer, Len(gBuffer) - 1)
            ' 2バイト目データ取得
            sz = sz & Left$(gBuffer, 1)
            ' 2バイト系データ処理
            ' (ここに、2バイト系データ処理を書く)
            
            ' 処理済みのデータを、バッファから削除
            gBuffer = Right$(gBuffer, Len(gBuffer) - 1)
        End If
    Wend
    
End Sub

※  あくまでアルゴリズムですから・・・
    参考までに・・・

以上。

編集 削除
モルトー山岡  2004-02-10 01:52:35  No: 111690  IP: [192.*.*.*]

ももんがさん、岡田 之仁さん、情報ありがとうございます。
(特に岡田さんには丁寧に書いていただきまして、恐縮です)。


計測器から1バイトの時と、2バイトのデータを取り出したいと思ってました。
1バイトずつ振り分けるというヒントをいただきまして、無事動作することが出来ました。

助けていただいて大変助かりました。
まだ未熟者でして、いずれ情報お返しできるように精進いたします。

ありがとうございました。

編集 削除
岡田 之仁  2004-02-10 08:46:15  No: 111691  IP: [192.*.*.*]

アルゴリズムを簡単の表現する意味でソースを掲載しましたが、
この状態では、まれにバグと言うか、問題が出ます。

2バイト系データの1バイト目を受信した折に、たまたまイベン
トが間に合い、OnComm処理が開始されてしまった場合、2バイト
目を受信していないので、データの切れ目の処理が無い為、ある
はずの2バイト目が無い為、おかしなことになります。

2バイト目を1バイトとして受信した場合、つじつまが合わなく
なりますので、2バイト系データの処理部分に、2バイト目が無
い場合の処理と、1バイト系データの処理部分に、2バイト系の
2バイト目のデータを、1バイト系として受け取ってしまった場
合の処理を追加しないと・・・折角受信したのに、読みほかして
しまうようなことが発生します。

非常にマレなことですが、あり得ますので・・・

以上。

編集 削除