RS232C通信のタイムアウトが機能しない理由とAPIの挙動について

このQ&Aのポイント
  • RS232C通信においてタイムアウトが機能しない原因を教えてください。
  • また、タイムアウトが働くとAPIはどのような挙動を示すのでしょうか。
  • お願いします。
回答を見る
  • ベストアンサー

RS232C通信のタイムアウトが働きません

http://okwave.jp/qa3351570.htmlの続きです。 お陰様でDLしたクラスの意味もほぼ理解でき、昔作成したPICボードにコマンドを送信し、返信を受け取る事ができました。試行錯誤の過程で、PCから送るコマンドの末尾に\rを付けないと、書き放しになってしまい、タスクマネージャから該当するプロセスを終了させないと終わらなくなる事が判明しました(自分で設定したプロトコルですが...)。上記クラスには、タイムアウト設定の関数(単純にSetCommTimeoutsを実行しているだけ)もあったため、試しに読み書きのタイムアウト値をを設定してみましたが、改善されません。タイムアウト値が意図した通り設定されている事は、読み出して確認しました。今は、\rをつけてやって動いてはいるのですが、 ・このケースで、タイムアウトが機能しないのは何故か ・タイムアウトが働くと、APIはどのような挙動をしめすのか 教えていただきたく、お願いします。

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

  • ベストアンサー
  • kb-nike
  • ベストアンサー率36% (72/200)
回答No.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" を用いて、文字列に変換できます。

mitarashi
質問者

お礼

お返事ありがとうございます。 勘違いしておりました。WriteFile後にマイコンボード側は読みっぱなしに陥っているので、一文字も送って来ませんから、PC側のReadFile(1バイトであろうと、1文字列であろうと)がTimeOutになったときの、lpNumberOfBytesRead は0に決まってますね。 DWORDの件も了解いたしました。 ありがとうございました。これにて閉めたいと思います。

その他の回答 (4)

  • kb-nike
  • ベストアンサー率36% (72/200)
回答No.4

ANo2 の補足です。 「DLしてきたクラス」の内容が分かりませんので的を外しているかもしれませんが: そのクラスの中で、ReadFile()をどのように呼び出しているのかが分かりませんので、 実験として、とりあえず設定はそのクラスを使って行い、 可能であれば、読込について、直接(API/SDKの)ReadFile()を使って確認されては如何でしょうか。

mitarashi
質問者

お礼

お返事ありがとうございます。クラスの関数の中味は、ただのReadFileAPIなんだけどなと思いつつも、見直してみて原因が分かりました。クラスの関数内で、実際に読み込んだ文字数が0で無くなるまで、ReadFileを繰り返すループになっていましたので、TimeOutが働いてReadFileの次のステップに進んでも、再びReadFileを繰り返す無限ループに陥っていたのでした。アドバイスありがとうございました。 ここで教えていただきたいのですが、1文を読み込む方の事例で、TimeOutが働いてReadFileを抜けた事を判定するにはどうしたら良いのでしょうか。実際に読み込んだ文字列の長さを調べると、0が得られましたが、これは再現性があるのでしょうか。(このとき、TimeOut前に、8文字位は読み込んでいるはずです) もう一つ素人の質問で申し訳ありませんが、構造体に設定しているDWORD型の変数の中味をMessageBox等で簡単に調べるにはどうしたら良いのでしょうか。さっぱり分からないので、floatにキャストしてから、sprintfで文字列に変換しておりますが、もっと普通の方法がありそうに思います。 以上、よろしくお願いいたします。

  • Interest
  • ベストアンサー率31% (207/659)
回答No.3

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を使ったほうが確実に動くプログラムを早く作れる」という結論に達しました。

mitarashi
質問者

お礼

情報ありがとうございます。 どこかのサイトに、シリアル通信をするのは簡単だが、多くの環境で動作するものを作るのは大変だとありましたが、その通りなのでしょう。中味は良く理解できていませんが、フロー制御も色々種類がある様ですし。しかし、今回PCと通信する相手は、自作で、TXD,RXDとGNDの3本線で通信できてしまう代物で、多くて20文字程度のコマンドとレスポンスの通信だけを考えていますので、なんとかなるのではないかと思っています。ついでにc++を習得しようというのですから、遠回りは承知の上です。 c++でやってみて、こんなところがうまくいかなかった、苦労したというところがあれば、教えていただけると幸いです。

  • kb-nike
  • ベストアンサー率36% (72/200)
回答No.2

ご質問の趣旨から外れていれば、お読み捨てください。 ・タイムアウトが働くと、APIはどのような挙動をしめすのか: ReadIntervalTimeout と ReadTotalTimeoutMultiplier が MAXDWORD、 かつ ReadTotalTimeoutConstant が ゼロより大~MAXDWORDより小、 の時、 入力バッファーが空であれば、ReadFile関数は待機し、 ○1文字(character)が到着すると直ちに戻る。 ○ ReadTotalTimeoutConstantで指定された時間内に文字が到着しない場合はReadFile関数はTimeoutする。 ReadTotalTimeoutMultiplier と ReadTotalTimeoutConstant がゼロの時、 読み取りに対して、totaltimeout は使われない。 これらのパラメータの設定・読み出しは、SetCommTimeouts・GetCommTimeouts関数でできます。 詳細は、COMMTIMEOUT構造体(Patform SDK)の解説を参照してください。

