以下の受信処理と送信処理でRS-232Cの通信を行っています。
送信側でRTS信号をアクティブにしたタイミングで、受信側のCTSのイベントが
アクティブになり、WaitForMultipleObjectsから抜けて来ると思っています。
しかし、実際にステップ実行していくと、送信処理のRTSを非アクティブに
するところで、WaitForMultipleObjectsから抜けて来きます。
そのため、送信側でRTSをONにしたあと、送信側でCTSのONを待って
実際の送信処理を行わなければならないのに、CTSのONを待たずに、WriteFileを
行ってしまいます。
上記について理由がわかる方、ご教授願います。
開発環境は、
Windows2000
VC++6.0
MFC
です。
// ★受信処理
// イベント設定
::SetCommMask(mPort,EV_CTS|EV_ERR); // 回線エラーとCTSを設定
// 受信イベント待ち
bool bRes = true;
DWORD dwCommEvent = 0;
if ( !::WaitCommEvent(mPort,&dwCommEvent,&ovlp) )
{
// イベント待ち
HANDLE hObj[] = { ovlp.hEvent };
switch( ::WaitForMultipleObjects(1,hObj,false,INFINITE) )
{
case WAIT_OBJECT_0: // 受信イベント
break;
}
}
if( bRes && (dwCommEvent&EV_CTS) )
{
// RTS(送信要求:request-to-send)をアクティブにする
EscapeCommFunction(mPort, SETRTS);
DWORD dwError = 0;
COMSTAT Stat;
::ClearCommError(mPort,&dwError,&Stat);
while( bRes && Stat.cbInQue > nRecvSize )
{
// 受信データを取得
DWORD dwTrans = 0;
if ( ::ReadFile(mPort,pBuff,nSize,&dwTrans,&mOvlpRecv) )
{
nRecvSize += dwTrans;
}
else
{
// オーバーラップ非同期処理(省略)
}
}
// RTS(送信要求:request-to-send)を非アクティブにする
EscapeCommFunction(mPort, CLRRTS);
}
// ★送信処理
// RTS(送信要求:request-to-send)をアクティブにする
EscapeCommFunction(mPort, SETRTS);
// イベント設定
::SetCommMask(mPort,EV_CTS|EV_ERR);
// 受信イベント待ち
DWORD nRecvSize = 0;
DWORD dwCommEvent = 0;
bool bRes = WaitCommEvent(mOvlpRecv);
if ( bRes )
{
bool bRes = true;
DWORD dwTrans = 0;
if ( !::WriteFile(mPort,pBuff,nSize,&dwTrans,&mOvlpSend) )
{
// オーバーラップ非同期処理(省略)
}
}
// RTS(送信要求:request-to-send)を非アクティブにする
EscapeCommFunction(mPort, CLRRTS);
次の質問します。
1.相手側機器は何ですか?
相手にあったケーブルを使っていますか?
相手がモデムの場合RTC-CTSの制御だけでは駄目かも知れません。
2.ヘルプをみると、EV_CTSは、「CTS( 送信可)信号の状態が変わったとき。」
となってます。
RTSの切り替えはうまくいてますか?
あと提案です。
動作がおかしいときは、WaitForMultipleObjectsのオプションで「INFINITE」
にしないほうがいいです。
1000mSなど数値で行い、抜けたときにタイムアウトかどうか判定したほうが
いいです。
それは、WaitForSingleObjectsの時も同じです。
> 1.相手側機器は何ですか?
> 相手にあったケーブルを使っていますか?
> 相手がモデムの場合RTC-CTSの制御だけでは駄目かも知れません。
相手はPCです。
> 2.ヘルプをみると、EV_CTSは、「CTS( 送信可)信号の状態が変わったとき。」
> となってます。
> RTSの切り替えはうまくいてますか?
RTSの切り替えは、 EscapeCommFunction(mPort, CLRRTS);を行ったときに、
イベントが発生しているので、「CTSの状態が変わったとき。」というのは、
間違っていません。ただし、EscapeCommFunction(mPort, SETRTS);では、
イベントが発生しません。
イベント発生のONとOFFが逆になっている??
・RTSの初期状態を確認していますか?
もともとONなら、ONにしても変化しないため、イベントも発生しないでしょう。
・イベント後CTSの状態を確認していますか?
変化を検出するため、OFF→ONでもON→OFFでもイベントが発生します。
ちゃんと同期を取るなら、どちらに変化したか、確認しましょう。
1. テスター、オシロスコープ等が用意できれば実際にRTS/CTS信号を
調べてみるのもいいかも知れません。
リスト上で分らなくて、実際に信号を見てみると分ることもあります。
2. ケ-ブルは、(リバース・クロス)ですよね。
自信がない時は、自作はしないほうがいいです。(手違いが良くある)
3. USB-232C変換ケーブルを使っている場合、ケ-ブルによっては、
CTS/RTS制御が有効でない可能性があります。
確かめたほうがいいです。
いろいろなアドバイスありがとうございます。
>REEさま
>・RTSの初期状態を確認していますか?
> もともとONなら、ONにしても変化しないため、イベントも発生しないでしょう。
初期状態は、RTS、CTSともにOFF状態になっています。
>・イベント後CTSの状態を確認していますか?
> 変化を検出するため、OFF→ONでもON→OFFでもイベントが発生します。
> ちゃんと同期を取るなら、どちらに変化したか、確認しましょう。
どちらに変化したか確認するようにします。アドバイスありがとうございます。
>ITOさま
参考になる意見をありがとうございます。
>. テスター、オシロスコープ等が用意できれば実際にRTS/CTS信号を
> 調べてみるのもいいかも知れません。
> リスト上で分らなくて、実際に信号を見てみると分ることもあります。
オシロ等は、用意できないので調べることができません。
PC上でシリアルのピンの状態をモニタできるツールでよいものがあれば、
紹介していただけないでしょうか?
ただし、時系列でモニタできるオシロスコープのようなものがいいです。
>2. ケ-ブルは、(リバース・クロス)ですよね。
> 自信がない時は、自作はしないほうがいいです。(手違いが良くある)
クロスケーブルでRTSとCTSがつながっています。
>3. USB-232C変換ケーブルを使っている場合、ケ-ブルによっては、
> CTS/RTS制御が有効でない可能性があります。
> 確かめたほうがいいです。
USBシリアルケーブル(USB-D-SUB9ピン変換ケーブル)を使っていたら、
CTS、RTSの信号の変化検出すらしませんでした。
CTSのイベントすら発生しませんでした。
なので、PCに標準でついているシリアルのコネクタに
接続してやると、CTS、RTSの信号制御が可能になりました。
これで、CTSのイベントが発生するようになりました。
USBシリアルケーブル(USB-D-SUB9ピン変換ケーブル)は、CTSと
RTSの信号制御ラインが有効でないようです。
ただ、今回は、RTSをONにしたときは、CTSのイベントが発生せずに、
RTSをOFFにしたときに、CTSのイベントが発生してしまいます。
>オシロ等は、用意できないので調べることができません。
>PC上でシリアルのピンの状態をモニタできるツールでよいものがあれば、
>紹介していただけないでしょうか?
>ただし、時系列でモニタできるオシロスコープのようなものがいいです。
RS-232Cラインモニターというのがあります。
僕が知っているメーカは、ビッツとかWaveEyEです。
ソフトをステップで走らせながらテスターで電圧レベルを見て確認していく
方法もあると思います。
>ただ、今回は、RTSをONにしたときは、CTSのイベントが発生せずに、
>RTSをOFFにしたときに、CTSのイベントが発生してしまいます。
一度、「WaitCommEvent」をやめて、
「GetCommModemStatus」で CTSの状態をチェックする方法もありますね。
ありがとうございます。ITOさん。
やってみます。