
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で質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# C言語プログラム変更 2 2022/12/21 15:03
- Excel(エクセル) [Excel2016] 相関表等の自動作成 2 2022/08/01 20:34
- Visual Basic(VBA) VBAでoutlook365が起動しません。 4 2022/08/25 13:31
- USBメモリー・SDカード・フラッシュメモリー 銀行が振込データの受け渡しに未だにFDを使っている理由は「FDDがAドライブ固定だから」って本当? 11 2022/06/02 03:53
- Wi-Fi・無線LAN PCWi-Fiの設定方法がわからなくて困っています。 4 2022/12/28 18:30
- システム CSVファイルのマッピング処理の省力化 1 2022/11/24 00:01
- その他(データベース) 業務用のデータベースサーバーの選び方について 4 2022/11/22 10:22
- C言語・C++・C# TCP/IP通信時のサーバーからの受信 2 2022/11/23 09:11
- Excel(エクセル) Excelで全クラスのランキング表を作成したい 4 2022/05/24 15:28
- Excel(エクセル) 【困っています】VBA 追加処理の記述を教えてください。 1 2022/08/25 22:54
このQ&Aを見た人はこんなQ&Aも見ています
関連するカテゴリからQ&Aを探す
おすすめ情報
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
Vba Array関数について教えてく...
-
【マクロ】シートの変数へ入れ...
-
【マクロ】並び替えの範囲が、...
-
エクセルのVBAコードと数式につ...
-
エクセルのマクロについて教え...
-
エクセルの改行について
-
【VBA】 結合セルに複数画像と...
-
vbsでのwebフォームへの入力制限?
-
算術演算子「¥」の意味について
-
【マクロ】売上一覧YYYYMMDDHHS...
-
【マクロ】開いているブックの...
-
Vba セルの4辺について罫線が有...
-
vb.net(vs2022)のtextboxのデザ...
-
ダブルクリックで貼り付けた画...
-
VBAの「To」という語句について
-
VBAでユーザーフォームを指定回...
-
VBAでCOPYを繰り返すと、処理が...
-
【マクロ】変数を使った、文字...
-
エクセルのVBAコードについて教...
-
ワードの図形にマクロを登録で...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
Vba セルの4辺について罫線が有...
-
vbsでのwebフォームへの入力制限?
-
【ExcelVBA】5万行以上のデー...
-
【マクロ】売上一覧YYYYMMDDHHS...
-
【マクロ】開いているブックの...
-
【マクロ】並び替えの範囲が、...
-
エクセルの改行について
-
エクセルのマクロについて教え...
-
vb.net(vs2022)のtextboxのデザ...
-
VBAでCOPYを繰り返すと、処理が...
-
VBA ユーザーフォーム ボタンク...
-
エクセルのVBAコードと数式につ...
-
エクセルのVBAコードについて教...
-
[VB.net] ボタン(Flat)のEnable...
-
【マクロ】変数を使った、文字...
-
改行文字「vbCrLf」とは
-
質問58753 このコードでうまく...
-
【マクロ】シートの変数へ入れ...
-
ワードの図形にマクロを登録で...
-
算術演算子「¥」の意味について
おすすめ情報