MSCommの通信エラーをクリアするには?

解決


おじさん  2003-04-08 07:48:18  No: 106587

MSCommで通信中にエラーが発生した場合、CommEventで内容表示後再度送受信を行いたいのですがその後も同じエラーとなってしまいます。
送受信データを見ると実際の送受信は正常に行われています。
エラーをクリアする方法はないでしょうか。


ととろジョージ  2003-04-09 20:02:51  No: 106588

こんにちは

>送受信データを見ると実際の送受信は正常に行われています。
通信は正常なのになぜErrなんでしょうね

どんなErrなんでしょうか?
たしかCommEventにはいくつかのErrがあったと想いますが
通信速度とか  どんなDataなのか気になります。
どのような処理をされてるのか簡単にコードを公開してみては
いかがですか?


おじさん  2003-04-15 03:11:29  No: 106589

ととろジョージさん、書き込みありがとうございます。
長期外出をしており書き込みが遅くなったことをお詫びします。
コードは以下のようにしています。
コマンドに対する返信は2種類あります。仮に返信Aと返信Bとします。
Aは20byte、Bは2000byteでテキストデータです。
ボーレートは57600bpsです。
エラー対処のチェックをするため、InBufferSize=512とし、
わざとオーバーフローが起こるようにしています。
まずAを受信します。(エラーは起こりません)
次にBを受信します。(オーバーフローとなります)
次に再度Aを受信します。
CommEventはオーバーフローとなっていますが受信データは正常です。
InBufferCountも正常です。

'--- シリアル受信 データを終わりまで受信する---
Public Sub Sr_Rcv()
    Err_Mes = ""
    Rcv_Cnt = 0   '受信データカウント
    Recv_Buf = ""
    Main_Form.Timer1.Enabled = True '制限時間
    Timer_Flag = False
    i = 0

RCV_LOOP:
    Do  'CR待ちループ
        If Main_Form.MSComm.InBufferCount > 0 Or Recv_Buf <> "" Then
            Recv_Wrk = Main_Form.MSComm.Input
            Recv_Buf = Recv_Buf & Recv_Wrk
            i = InStr(Recv_Buf, vbCr)
            'Debug.Print Recv_Buf, i
            If i > 0 Then
                Exit Do
            End If
        End If
      
        If Timer_Flag = True Then
            Timer_Flag = False
            Err_Mes = "タイムアウト"
            Exit Sub
        End If
        
        If Main_Form.MSComm.CommEvent > 1000 And Main_Form.MSComm.CommEvent < 1012 Then  '通信エラー
            Exit Do
        End If
        
        DoEvents
    Loop
    'CRあり
    Main_Form.Timer1.Enabled = False
    If Main_Form.MSComm.CommEvent = comRxOver Then
        Err_Mes = "バッファオーバーフロー"
            MsgBox Err_Mes, vbCritical, "エラー表示"
            MsgBox i & "," & Main_Form.MSComm.InBufferCount & ";" & vbCrLf & Recv_Buf  'チェック用
     Do  '受信内容チェック
            Recv_Wrk = Main_Form.MSComm.Input
            Recv_Buf = Recv_Buf & Recv_Wrk
            If Recv_Wrk = "" Then
                Exit Do
            End If
            DoEvents
        Loop
      MsgBox Recv_Buf  '受信内容
        'Exit Sub
    ElseIf Main_Form.MSComm.CommEvent > 1000 And Main_Form.MSComm.CommEvent < 1012 Then  '通信エラー
        Err_Mes = "通信エラーです" & vbCrLf & "エラー番号: " & Main_Form.MSComm.CommEvent
            MsgBox Err_Mes, vbCritical, "エラー表示"
        Exit Sub
    End If
    
    If i > 0 Then
        Rcvdat(Rcv_Cnt) = Left$(Recv_Buf, i - 1)
        Recv_Buf = Right$(Recv_Buf, Len(Recv_Buf) - i)
    End If
    MsgBox Recv_Buf
    
    If InStr(Rcvdat(Rcv_Cnt), DEF_END) > 0 Then     '"END"で受信を終わる
        Exit Sub
    End If
    
    Rcv_Cnt = Rcv_Cnt + 1
    If Err_Mes = "" Then
        GoTo RCV_LOOP   '受信ループになる
    End If
End Sub


猫八  2003-04-15 14:00:02  No: 106590

取りあえず下記の2行追加かな。

Do '受信内容チェック
    Recv_Wrk = Main_Form.MSComm.Input
    Recv_Buf = Recv_Buf & Recv_Wrk
    If Recv_Wrk = "" Then
        Exit Do
    Else                      <=追加
        Err_Msg=""            <=追加
    End If
    DoEvents
