みんなの「教えて(疑問・質問)」にみんなで「答える」Q&Aコミュニティ

こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

解決済みの質問

ClearCommError呼び出し時のCE_OVERRUN対処策

お世話になります。
現在C++にてシリアル受信プログラムを作成しており、その中でClearCommError()を呼び出して、ポートに準備されているデータサイズを取得しようと思っているのですが、たまにClearCommErrorにてCE_OVERRUNが発生し、受信できないときがあります。
このCE_OVERRUNの対処策として考えられることは何かありませんでしょうか?
対応として、わたくしなりには以下のような処理をしてみましたがうまくいきませんでした。
・ClearCommErrorをもう一度呼び出し、エラーをクリアし、再度受信処理をする → 次の受信処理で同じようにCE_OVERRUNが発生する
・一度に受信するデータサイズを小さくしてみたが、同じようにたまにCE_OVERRUNが発生する
・CE_OVERRUNが発生するのはシリアル受信しながら別の処理をしているときに必ず発生する

CE_OVERRUNが発生した場合にはもうどうすることも出来ないのでしょうか?このエラーの対応策や、回避策をご存じの方がいらっしゃいましたら
ご助言頂ければと思っております。

よろしくお願い致します。環境はVisual Studio 2005 のC++です。

投稿日時 - 2010-02-14 13:35:44

QNo.5675691

すぐに回答ほしいです

質問者が選んだベストアンサー

書いてある受信部のプログラムをスレッドなどで実行してますか?
スレッド化していないのであればオーバラン出る可能性は高いでしょう
(特に相手側がデータ垂れ流しにしてる場合)

>シリアル通信でのフロー制御を実装したことがないのですが、これは
>DCBのfOutxCtsFlowやfOutxDsrFlowをtrueにするだけでよいのでしょうか?

RTS/CTS制御の時にはそれでいいはずです

>それともハード的に変更しなければならないのでしょうか?

一口にフロー制御といっても手法が2種類あります
1.XON/XOFF データ送受信による制御
2.RTS/CTS 信号ラインによる制御
3.1と2両方使用

使ってる通信のデータ内容によっては1は使えないこともあります
(送受信データにXON/XOFFキャラクターが含まれる場合)
が既に通信できているならならハード的な変更は不要です

2・3を行う場合配線がちゃんと行われてる必要があります
(特に自作で手抜きの折り返しケーブル使っている場合は注意)

相手が何でどのような通信データのやり取りなのかも不明なのですが
本当に垂れ流しデータなのでしょうか?
(何らかのコマンドの応答が帰ってきてるだけなら送信側処理を見直すべきです)

後、当たり前ですが相手側がフロー制御対応してる必要があります
(自分の方だけがやればいいって話ではありません)
使ってる機器に合わせてください
(通信相手側の情報が無いので其処は私には分かりません)

投稿日時 - 2010-02-15 17:32:19

お礼

>書いてある受信部のプログラムをスレッドなどで実行してますか?
>スレッド化していないのであればオーバラン出る可能性は高いでしょう
>(特に相手側がデータ垂れ流しにしてる場合)
受信処理は別スレッドで呼び出しております。逆に、別スレッドにしないで呼び出したほうがオーバーランエラーは発生しないようです。

>相手が何でどのような通信データのやり取りなのかも不明なのですが
>本当に垂れ流しデータなのでしょうか?
>(何らかのコマンドの応答が帰ってきてるだけなら送信側処理を見直
>すべきです)
データは、こちら側から相手側へ要求コマンドを送ってから、相手側からデータを受けるといった形です。

>後、当たり前ですが相手側がフロー制御対応してる必要があります
>(自分の方だけがやればいいって話ではありません)
>使ってる機器に合わせてください
>(通信相手側の情報が無いので其処は私には分かりません)
やはりそうですよね。相手側の仕様変更変更や、配線の変更等も必要となってくるわけですね。
相手側とその点を確認して、仕様について考えたいと思います。
参考となるご意見大変ありがとうございました。

投稿日時 - 2010-02-18 10:44:14

ANo.2

このQ&Aは役に立ちましたか?

4人が「このQ&Aが役に立った」と投票しています

回答(2)

ANo.1

どのような受信処理を書いているのか分かりませんが
受信データがあるのに受信しないからオーバランが発生するという原理はお分かりでしょうか?
(送信側は受信側のことを気にせずデータを送り続けている)

対処するためには2種類の方法しかありません
・フロー制御を行う
・通信速度を下げる
どちらかとなります

根本の受信処理のつくりが悪いだけって可能性もあります

投稿日時 - 2010-02-14 15:35:50

お礼

koi1234様、ご回答ありがとうございます。
受信処理のプログラム記載していなかった為、分かりづらくなってしまい申し訳ございません。
受信処理としては以下のようになっております。
シリアルポートの設定
//シリアルポートの設定
DCB dcb;
GetCommState(m_hComm,&dcb);
dcb.BaudRate = 38400;
dcb.ByteSize = 8;
dcb.Parity = false;
dcb.StopBits = ONESTOPBIT;
dcb.fOutxCtsFlow = false;
dcb.fOutxDsrFlow = false;
dcb.fDsrSensitivity = false;
SetCommState(m_hComm,&dcb);

//シリアル受信処理
unsigned char recv[512];
unsigned char recv_data[512];
DWORD dwCount;
DWORD dwRead;
DWORD dwErrors;
CMSTAT ComStat;
int count = 0;
while(1){
if(要求バイト分受信出来れば)
break;
ClearCommError(m_hComm,&dwErrors,&ComStat);
dwCount = ComStat.cbInQue;
if(dwCount == 0){
Sleep(10);
continue;
}
::ReadFile(m_hComm,recv,dwCount,&dwRead,NULL);
if(dwRead == 0){
Sleep(10);
continue;
}
for(int i=0 ; i<dwRead ; i++){
recv_data[count++] = recv[i];
}
}

のような処理となっております。このなかのClearCommErrorでの
dwErrorsにCE_OVERRRUNが発生し、受信エラーとなります。

教えて頂いた対処のほうのなかで、通信速度については決定している
ため、フロー制御をしてみようかなと思っております。
シリアル通信でのフロー制御を実装したことがないのですが、これは
DCBのfOutxCtsFlowやfOutxDsrFlowをtrueにするだけでよいのでしょうか?
それともハード的に変更しなければならないのでしょうか?

投稿日時 - 2010-02-15 09:10:37

あなたにオススメの質問