mitarashi
質問者

お礼

アドバイスをありがとうございます。 いろいろと検証していて、返答が遅れて申し訳ありません。非同期通信なので、WriteFileの方は送り放しで完了してしまい、PIC(制御用マイコン)から返事が無いので、最初のReadFileで1文字読み込む所でずっと待っている事が分かりました(考えてみれば当たり前ですが)。ご紹介いただいたサイトや、COMMTIMEOUT構造体でヒットした日本語のサイトで勉強した結果、タイムアウトが働いた場合、発生までに読み込んだ文字を返して、終了する事が分かりました。現状待ちっぱなしになっているのは、設定がどこかおかしいところがあると思いますので、再度見直してみます。何か分かりましたら、報告いたします。

mitarashi
質問者

補足

その後判明したことをお知らせします。 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)
回答No.1

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を呼び出すことを考えれば、はるかに簡単です。

mitarashi
質問者

お礼

アドバイスありがとうございました。実はVB2005には、commのコントロールがある事を知って、Express版をDLし、数千円をはたいて参考書も買い入れたのですが、考えてみるとFramework2って、XP機では元々入っていないんですね。実行ファイルだけのコピーで使えるものを作りたいのです。XP機なら入っているFramework1.1ベースのVB2003(手元にあります)では、APIを使わざるを得ないので、それならいっそc++でと考えたものです。VBAでAPIを使っていて、こんな面倒くささはc++では要らないんだろうなと、常々考えていたもので。c++の奥深さは果てしなさそうですが、チャレンジしてみたいと考えています。