Loop

PS.5年ぶりにGotoをみたけど....。


おじさん  2003-04-15 20:17:15  No: 106591

補足します。
上には受信のコードのみ載せましたが、
Aの受信の前にはAの要求コマンドを送信します。
Bの受信の前にはBの要求コマンドを送信します。
そこで、Main_Form.MSComm.InBufferCount = 0
としていますが、CommEventはクリアされません。
ちなみに、送信前に
Main_Form.MSComm.PortOpen = False
一度ポートを閉じ、
Main_Form.MSComm.PortOpen = True
再度オープンしても、CommEventはクリアされません。


猫八  2003-04-15 23:54:28  No: 106592

仕様を誤解していたようなので上の修正は却下で。

>Main_Form.MSComm.InBufferCount = 0
または
>Main_Form.MSComm.PortOpen = False
を実行した時点で受信バッファはクリアされるので、その後で何らかの
エラーが発生しているのではないでしょうか。


おじさん  2003-04-16 18:58:29  No: 106593

Main_Form.MSComm.InBufferCount = 0
としていますので
送信前にInBufferCountを読み込むと当然0です。
CommEventを読み込むと1008(オーバーフロー)のままです。
そのまま送信、受信すると、CommEventは1008のまま。
しかし受信データは正しいのです。
なぜなんでしょう。
VBでは対応できないシステムの問題か、ハード的な問題なんでしょうかね。


猫八  2003-04-16 22:58:33  No: 106594

RS-232Cのデータを監視するモニタ装置があればもう少し調べられるのに..。(^^;)
受信データを信じるなら確かにシステムの問題かもしれませんね。
逆にエラーを信じるなら、プロトコルの設定ミスの可能性もあります。

念のため、送信側/受信側共に通信プロトコルを確認してみてください。
それと、通信ケーブルのフローで使っているラインが切れている可能性も
あります。


おじさん  2003-04-17 06:42:49  No: 106595

相手側は私自身でプログラムしたマイコンなんです。
送受信の内容は私が作ってますしデータ内容は間違いないと思います。
(マイコンが送ったとおりにPC側は受信しています。)
ハンドシェイクは使用していません。
煮詰まってきました。


猫八  2003-04-17 07:55:28  No: 106596

>ハンドシェイクは使用していません。
ハンドシェイクをしていない場合は、オーバーフローエラーを無視して
良いと思います。
それは、フロー制御をしていなければオーバーフローが発生した場合に
送信側でデータの送信を止めることができないことと、
内部でのエラーからの復旧処理が行われない可能性があります。(Win-MSComm間)  
対策としては、ハンドシェイクを有効にするか、あるいはCommEventの
1008はエラー判定から外すことで解決しそうな気がします。


おじさん  2003-04-17 20:19:30  No: 106597

受信データが足りなければ再送すればいいわけですから
1008は無視でもOKです。
ただ、他のエラーでも同様なのです。
7bitデータで受信しているところで、1回だけ8bitデータを受信させると
フレーミングエラー(1004)になります。
その後、7bitデータを受信しても1004はそのままです。


猫八  2003-04-18 06:55:27  No: 106598

もしかすると、RThresholdが0になっていませんか?
RThresholdの値が0になっているとデータを正常に受信してもCommEventの値
は変化しないそうです。
正確には、エラーは設定されるがCommEventの値がcomEvReceive は設定されない。
それとCommEventの値が変化しなければOnCommイベントも発生しないようです。
参照:MSDN→OnComm イベント
RThreshold=1とするだけでCommEventが更新しそうな気がします。


Loreley  2003-04-18 12:28:53  No: 106599

送信側もプログラムであれば
受信側のデータを全部取得した後、
送信側を閉じて開けるという手もいいかもしれません。


おじさん  2003-04-18 19:40:58  No: 106600

RThreshold=0だとcomEvReceiveは設定されない。・・そうですよね。
RThreshold=0、SThreshold=0、としていました。
comEvReceiveもcomEvSendも使っていなかったもので。
気が付きました。CommEventは最後のEventを保持するんですよね。
エラーのあとにEventがなければエラーのままなんです。
comEvReceiveやcomEvSendを発生させればエラーはクリアされます。
そこでもしまたエラーならエラー値になるんです。
うまくいきました。
RThresholdを設定するとオーバーフローが検出できないようなので
SThresholdを設定しました。
エラーのあとの送信でcomEvSendが立って送受信がエラー無くできました。
書き込みしてくださったみなさんありがとうございました。
中でも、昼夜を問わず考えていただきました猫八さん、感謝いたします。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加