MSCommで通信中にエラーが発生した場合、CommEventで内容表示後再度送受信を行いたいのですがその後も同じエラーとなってしまいます。
送受信データを見ると実際の送受信は正常に行われています。
エラーをクリアする方法はないでしょうか。
こんにちは
>送受信データを見ると実際の送受信は正常に行われています。
通信は正常なのになぜErrなんでしょうね
どんなErrなんでしょうか?
たしかCommEventにはいくつかのErrがあったと想いますが
通信速度とか どんなDataなのか気になります。
どのような処理をされてるのか簡単にコードを公開してみては
いかがですか?
ととろジョージさん、書き込みありがとうございます。
長期外出をしており書き込みが遅くなったことをお詫びします。
コードは以下のようにしています。
コマンドに対する返信は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
取りあえず下記の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をみたけど....。
補足します。
上には受信のコードのみ載せましたが、
Aの受信の前にはAの要求コマンドを送信します。
Bの受信の前にはBの要求コマンドを送信します。
そこで、Main_Form.MSComm.InBufferCount = 0
としていますが、CommEventはクリアされません。
ちなみに、送信前に
Main_Form.MSComm.PortOpen = False
一度ポートを閉じ、
Main_Form.MSComm.PortOpen = True
再度オープンしても、CommEventはクリアされません。
仕様を誤解していたようなので上の修正は却下で。
>Main_Form.MSComm.InBufferCount = 0
または
>Main_Form.MSComm.PortOpen = False
を実行した時点で受信バッファはクリアされるので、その後で何らかの
エラーが発生しているのではないでしょうか。
Main_Form.MSComm.InBufferCount = 0
としていますので
送信前にInBufferCountを読み込むと当然0です。
CommEventを読み込むと1008(オーバーフロー)のままです。
そのまま送信、受信すると、CommEventは1008のまま。
しかし受信データは正しいのです。
なぜなんでしょう。
VBでは対応できないシステムの問題か、ハード的な問題なんでしょうかね。
RS-232Cのデータを監視するモニタ装置があればもう少し調べられるのに..。(^^;)
受信データを信じるなら確かにシステムの問題かもしれませんね。
逆にエラーを信じるなら、プロトコルの設定ミスの可能性もあります。
念のため、送信側/受信側共に通信プロトコルを確認してみてください。
それと、通信ケーブルのフローで使っているラインが切れている可能性も
あります。
相手側は私自身でプログラムしたマイコンなんです。
送受信の内容は私が作ってますしデータ内容は間違いないと思います。
(マイコンが送ったとおりにPC側は受信しています。)
ハンドシェイクは使用していません。
煮詰まってきました。
>ハンドシェイクは使用していません。
ハンドシェイクをしていない場合は、オーバーフローエラーを無視して
良いと思います。
それは、フロー制御をしていなければオーバーフローが発生した場合に
送信側でデータの送信を止めることができないことと、
内部でのエラーからの復旧処理が行われない可能性があります。(Win-MSComm間)
対策としては、ハンドシェイクを有効にするか、あるいはCommEventの
1008はエラー判定から外すことで解決しそうな気がします。
受信データが足りなければ再送すればいいわけですから
1008は無視でもOKです。
ただ、他のエラーでも同様なのです。
7bitデータで受信しているところで、1回だけ8bitデータを受信させると
フレーミングエラー(1004)になります。
その後、7bitデータを受信しても1004はそのままです。
もしかすると、RThresholdが0になっていませんか?
RThresholdの値が0になっているとデータを正常に受信してもCommEventの値
は変化しないそうです。
正確には、エラーは設定されるがCommEventの値がcomEvReceive は設定されない。
それとCommEventの値が変化しなければOnCommイベントも発生しないようです。
参照:MSDN→OnComm イベント
RThreshold=1とするだけでCommEventが更新しそうな気がします。
送信側もプログラムであれば
受信側のデータを全部取得した後、
送信側を閉じて開けるという手もいいかもしれません。
RThreshold=0だとcomEvReceiveは設定されない。・・そうですよね。
RThreshold=0、SThreshold=0、としていました。
comEvReceiveもcomEvSendも使っていなかったもので。
気が付きました。CommEventは最後のEventを保持するんですよね。
エラーのあとにEventがなければエラーのままなんです。
comEvReceiveやcomEvSendを発生させればエラーはクリアされます。
そこでもしまたエラーならエラー値になるんです。
うまくいきました。
RThresholdを設定するとオーバーフローが検出できないようなので
SThresholdを設定しました。
エラーのあとの送信でcomEvSendが立って送受信がエラー無くできました。
書き込みしてくださったみなさんありがとうございました。
中でも、昼夜を問わず考えていただきました猫八さん、感謝いたします。
ツイート | ![]() |