V.B6.0を使用しています。
測定器にバイナリーデータを送信すると、正しいバイナリーデータがテキストボックスに表示されます。
しかし、一度データを送信させた後に違うバイナリーデータを送信すると、一回目の時の戻り値がテキストボックスに表示され、もう一回コマンドボタンを押すと正しい戻り値が表示されます。
どのようにしたらよろしいでしょうか。
ただし、一回目(一度のほうのデータ)と二回目(違うデータ)の戻り値が表示されるテキストボックスは違います。
何かお気付きの点がありました返答をお願いいたします。
そういう風に作ってるからじゃないですか?
編集 削除1回目の戻り値と、2回目の戻り値を違うTextBoxに表示している
様ですが、どのようにして1回目の戻り値と、2回目の戻り値を
判断していますか。
033さん、ねろさんありがとうございます。
プログラムは、
Private Sub Command3_Click()
If MSComm1.PortOpen = True Then
Dim Buffer(3) As Byte 'バイト型配列
Buffer(0) = &H00
Buffer(1) = &H50
Buffer(2) = &H60
Buffer(3) = &HA4
MSComm1.Output = Buffer
'受信データの取得
varBuffer = MSComm1.Input
Text2.Text = Text2.Text & varBuffer
End If
Private Sub Command9_Click()
Dim bytArray(1) As Byte
If MSComm1.PortOpen = True Then
bytArray(0) = &HFF
bytArray(1) = &HB5
MSComm1.Output = bytArray
'受信データの取得
varBuffer = MSComm1.Input
Text3.Text = Text3.Text & varBuffer
End If
というように作成しました。
一回目の戻り値と、二回目の戻り値を判断するようなことはしていないと思います。
何かお気付きの点がありましたらご返答をお願いいたします。
データを送信バッファに詰めた後にすぐにデータを受け取ろうとしていますが、
そんなに早くデータがきていないのでは?(命令の速度はPCのスペックに左右さ
れるので明示的なウェイトが必要だと思いますよ。)
GODさんありがとうございます。
戻り値は30msec以内に返ってきます。
また。、ウェイトを使用する場合はどのよなコマンドを利用したらよろしいでしょうか。
質問ばかりで申し訳ありませんがよろしくお願いします。
Wait用関数を作成してみました。
実験はしてませんので考え方だけを参考にして下さい。(多分動くと思うけど・・・)
Private Declare Function timeGetTime Lib "winmm.dll" () As Long
' lngTime - ウェイト時間(ms) デフォルト1秒
' 戻り:True-受信あり,False-タイムアウト
Private Function RecvWait(Optional lngTime As Long = 1000) As Boolean
Dim STime As Long
Dim blnTimeOut As Boolean
STime = timeGetTime
Do While MSComm1.InBufferCount = 0
If timeGetTime - STime >= lngTime Then
blnTimeOut = True
Exit Do
End If
DoEvents
Loop
RecvWait = Not blnTimeOut
End Function
Private Sub Command3_Click()
'その他の処理
' :
MSComm1.Output = Buffer
If RecvWait(100) Then
'受信データの取得
varBuffer = MSComm1.Input
Text2.Text = Text2.Text & varBuffer
Else
Debug.Print "タイムアウト"
End If
End Sub
シリアルポートについては、APIレベルで、各種の制御の要求に対して
・処理に時間がかかるので後で結果を確認するよう求める
・ハードウェアの内部処理に丸投げし、投げ終わった時点で実行完了を返す
という2種類の挙動の物が存在します。
後者の場合、各種メソッドが終了するのと実際にその要求に従った信号線の制御が完了するまでに結構時間差があるので、ms単位のタイムアウトなんてことをしてもバグにしかなりません。
素直に送信時に受信フラグをクリアして、一定の秒数待って、まだ受信していなければタイムアウトで良いのでは?
> 後者の場合、各種メソッドが終了するのと実際にその要求に従った信号線の制御が
> 完了するまでに結構時間差があるので、ms単位のタイムアウトなんてことをしても
> バグにしかなりません。
>
別にバグにはならないと思いますよ。
タイムアウトはソフトウェアの仕様に盛り込まれているでしょうからそれに従えばい
いはずです。別に無理してmsにする必要も無いでしょうからウェイト時間は引き数で
渡せるようにしてあるんですが・・・
ソフトウェアの仕様的にバイト間タイムアウトと1コマンド受信のタイムアウトが出
てくるでしょうからうまく流用すれば問題ないと思いますが。
> 素直に送信時に受信フラグをクリアして、一定の秒数待って、まだ受信していなけ
> ればタイムアウトで良いのでは?
>
ソフト使用者側の意見としては待ち時間は少ない方が好ましいはずなので必ず一定時
間待つというような処理はどうかと思います。早く終わるなら早いほうが好ましいは
ずです。例えば何らかの処理をする時にボタンを押下してから必ず3秒間応答が無く
なったら嫌ですよね。
>別にバグにはならないと思いますよ。
> タイムアウトはソフトウェアの仕様に盛り込まれているでしょうからそれに従えばい
> いはずです。別に無理してmsにする必要も無いでしょうからウェイト時間は引き数で
> 渡せるようにしてあるんですが・・・
> ソフトウェアの仕様的にバイト間タイムアウトと1コマンド受信のタイムアウトが出
> てくるでしょうからうまく流用すれば問題ないと思いますが。
実際のところ、十分に長いタイムアウト時間の場合はバグにはならないと思いますね。Outputについては送信バッファの残り状況の確認をしてから待ちに入れば良いはずなので、
While MsComm1.OutputBufferCount > 0
DoEvents
Wend
をタイムアウト確認の前にでも入れてやればOKでしょう。
CTSEnableとDTREnableについても同様の問題があるのですが、これはまだ良い方法を知りません。とりあえず適当な時間も待ちを入れてごまかしています。
> ソフト使用者側の意見としては待ち時間は少ない方が好ましいはずなので必ず一定時
> 間待つというような処理はどうかと思います。早く終わるなら早いほうが好ましいは
> ずです。例えば何らかの処理をする時にボタンを押下してから必ず3秒間応答が無く
> なったら嫌ですよね。
説明不足で誤解を招いてしまったようです。
「受信が完了していたら即座に次の処理へ移る」
という意図だったのですが、読み返してみるとそうは伝わりませんね。 m(_o_)m
> Outputについては送信バッファの残り状況の確認をしてから待ちに入れば良いはずなので、
> While MsComm1.OutputBufferCount > 0
> DoEvents
> Wend
> をタイムアウト確認の前にでも入れてやればOKでしょう。
>
どうせやるなら上記だけでは足りませんよ。送信側もタイムアウト処理を付けるべきです。
OutputBufferCountがクリアされないと無限ループに陥り、バグの原因になってしまいます。
ただ、簡単な方法を取るのであれば受信タイムアウトに送信タイムアウトを足しこんで受信
待ち時間としてしまう方法もありかと。
CTSEnable → CTSHolding?
DTREnable → RTSEnable?
フロー制御が働いて通信が停止しているときはタイムアウト時間が経過するとタイムアウト
になりますよ。
タイムアウトの際に適宜送/受信バッファをクリアすれば問題は起きにくくなるでしょう。
MsComm1.OutputBufferCount = 0
MsComm1.InputBufferCount = 0
>ビギナー さん
送信コマンド別に、違うTextBoxにレシーブデーターを書き込みたいが為に
このようなプログラムになっているのでしょうが、ちょっと工夫して
レシーブデーターはOnCommイベントの中で取得した方がいいのでは。
たとえばListBoxを使って、送信要求とレシーブデーターを書いていくとか。
そうすればこのようなバグは起こらないし、タイムアウトなどのエラーも
Comeventプロパティーに任せられます。
> どうせやるなら上記だけでは足りませんよ。送信側もタイムアウト処理を付けるべきです。
> OutputBufferCountがクリアされないと無限ループに陥り、バグの原因になってしまいます
そうですね。ご指摘の通りです。
> CTSEnable → CTSHolding?
> DTREnable → RTSEnable?
この2つはOuputプロパティ変更と切り離して考えて下さい。
この2つのプロパティについても、変更が完了しても実際の信号線の出力電圧が変化していない場合があるのに、出力電圧の変化を確認する確実な方法がMsCommに設けられていないという意味です。
説明不足が多くて誤解を生んでしまったようで申し訳ありませんでした。
> この2つのプロパティについても、変更が完了しても実際の信号線の出力電圧が
> 変化していない場合がある
>
これって回路的に不具合があるか16550互換チップ(?)がいかれているのではないで
すか。両プロパティはポートにIn/Outしているだけでしょうから(未確認)。
電圧の確認は実際にどのように行っているのですか?変化に必要な時間はどのくら
いでしたか。
因みにRTSEnableがOFFになってもデータの受信がすぐに止まるわけではありません
よ。それはチップのFIFOのデータとOS側(?)の通信用バッファ分のデータは受信で
きる仕様になっていますから。(溜まっていればですけど)
あと、RTSEnableをOFFに落としても相手が無視して送りつづけていればバッファの
許す限り受信しますね。
> 出力電圧の変化を確認する確実な方法がMsCommに設けられていないという意味で
> す。
>
プロパティを読めば取れると思いますが。
> これって回路的に不具合があるか16550互換チップ(?)がいかれているのではないで
> すか。両プロパティはポートにIn/Outしているだけでしょうから(未確認)。
> 電圧の確認は実際にどのように行っているのですか?変化に必要な時間はどのくら
> いでしたか。
問題の現象は某社の増設ボードで起きた物で、メーカーによるとサブCPUを装備し、チップの制御はサブCPUが行うので高速だということらしいです。たぶん、ドライバがサブCPUに丸投げしているんでしょう。
その時は対話型のアプリケーションではないため、1秒程度の待ちを入れてごまかしましたので、細かい発生要件まではつかんでいません。
> プロパティを読めば取れると思いますが。
そうかもしれませんね。機会があれば試してみます。