RS-232Cで測定器からデータを受信するには?


ビギナー  2004-11-11 18:52:19  No: 117535  IP: [192.*.*.*]

V.B6.0を使用しています。
測定器にバイナリーデータを送信すると、正しいバイナリーデータがテキストボックスに表示されます。
しかし、一度データを送信させた後に違うバイナリーデータを送信すると、一回目の時の戻り値がテキストボックスに表示され、もう一回コマンドボタンを押すと正しい戻り値が表示されます。
どのようにしたらよろしいでしょうか。
ただし、一回目(一度のほうのデータ)と二回目(違うデータ)の戻り値が表示されるテキストボックスは違います。
何かお気付きの点がありました返答をお願いいたします。

編集 削除
033  2004-11-11 23:13:36  No: 117536  IP: [192.*.*.*]

そういう風に作ってるからじゃないですか?

編集 削除
ねろ  2004-11-13 16:34:04  No: 117537  IP: [192.*.*.*]

1回目の戻り値と、2回目の戻り値を違うTextBoxに表示している
様ですが、どのようにして1回目の戻り値と、2回目の戻り値を
判断していますか。

編集 削除
ビギナー  2004-11-15 10:53:20  No: 117538  IP: [192.*.*.*]

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

というように作成しました。

一回目の戻り値と、二回目の戻り値を判断するようなことはしていないと思います。

何かお気付きの点がありましたらご返答をお願いいたします。

編集 削除
GOD  2004-11-15 11:05:37  No: 117539  IP: [192.*.*.*]

データを送信バッファに詰めた後にすぐにデータを受け取ろうとしていますが、
そんなに早くデータがきていないのでは?(命令の速度はPCのスペックに左右さ
れるので明示的なウェイトが必要だと思いますよ。)

編集 削除
ビギナー  2004-11-15 11:40:37  No: 117540  IP: [192.*.*.*]

GODさんありがとうございます。
戻り値は30msec以内に返ってきます。
また。、ウェイトを使用する場合はどのよなコマンドを利用したらよろしいでしょうか。
質問ばかりで申し訳ありませんがよろしくお願いします。

編集 削除
GOD  2004-11-15 12:36:43  No: 117541  IP: [192.*.*.*]

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

編集 削除
ひろ  2004-11-15 13:01:09  No: 117542  IP: [192.*.*.*]

シリアルポートについては、APIレベルで、各種の制御の要求に対して

・処理に時間がかかるので後で結果を確認するよう求める
・ハードウェアの内部処理に丸投げし、投げ終わった時点で実行完了を返す

という2種類の挙動の物が存在します。

後者の場合、各種メソッドが終了するのと実際にその要求に従った信号線の制御が完了するまでに結構時間差があるので、ms単位のタイムアウトなんてことをしてもバグにしかなりません。

素直に送信時に受信フラグをクリアして、一定の秒数待って、まだ受信していなければタイムアウトで良いのでは?

編集 削除
GOD  2004-11-15 13:25:43  No: 117543  IP: [192.*.*.*]

> 後者の場合、各種メソッドが終了するのと実際にその要求に従った信号線の制御が
> 完了するまでに結構時間差があるので、ms単位のタイムアウトなんてことをしても
> バグにしかなりません。
>
別にバグにはならないと思いますよ。
タイムアウトはソフトウェアの仕様に盛り込まれているでしょうからそれに従えばい
いはずです。別に無理してmsにする必要も無いでしょうからウェイト時間は引き数で
渡せるようにしてあるんですが・・・
ソフトウェアの仕様的にバイト間タイムアウトと1コマンド受信のタイムアウトが出
てくるでしょうからうまく流用すれば問題ないと思いますが。

> 素直に送信時に受信フラグをクリアして、一定の秒数待って、まだ受信していなけ
> ればタイムアウトで良いのでは?
>
ソフト使用者側の意見としては待ち時間は少ない方が好ましいはずなので必ず一定時
間待つというような処理はどうかと思います。早く終わるなら早いほうが好ましいは
ずです。例えば何らかの処理をする時にボタンを押下してから必ず3秒間応答が無く
なったら嫌ですよね。

編集 削除
ひろ  2004-11-15 19:17:03  No: 117544  IP: [192.*.*.*]

>別にバグにはならないと思いますよ。
> タイムアウトはソフトウェアの仕様に盛り込まれているでしょうからそれに従えばい
> いはずです。別に無理してmsにする必要も無いでしょうからウェイト時間は引き数で
> 渡せるようにしてあるんですが・・・
> ソフトウェアの仕様的にバイト間タイムアウトと1コマンド受信のタイムアウトが出
> てくるでしょうからうまく流用すれば問題ないと思いますが。

実際のところ、十分に長いタイムアウト時間の場合はバグにはならないと思いますね。Outputについては送信バッファの残り状況の確認をしてから待ちに入れば良いはずなので、
While MsComm1.OutputBufferCount > 0
    DoEvents
Wend
をタイムアウト確認の前にでも入れてやればOKでしょう。

