- ベストアンサー
RS232C通信のタイムアウトが機能しない理由とAPIの挙動について
- RS232C通信においてタイムアウトが機能しない原因を教えてください。
- また、タイムアウトが働くとAPIはどのような挙動を示すのでしょうか。
- お願いします。
- みんなの回答 (5)
- 専門家の回答
質問者が選んだベストアンサー
ANo.4の補足です: (API関数の)ReadFile()を「1バイト読取り」で使っている場合、タイムアウトで戻ってくるときは「読取ったバイト数」の値はゼロであるはずです。 それ以前に(タイムアウト以前に)、読み取った文字数は関係ありません(1バイト毎に戻ってきていますから)。 タイムアウトによる ReadFile() の戻りはエラーではない(と思います)ので、戻り値はTRUEだと思います(このことは実体験していないので断言できませんが)。 この戻り値によって、タイムアウトか回線等のエラーか判定できると思います。 回線等のエラーは、ClearCommError() 関数を使って知ることが出来ます。 DWORD は 32-bit unsigned integer です。 unsigned integer のサイズはシステムによって異なります。 (32ビットシステムでは32ビット、16ビットシステムでは16ビット。) ご使用のシステムは、32ビットでしょうから、そのままか、あるいは unsigned int に型キャストして、 sprintf()であれば、書式制御文字列として "%u" を用いて、文字列に変換できます。
その他の回答 (4)
- kb-nike
- ベストアンサー率36% (72/200)
ANo2 の補足です。 「DLしてきたクラス」の内容が分かりませんので的を外しているかもしれませんが: そのクラスの中で、ReadFile()をどのように呼び出しているのかが分かりませんので、 実験として、とりあえず設定はそのクラスを使って行い、 可能であれば、読込について、直接(API/SDKの)ReadFile()を使って確認されては如何でしょうか。
お礼
お返事ありがとうございます。クラスの関数の中味は、ただのReadFileAPIなんだけどなと思いつつも、見直してみて原因が分かりました。クラスの関数内で、実際に読み込んだ文字数が0で無くなるまで、ReadFileを繰り返すループになっていましたので、TimeOutが働いてReadFileの次のステップに進んでも、再びReadFileを繰り返す無限ループに陥っていたのでした。アドバイスありがとうございました。 ここで教えていただきたいのですが、1文を読み込む方の事例で、TimeOutが働いてReadFileを抜けた事を判定するにはどうしたら良いのでしょうか。実際に読み込んだ文字列の長さを調べると、0が得られましたが、これは再現性があるのでしょうか。(このとき、TimeOut前に、8文字位は読み込んでいるはずです) もう一つ素人の質問で申し訳ありませんが、構造体に設定しているDWORD型の変数の中味をMessageBox等で簡単に調べるにはどうしたら良いのでしょうか。さっぱり分からないので、floatにキャストしてから、sprintfで文字列に変換しておりますが、もっと普通の方法がありそうに思います。 以上、よろしくお願いいたします。
- Interest
- ベストアンサー率31% (207/659)
ANo.1 = Interst です。 > 考えてみるとFramework2って、XP機では元々入っていないんですね。 > 実行ファイルだけのコピーで使えるものを作りたいのです。 私なら、.NET Framework 2.0 が信頼できる筋(=Microsoft)から無償提供されているのですから「入ってないなら入れれば良い」と考えますが、それでは何か不都合があるのでしょうか? 以前、私もC++で作ろうと思ったときにサンプルになりそうなコードがネット上にあるかどうか調べてみて http://www.codeproject.com/system/serial.asp http://www.lvr.com/serport.htm などを見つけましたが、最終的には「.NET Framework 2.0で提供されているSerialPortを使ったほうが確実に動くプログラムを早く作れる」という結論に達しました。
お礼
情報ありがとうございます。 どこかのサイトに、シリアル通信をするのは簡単だが、多くの環境で動作するものを作るのは大変だとありましたが、その通りなのでしょう。中味は良く理解できていませんが、フロー制御も色々種類がある様ですし。しかし、今回PCと通信する相手は、自作で、TXD,RXDとGNDの3本線で通信できてしまう代物で、多くて20文字程度のコマンドとレスポンスの通信だけを考えていますので、なんとかなるのではないかと思っています。ついでにc++を習得しようというのですから、遠回りは承知の上です。 c++でやってみて、こんなところがうまくいかなかった、苦労したというところがあれば、教えていただけると幸いです。
- kb-nike
- ベストアンサー率36% (72/200)
ご質問の趣旨から外れていれば、お読み捨てください。 ・タイムアウトが働くと、APIはどのような挙動をしめすのか: ReadIntervalTimeout と ReadTotalTimeoutMultiplier が MAXDWORD、 かつ ReadTotalTimeoutConstant が ゼロより大~MAXDWORDより小、 の時、 入力バッファーが空であれば、ReadFile関数は待機し、 ○1文字(character)が到着すると直ちに戻る。 ○ ReadTotalTimeoutConstantで指定された時間内に文字が到着しない場合はReadFile関数はTimeoutする。 ReadTotalTimeoutMultiplier と ReadTotalTimeoutConstant がゼロの時、 読み取りに対して、totaltimeout は使われない。 これらのパラメータの設定・読み出しは、SetCommTimeouts・GetCommTimeouts関数でできます。 詳細は、COMMTIMEOUT構造体(Patform SDK)の解説を参照してください。
お礼
アドバイスをありがとうございます。 いろいろと検証していて、返答が遅れて申し訳ありません。非同期通信なので、WriteFileの方は送り放しで完了してしまい、PIC(制御用マイコン)から返事が無いので、最初のReadFileで1文字読み込む所でずっと待っている事が分かりました(考えてみれば当たり前ですが)。ご紹介いただいたサイトや、COMMTIMEOUT構造体でヒットした日本語のサイトで勉強した結果、タイムアウトが働いた場合、発生までに読み込んだ文字を返して、終了する事が分かりました。現状待ちっぱなしになっているのは、設定がどこかおかしいところがあると思いますので、再度見直してみます。何か分かりましたら、報告いたします。
補足
その後判明したことをお知らせします。 DLしてきたクラスには、1文字ずつReadFileする関数と、1文をReadFileする関数があり(オーバーロード)、今まで1文字を読む方を使っていました。こちらで、http://members.jcom.home.ne.jp/0434383301/vc10.htm等を参考に、inReadInterval,inReadMultiplyer,inReadConstant = MAXDWORD,MAXDWORD,0等と設定してもタイムアウトは発生しませんでした。思い立って1文をReadFileする関数を使用したところ、inReadInterval,inReadMultiplyer,inReadConstant = 20,10,100といった普通の設定でタイムアウトが発生し、プログラムが読みっぱなしになる事はなくなりました。 1文字ずつ読む方でタイムアウトを発生させる設定・方法がありましたら、教えてください。 もうしばらく開いておきます。
- Interest
- ベストアンサー率31% (207/659)
http://okwave.jp/qa3351570.html 見てきました。 VBAがわかるのでしたら、自作するより、VBで提供されているシリアル通信用の部品を使ったほうが安全確実で早くできるでしょう。 Visual Basic は Express Edition なら無償で入手できます。 http://www.microsoft.com/japan/msdn/vstudio/express/vbasic/ VBの使い方はVBAが判るなら大体一緒だと思いますが一応。 http://homepage1.nifty.com/rucio/main/main.htm 現行バージョンのVBでシリアル通信 http://www.microsoft.com/japan/msdn/vbasic/migration/tips/SeriaPort/ C++でWin32APIを呼び出すことを考えれば、はるかに簡単です。
お礼
アドバイスありがとうございました。実はVB2005には、commのコントロールがある事を知って、Express版をDLし、数千円をはたいて参考書も買い入れたのですが、考えてみるとFramework2って、XP機では元々入っていないんですね。実行ファイルだけのコピーで使えるものを作りたいのです。XP機なら入っているFramework1.1ベースのVB2003(手元にあります)では、APIを使わざるを得ないので、それならいっそc++でと考えたものです。VBAでAPIを使っていて、こんな面倒くささはc++では要らないんだろうなと、常々考えていたもので。c++の奥深さは果てしなさそうですが、チャレンジしてみたいと考えています。
お礼
お返事ありがとうございます。 勘違いしておりました。WriteFile後にマイコンボード側は読みっぱなしに陥っているので、一文字も送って来ませんから、PC側のReadFile(1バイトであろうと、1文字列であろうと)がTimeOutになったときの、lpNumberOfBytesRead は0に決まってますね。 DWORDの件も了解いたしました。 ありがとうございました。これにて閉めたいと思います。