
VB2005でWin32APIを用いてRS-232CのRTS信号を、データ送信中だけHIGHにさせるプログラムを作成中です。
色々調べて、Win32APIを使うことで、それらしい動作をさせるプログラムを作れることが分かり、色々調べてコーディングしたのですが、上手く動きません…。処理の流れは以下のようになっています。
(1) CreateFile()関数でCOMを開く。
(CreateFile()の「フラグ」には"FILE_FLAG_OVERLAPPED"を指定)
(2) CreateEvent()関数にてイベントオブジェクトを作成。
(3) EscapeCommFunction()でRTS信号をHIGHに設定。
(4) WriteFile()関数でRS-232Cへデータを送信する。
※ここまでは、オシロスコープにて正しく動作していることを確認しています。
(5) データ送信完了を待つために、SetCommEvent()関数で"EV_TXEMPTY"イベントマスクをセット。
(6) WaitCommEvent()で送信完了を待つ。
⇒WaitCommEvent()関数が、データ送信完了を待たずに抜けてきてしまう(Falseがリターンされる)…。
(7) そこで、WaitForSingleObject()を使ってイベントハンドラが"シグナル状態"になるのを待つ。
⇒タイムアウトに"INFINITE"を指定すると、無限待ち状態に陥ってしまう。
⇒また、タイムアウトに"1000"を指定すると、約1秒後に"WAIT_TIMEOUT"が返ってきてしまう。
WriteFile()関数、そしてWaitCommEvent()関数の引数には、OVERLAPPED構造体へのポインタを渡しているのですが、思うように動いてくれません。
※Win32APIの関数宣言の記述方法(データ型など)が誤って、このようになっていたりするのでしょうか…
どなたかヒントでもお教えいただけると、大変助かります。
以上、よろしくお願いいたします。
No.1ベストアンサー
- 回答日時:
>SetCommEvent()関数で"EV_TXEMPTY"イベントマスク
多分 SetCommMask のTypeミスですよね?
実際送信監視をしたことはないのと扱ったのが
かなり昔の話なので間違ってる可能性ありますが
(更にVBは知りません)
(6)でGetLastErrorで戻りが ERROR_IO_PENDING になってませんか?
その場合送信中って判断しないといけなかったような
http://msdn.microsoft.com/ja-jp/library/cc429842 …
以下余談
本来の目的が良くわからないのですがもしフロー制御などのために
RTS信号使うのであればわざわざ自分でコントロールする必要ないはずです
(フロー制御としてRTSCTSを選択すれば勝手にやってくれるはず)
この回答への補足
ご回答ありがとうございます。
仰る通り、GetLastErrorの返り値は "ERROR_IO_PENDING"です。
この返り値は、正しいのだと思うのですが、
その後、While文で"WaitForSingleObject()"を繰り返し呼び出し、
シグナル状態になるのを待っているのですがこのWhile文を抜けることができません。
※"WaitForSingleObject()"の返り値が"0"になれば、While文を抜けるようコーディングしています。
> RTS信号使うのであればわざわざ自分でコントロールする必要ないはずです
> (フロー制御としてRTSCTSを選択すれば勝手にやってくれるはず)
これは、何かの設定をすれば、プログラム側からRS-232Cへデータ送信している間にだけ、RTS信号をHIGHにすることが出来る、ということでしょうか??
No.7
- 回答日時:
横から口出しさせてもらいます、
>データ送信完了後20ミリ秒以内にRTS信号をLOWにしないと、
>正しく通信できないようになっています。
これは非常に難しいです。
なぜかというと、
SetCommEvent()関数の"EV_TXEMPTY"イベントは
「送信バッファから最後のデータを送信した」ときに発生しますが
あくまでも、送信バッファが空になっただけで、送信が完了している保証が無いのです。
"EV_TXEMPTY"イベントからどのくらいの待ち時間が必要かはPC毎に異なる可能性があります。
※送信バッファのデータが1バイトずつUARTチップに送られるが、
※UARTチップ自体がバッファを持っているので、
※送信バッファが空になっても送信は続いています。
助言、ありがとうございます。
EV_TXEMPTYイベントでは、微妙なタイミングが難しいのですね。
最終的に、RtsControlに”Toggle”を指定することで、やりたい事が実現できました。
No.6
- 回答日時:
連投になりますがURL書いたほうが早そうなので
以下URL見てて ひょっとしたら目的はRS485 とかですかねなんて思いました
(半2重通信?)
余りに昔で当時私が使っていたWEBは消えてなくなってましたが
検索かけたところ別のところにありました(こっちが本家か?)
Delphiソースになりますが以下ソースを参考にしてみてはどうでしょう
(#5で書いた人様のコンポーネントってのがまさにこれのことです)
http://wiki.fdiary.net/apollo/?Phi%3A%3ACommX
※ Delphi(Pascal)ソースですが使ってるのはWin32APIなので
それほど悩まなくても読めるのではないかと思います
この回答への補足
その通り、RS-485とRS-232C両方を備えたデバイスとパソコン間で通信しようとしています。
下にも書かせていただいた通り、パソコン側はデータ送信中にRTS信号をHIGHにして、
データ送信完了後20ミリ秒以内にRTS信号をLOWにしないと、正しく通信できないようになっています。
koi1234さん
色々ありがとうございました。
最終的に、"EV_TXEMPTY"イベントを使用せず、DCB構造体のRtsControlを"Toggle"にセットすることで
要望通りの動きをオシロスコープにて確認できました。
以前もToggle指定を試していましたが、正しい使い方は、DCB構造体内の
「ビットフィールド」で設定する、ということでした。これを知らずに
BYTE変数で指定していました…。
本当にありがとうございました。
大変勉強になりました。
No.5
- 回答日時:
>ピクリとも動きませんでした・・・。
ここら辺は補足に書いたとおりデータ送信時にHIGHにするという挙動とは
異なる可能性があります
(信号の極性の話もそうですが変化タイミングは間違いなく違います)
確認する為には特殊な条件環境を構築しないと確認できないので
簡単なテストが出来ないのですがテスト環境の問題で変らない
と思い込まれているだけではないかと思います(そうじゃないならごめんなさい)
# 送信側はデータ送り続け受信側はデータ受信しないような通信環境を
# 作らないと確認できません
# 通信ソフト動かすと普通は受信動作してしまうのでなかなか確認できません
最終的に行いたいのはフロー制御としての信号制御処理なのでしょうか?
今、人様が作った通信プログラムのコンポーネント処理を見ていたのですが
(それも送信バッファイベントは見てませんでした & 言語はdelphi)
受信時 ERROR_IO_PENDING だった時に
GetOverlappedResultで TRUE になるまでループしてますね
送信でも同様な処理が必要なのかもしれません
そういえば昔 #4さんの言われてるような型の違いで
動かなくなるってのもあったのを思い出しました
(どの言語でも似たような話があるのかと再認識しました)
問題になるのは Create時の 戻り値ぐらいだったような気もしますが
いかんせん昔の話で忘れています
この回答への補足
本当に色々ありがとうございます。
ご紹介いただいたソースを見ました。
確かに、"GetOverlappedResult()"でTrueになるのを待っている処理になっていますね。
※"WaitCommEvent()"は使用していないようですね…。
明日、早速試してみたいと思います。
> 確認する為には特殊な条件環境を構築しないと確認できないので
> 簡単なテストが出来ないのですがテスト環境の問題で変らない
> と思い込まれているだけではないかと思います(そうじゃないならごめんなさい)
> # 送信側はデータ送り続け受信側はデータ受信しないような通信環境を
> # 作らないと確認できません
> # 通信ソフト動かすと普通は受信動作してしまうのでなかなか確認できません
テスト環境では、通信先デバイスにはRS-232Cケーブルを接続せずに、パソコンから伸びたRS-232Cケーブルの先にピンを立て、そこにオシロスコープで当たって信号をチェックしています。
> 最終的に行いたいのはフロー制御としての信号制御処理なのでしょうか?
最終的には、通信先デバイスとデータの送受信を行いたいのですが、そのデバイスの通信仕様(ルール)で、パソコン側からデータを送信する際にはRTS信号をHIGHにし、データ送信完了後20ミリ秒以内にRTS信号をLOWにしなければ、正しく通信できません。
No.4
- 回答日時:
VB6以前のLong型はVB2005ではInteger型になっているので、Win32APIを使う場合はこれを書き換えないと正常動作
しませんが、お使いのプログラムでは変更済みでしょうか?この回答への補足
sknbsknb2さん
ご回答ありがとうございます。
データ型の宣言が違っているのはネットで調べて理解しております。
基本的に、「http://www.pinvoke.net/」で関数の型、構造体などを調べてコーディングしています。
この宣言、または関数の呼び出し順が間違っているのかもしれません…。
No.2
- 回答日時:
>その後、While文で"WaitForSingleObject()"を繰り返し呼び出し、
>シグナル状態になるのを待っているのですがこのWhile文を抜けることができません。
合ってるかは判りません(↑が記載ミスではないとして)
WaitCommEventが(ERROR_IO_PENDINGで)エラーになっているのですから
WaitForSingleObjectを呼び出してもダメでしょう
繰り返すならWaitCommEventを繰り返すべきでは?
>何かの設定をすれば、プログラム側からRS-232Cへ
>データ送信している間にだけ、RTS信号をHIGHにすることが出来る
(実際の信号レベルまで確認したわけではありませんが)
フロー制御で使いたいということであればそういうことです
(フロー制御にはそれ以外にもXON/XOFFも可能です 併用も可)
DCB構造体の設定を行うことでその辺りの設定が行えます
書かれてませんが既に通信レートなどの設定で使ってる気がします
標準のまま何も設定していなくて動いているかもしれませんが
本来アプリ側できちんと設定すべきです
http://msdn.microsoft.com/ja-jp/library/cc429121 …
御存知かもしれませんが↑に通信関連関数一覧の説明があるので
BuildCommDCB/GetCommState/SetCommState 辺りを見てください
この回答への補足
色々ありがとうございます。
> WaitCommEventが(ERROR_IO_PENDINGで)エラーになっているのですから
> WaitForSingleObjectを呼び出してもダメでしょう
> 繰り返すならWaitCommEventを繰り返すべきでは?
WaitCommEvent()繰り返しも試してみましたが、Whileループから抜け出せません・・・。
※以下、ソースコード抜粋。
途中でVB.NETからVC#に移植して試しておりますので、VC#のソースになっていますが、あしからずご了承頂けますか。
uint dwEvent;
//// RTS信号 HI
EscapeCommFunction(hSerialPort, (uint)ExtendedFunctions.SETRTS);
//// データ送信
WriteFile(hSerialPort, snd_buf, (uint)(len), out (uint)lrc, ref hOvr);
// イベント作成
hOvr.EventHandle = CreateEvent(IntPtr.Zero, true, false, null);
// 送信エンプティのイベントを設定
SetCommMask(hSerialPort, EV_TXEMPTY);
// イベント=送信バッファエンプティ待ち
WaitCommEvent(hSerialPort, out dwEvent, ref hOvr);
while (true)
{
WaitCommEvent(hSerialPort, out dwEvent, ref hOvr);
if (dwEvent == EV_TXEMPTY)
{
break;
}
}
> DCB構造体の設定を行うことでその辺りの設定が行えます
DCB.RtsControlというのがありましたので、それを"Enable"、"Toggle"、"Handshake"など試してみましたが、ピクリとも動きませんでした・・・。
DCB構造体に対しては、仰るとおり、ボーレートやデータビット長などの設定を行っております。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
関連するカテゴリからQ&Aを探す
今、見られている記事はコレ!
-
弁護士が解説!あなたの声を行政に届ける「パブリックコメント」制度のすべて
社会に対する意見や不満、疑問。それを発信する場所は、SNSやブログ、そしてニュースサイトのコメント欄など多岐にわたる。教えて!gooでも「ヤフコメ民について」というタイトルのトピックがあり、この投稿の通り、...
-
弁護士が語る「合法と違法を分けるオンラインカジノのシンプルな線引き」
「お金を賭けたら違法です」ーーこう答えたのは富士見坂法律事務所の井上義之弁護士。オンラインカジノが違法となるかどうかの基準は、このように非常にシンプルである。しかし2025年にはいって、違法賭博事件が相次...
-
釣りと密漁の違いは?知らなかったでは済まされない?事前にできることは?
知らなかったでは済まされないのが法律の世界であるが、全てを知ってから何かをするには少々手間がかかるし、最悪始めることすらできずに終わってしまうこともあり得る。教えてgooでも「釣りと密漁の境目はどこです...
-
カスハラとクレームの違いは?カスハラの法的責任は?企業がとるべき対応は?
東京都が、客からの迷惑行為などを称した「カスタマーハラスメント」、いわゆる「カスハラ」の防止を目的とした条例を、全国で初めて成立させた。条例に罰則はなく、2025年4月1日から施行される。 この動きは自治体...
-
なぜ批判コメントをするの?その心理と向き合い方をカウンセラーにきいた!
今や生活に必要不可欠となったインターネット。手軽に情報を得られるだけでなく、ネットを介したコミュニケーションも一般的となった。それと同時に顕在化しているのが、他者に対する辛らつな意見だ。ネットニュース...
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
C# シリアル通信でデータ受信...
-
バイナリデータ受信時のデータ順
-
ReadFile(GPSとの通信)Win7で...
-
VB2005でWin32APIを用いてRS-23...
-
シリアルポート通信
-
シリアル通信エラー
-
rs232cでの受信データ(mscomm)...
-
WaitForMultipleObjects関数の...
-
シリアル通信の出力バッファと...
-
ftplibのエラー処理
-
winsock recvでデータの取得方法
-
Macターミナルで実行中のプログ...
-
powershell を使いカレントディ...
-
タスクマネージャーのプロセス...
-
プロセスのアタッチ・デタッチ...
-
ループを使わずに、特定時間に...
-
パソコンの演算速度について
-
フレームワーク「4.8.1」で、[S...
-
バックグラウンドで実行される...
-
Amazonfireタブレットにわから...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
C# シリアル通信でデータ受信...
-
winsockでソケット通信の開発を...
-
socket: recvはいつ,どれだけ...
-
「スイッチングハブのバッファ...
-
シリアル通信の出力バッファと...
-
WriteFile()でのデータ送信がで...
-
COMポートの同時オープン同時読...
-
SerialPortのDataReceivedイベ...
-
RS-232Cでバイナリデータを受信...
-
シリアル通信エラー
-
WinsockAPIのrecvfromの受信デ...
-
Linuxでのシリアル通信について...
-
SocketのSend関数でのCLOSEの検...
-
UDP処理のエラーについて
-
WaitForMultipleObjects関数の...
-
rs232cでの受信データ(mscomm)...
-
ソケット通信内 read関数について
-
recv関数の受信結果について
-
TCP/IP通信プログラミングにお...
-
VC++2010 TCPIP通信の受信処理...
おすすめ情報