CTSEnableとDTREnableについても同様の問題があるのですが、これはまだ良い方法を知りません。とりあえず適当な時間も待ちを入れてごまかしています。

> ソフト使用者側の意見としては待ち時間は少ない方が好ましいはずなので必ず一定時
> 間待つというような処理はどうかと思います。早く終わるなら早いほうが好ましいは
> ずです。例えば何らかの処理をする時にボタンを押下してから必ず3秒間応答が無く
> なったら嫌ですよね。

説明不足で誤解を招いてしまったようです。
「受信が完了していたら即座に次の処理へ移る」
という意図だったのですが、読み返してみるとそうは伝わりませんね。 m(_o_)m

編集 削除
GOD  2004-11-15 23:37:53  No: 117545  IP: [192.*.*.*]

> Outputについては送信バッファの残り状況の確認をしてから待ちに入れば良いはずなので、
> While MsComm1.OutputBufferCount > 0
>     DoEvents
> Wend
> をタイムアウト確認の前にでも入れてやればOKでしょう。
>
どうせやるなら上記だけでは足りませんよ。送信側もタイムアウト処理を付けるべきです。
OutputBufferCountがクリアされないと無限ループに陥り、バグの原因になってしまいます。
ただ、簡単な方法を取るのであれば受信タイムアウトに送信タイムアウトを足しこんで受信
待ち時間としてしまう方法もありかと。
CTSEnable → CTSHolding?
DTREnable → RTSEnable?
フロー制御が働いて通信が停止しているときはタイムアウト時間が経過するとタイムアウト
になりますよ。
タイムアウトの際に適宜送/受信バッファをクリアすれば問題は起きにくくなるでしょう。
MsComm1.OutputBufferCount = 0
MsComm1.InputBufferCount = 0

編集 削除
ねろ  2004-11-16 09:54:36  No: 117546  IP: [192.*.*.*]

>ビギナー さん
送信コマンド別に、違うTextBoxにレシーブデーターを書き込みたいが為に
このようなプログラムになっているのでしょうが、ちょっと工夫して
レシーブデーターはOnCommイベントの中で取得した方がいいのでは。
たとえばListBoxを使って、送信要求とレシーブデーターを書いていくとか。
そうすればこのようなバグは起こらないし、タイムアウトなどのエラーも
Comeventプロパティーに任せられます。

編集 削除
ひろ  2004-11-16 11:17:28  No: 117547  IP: [192.*.*.*]

> どうせやるなら上記だけでは足りませんよ。送信側もタイムアウト処理を付けるべきです。
> OutputBufferCountがクリアされないと無限ループに陥り、バグの原因になってしまいます

そうですね。ご指摘の通りです。

> CTSEnable → CTSHolding?
> DTREnable → RTSEnable?

この2つはOuputプロパティ変更と切り離して考えて下さい。
この2つのプロパティについても、変更が完了しても実際の信号線の出力電圧が変化していない場合があるのに、出力電圧の変化を確認する確実な方法がMsCommに設けられていないという意味です。

説明不足が多くて誤解を生んでしまったようで申し訳ありませんでした。

編集 削除
GOD  2004-11-16 13:04:21  No: 117548  IP: [192.*.*.*]

> この2つのプロパティについても、変更が完了しても実際の信号線の出力電圧が
> 変化していない場合がある
>
これって回路的に不具合があるか16550互換チップ(?)がいかれているのではないで
すか。両プロパティはポートにIn/Outしているだけでしょうから(未確認)。
電圧の確認は実際にどのように行っているのですか?変化に必要な時間はどのくら
いでしたか。
因みにRTSEnableがOFFになってもデータの受信がすぐに止まるわけではありません
よ。それはチップのFIFOのデータとOS側(?)の通信用バッファ分のデータは受信で
きる仕様になっていますから。(溜まっていればですけど)
あと、RTSEnableをOFFに落としても相手が無視して送りつづけていればバッファの
許す限り受信しますね。

> 出力電圧の変化を確認する確実な方法がMsCommに設けられていないという意味で
> す。
>
プロパティを読めば取れると思いますが。

編集 削除
ひろ  2004-11-16 14:25:03  No: 117549  IP: [192.*.*.*]

> これって回路的に不具合があるか16550互換チップ(?)がいかれているのではないで
> すか。両プロパティはポートにIn/Outしているだけでしょうから(未確認)。
> 電圧の確認は実際にどのように行っているのですか?変化に必要な時間はどのくら
> いでしたか。

問題の現象は某社の増設ボードで起きた物で、メーカーによるとサブCPUを装備し、チップの制御はサブCPUが行うので高速だということらしいです。たぶん、ドライバがサブCPUに丸投げしているんでしょう。

その時は対話型のアプリケーションではないため、1秒程度の待ちを入れてごまかしましたので、細かい発生要件まではつかんでいません。

> プロパティを読めば取れると思いますが。

そうかもしれませんね。機会があれば試してみます。

編集 削除