関連するQ&A

  • VISCAプロトコル(RS232C通信)のプログラム

    VISCAプロトコル(RS232C通信)のプログラムがうまく動きません。 大学の研究にてSONYのEVI-D100というカメラをパソコンから制御する必要が出てきました。 このカメラはVISCAプロトコル(RS232C通信)で制御するらしく、シリアル通信でコマンドを送る以下のようなプログラムをウェブで見つけて参考にしています。 http://onishi-lab.jp/programming/rs232c_win.html しかし、短いコマンド(例:カメラを右にパンする、81 01 06 01 10 10 02 03 FF)は動くのですが、長いコマンド(例:カメラのパンチルト上限を設定、81 01 06 07 00 01 0F 0A 05 00 0F 0E 09 08 FF)になるとコマンド中に0が入ると動いてくれません。また、コマンド中に0がなくても思うような動きをしてくれません。 一応自分で通信タイムアウトは書き加えたのですが、それでもうまく動きません GetCommTimeouts( hCom, &cto ); // タイムアウトの設定状態を取得 cto.ReadIntervalTimeout = 0; cto.ReadTotalTimeoutMultiplier = 0; cto.ReadTotalTimeoutConstant = 1000; cto.WriteTotalTimeoutMultiplier = 0; cto.WriteTotalTimeoutConstant =1000; SetCommTimeouts( hCom, &cto ); // タイムアウトの状態を設定 RS232Cについては初心者なのでよくわからないことも多いのですが、どこをどう書き換えれば動くかなどを教えていただけると幸いです。よろしくお願いします。 EVI-D100のマニュアルページへのリンクを貼っておきます。 http://www.totsu.co.jp/isp/ispproducts/pdf/D100_tec.pdf

  • ftpのタイムアウト指定

    バッチファイルから ftp -s:ftpcmd.txt のようにos標準添付のftpコマンドを使用しているのですが ftpコマンドにはタイムアウト時間の指定はないのでしょうか? 以前ftpで通信したところ2日間終了せず ずっと動きつづけていた事があります 一定時間でタイムアウトするようにしたいのです ダイムアウトする方法について教えて下さい

  • 拡張したRS485通信ボードである条件下にて通信タイムアウトエラーが発

    拡張したRS485通信ボードである条件下にて通信タイムアウトエラーが発生する。 開発環境:VisualBasic6.0(SP6) PC:WinXP PCにRS485通信用のPCIボード(Win32API対応)を増設しました。ポートの割り当てはCOM3、4、7、8となっています。VB6で計測器との通信プログラムを作成しました。 開発環境がインストールされてあるPC上で、開発ユーザーがログインして作成したソフトの実行ファイルを起動して使用する際には、正常に通信しております。 しかし、PC起動後に他ユーザーがログインして使用すると、通信タイムアウトエラーが発生してしまいます。ポートのオープンとボーレートの設定まではうまく出来ているようです。ただ、PC起動後に開発ユーザーがログインしてログオフし、他ユーザーがログインして使用すれば問題なく通信します。 原因がまったく分からず、困っております。どなたかご教授下さい。

  • DNSタイムアウト

    有線でインターネットをしていると、一日に数回ローカルエリアネットワークが切断されます。この時に、イベントビューアを見るといつもID:1014 DNSタイムアウトが表示されています。 調べたところ、これはIPv6が邪魔をしているからとのことだったので、このプロトコルを使用しないように設定しましたが、改善されませんでした。 DNSのIPアドレスはルータの設定ページに表示されていたものを使用しています。 たぶんDNSが問題であると思うのですが。。。 どうすればローカルエリアネットワークが切断されないようにすることが出来るでしょうか? 必要な情報がございましたらお知らせください。 よろしくお願いします。 使用環境:Windows7 Home Premium 32bit SP1

  • データ読込時のタイムアウト

    SQL-Serverのデータ(約30万件)を関数で処理した結果、約1000件くらいを、VS2005のレポートサービスで出力したいと思います。 その際、大体50:50の確立でタイムアウトを起こしてしまいます。 エラーを起こす場所は、 Me.××TableAdapter.Fill(Me.▲▲DataSet.××) です。 SQLコマンドに対しては、CommandTimeoutで対処するのは解りますが、テーブルアダプタを介してのデータの読込に関するタイムアウトの時間設定が解りません。どうしたらよろしいでしょうか?

  • SQLServer2008でタイムアウト

    SQLServer2008を使っています。 レセプトを入れた大きなテーブル(1000万行以上)から、何年何月にどの保険者(たとえば国保)に何件請求があったかを取り出したいと思います。 保険者は保険者番号(10桁前後の数値)、診療年月は200904のような形で入っています。 主キーになる項目はないので主キーは設定していません。 ManagementStudioにて保険者番号、診療年月に下記のコマンドでインデックスを設定しました。 CREATE NONCLUSTERED INDEX IDX_レセプト1 ON dbo.レセプト(保険者番号) CREATE NONCLUSTERED INDEX IDX_レセプト2 ON dbo.レセプト(診療年月) その後、目的の集計を行うべくManagementStudioで下記のSelectコマンドを実行しました。 SELECT 保険者番号, 診療年月, COUNT(保険者番号) AS Expr1 FROM dbo.レセプト GROUP BY 保険者番号, 診療年月 ところがタイムアウトになってしまうのです。 オブジェクトエクスプローラーで一番上のアイコンを右クリックし、プロパティで接続のタイムアウトを0に設定してみましたが改善しません。 どうしたらいいでしょうか。

  • プロキシサーバのDNS名前解決タイムアウトエラー

    CentOSでプロキシサーバをsquid及びDNSサーバをBIND9で運用において、プロキシのeht0の設定がDNS1のみ(セカンダリなし)で、ネットサーフィンしているときにたまにDNSの名前解決がタイムアウト(セカンダリがあればセカンダリに問い合わせる)になって、止まってしまうのですが、プロキシの挙動はプライマリしかDNSがない場合には、タイムアウト時に再度問い合わせもしくは、端末にエラーを返すことしないのでしょうか? もしくはエラーを返す場合のsquidの設定は何を指定すればよいのでしょうか。

  • EPSON SCAN2 のタイムアウトについて

    EPSON SCAN2 のタイムアウトについて EPSON SCAN2ユーティリティーにて「節電の設定をする」から時間を設定する事が可能とアドバイスを受けましたが、スキャナーをLAN接続している場合は、この設定は出来ませんでした。何か他に設定する方法は無いでしょうか。 ※OKWAVEより補足:「EPSON社製品」についての質問です。

  • ダウンロード処理がタイムアウトする場合

    I.Eであるサイトよりでファイルのダウンロードをしたいのですが、 「Internet Explorerではxxxxxxxをダウンロードできません。処理がタイムアウトになりました」 のウィンドウが出て、ダウンロードが強制終了します。 転送率は低いですが、90%完了まではいきます。 タイムアウトする迄の時間設定の変更は可能でしょうか?(時間を長くしたい) また、90%は完了しているので、その続きからダウンロードする事は可能でしょうか? 環境はWindows Me /Internet Explorer 6/YAHOO BB です。

  • ドメインにログインするのにタイムアウトありますか?

    ADドメインで運用しているのですが、 クライアントのパソコンを起動してから、 ログインするまでに2~3分くらい遅れると ログインできない現象が起こります。 起動してからログインするまでに時間をかけなければ ログインは正常に動作しますし、 その他のドメイン設定も有効なのですが、 ドメインにログインするまでの タイムアウト設定などがあるのでしょうか? どなたか知っている方、いましたら教えてください。 よろしくお願いします。 [環境] サーバー:Windows2008server R2 (Active Directry) クライアント:WindowsXP SP1 or SP2 ※ファイル・プリントサーバとして使用しています。 ※DHCP・DNSサーバーも兼用しています。