こんにちわ
まずはプログラムを見てください。
Private Sub Timer1_Timer()
If MSComm1.PortOpen = True Then
MSComm1.Output = "Q" + vbCr
comd = MSComm1.Input
comd = Format(comd, "0.################")
Label9.Caption = comd
MSComm1.Output = "F" + vbCr
comd = MSComm1.Input
Label20.Caption = comd
End If
End Sub
これはロックインアンプへ信号を送りその後データを取得し、プログラム内の各ラベルにその値を表示させるためのものですが、
片方のラベルにだけ表示されてしまいます。
なぜなのかまったくわからず困っています。
誰か助けてください。
>片方のラベルにだけ
具体的に、どちらに表示されてどちらに表示されないのですか?
表示されない方のコマンドは正しく送信されていますか?
通ってみた さんありがとうございます。
補足を追加いたします。
label9.captionのほうに値が入るのですが、もう一方は表示されません。
コマンドに関しては正しく送信されていることは確認できています。
どうかよろしくお願いします。
シリアル通信は非同期ですから、コマンドを出しても
すぐに応答が有るか否かわかりません。
また相手の機器がすぐに応答を返してもそのコードでは
受信は難しいでしょう。
受信の方法はMSDNにポーリングによる方法と、
イベントによる方法が出ていますので、参照してください。
我龍院さん、回答ありがとうございます。
さっそく我龍院さんが言われた方法を参照してみたいと思います。
もしよろしければ、受信の難しい理由を教えていただけないでしょうか?
最初の命令だけしか応答がないのはなぜだかわかりませんか?
MSComm.Inputはその時に受信バッファに有るデーターを返すだけです。
相手機器が100文字送る予定でも、現時点で受信バッファに10文字しか
届いて居ない場合は、10文字を返します。
従って送信要求を出してから相手機器が送信を終了するまで待つ必要が
有ります。
ただし相手の機器の送信が終わったことを知る方法は、シリアル通信の
プロトコルには有りません。
と言うか、そもそもシリアル通信には送信終了の概念が有りません。
その為通常複数のデータを送受信する場合は、データーのプロトコルで
各データーの区切りを明確にします、これにはデーター長を固定する
方法や、CSVで送る方法等が有ります。
>MSComm1.Output = "F" + vbCr
となっていますから、データーの区切りにはvbCrが使われていますね、
おそらく送られて来るデーターの最後にもvbCrが付いてくるのでしょう、
従って受信側では、vbCrが来るまで、MSComm.Inputで読みつづける
必要が有ります。
片方のデーターだけ受信出来ているように見える理由ですが、
一回目は、送信要求を出して直ぐ受信していますので、多分
データーは何も無いでしょう。
一回目のデーター要求の応答を2回目で受信している可能性が高いですね。
我龍院さん、たびたびの回答ありがとうございます。
我龍院さんの指摘>送信要求を出してから相手機器が送信を終了するまで待つ必要が有ります。
を参考に次のようなプログラムを書いてみました。
Private Sub Timer1_Timer()
If MSComm1.PortOpen = True Then
MSComm1.Output = "F" + vbCr
comd = MSComm1.Input
Label9.Caption = comd
For i = 0 To 10000
For j = 0 To 1300
Next j
Next i
MSComm1.Output = "Q" + vbCr
comd = MSComm1.Input
Label20.Caption = comd
End If
End Sub
For文を用いて送信終了を待ってみたんですが、今度は指定のラベルに受信されない
問題が発生してしまいました。
この場合、信号"F"をLabel9に、信号"Q"をLabel20に表示したいのですが。
逆に表示してしまいます。なぜだかわかるでしょうか?
もしよろしければ質問の回答お願いします。
えーと、一定周期で交互にコマンドを出すのですね。
ループではなくてOnCommイベントを使いましょう。
Option Explicit
'---------------------------
'コマンド定義
Const FCOMMAND = "F" & vbCr
Const QCOMMAND = "Q" & vbCr
'---------------------------
Private Type com
strCommand As String '送信コマンド
boolComBusy As Boolean '状態フラグ
strReciveData As String '受信データ
End Type
Dim MyCom As com
'データの受信
Private Sub MSComm1_OnComm()
'受信データ
Static strInputData As String
'受信+データ連結
strInputData = strInputData & MSComm1.Input
If Right(strInputData, 1) = vbCr Then
'データの区切りが来た
MyCom.strReciveData = strInputData 'データのコピー
strInputData = vbNullString 'データバッファの初期化
ShowData 'データ表示
'データーが返ってきたので次のコマンドを出す。
MyCom.boolComBusy = False
End If
End Sub
'データ表示
Private Sub ShowData()
If MyCom.strCommand = FCOMMAND Then
Label9.Caption = MyCom.strReciveData
ElseIf MyCom.strCommand = QCOMMAND Then
Label20.Caption = MyCom.strReciveData
End If
End Sub
Private Sub Timer1_Timer()
'データーが完全に返るまで送信コマンドは送らない
If Not MyCom.boolComBusy Then
'前のコマンドを見て次のコマンドを出す
If MyCom.strCommand = vbNullString Or MyCom.strCommand = QCOMMAND Then
MyCom.strCommand = FCOMMAND
ElseIf MyCom.strCommand = FCOMMAND Then
MyCom.strCommand = QCOMMAND
End If
MSComm1.Output = MyCom.strCommand
MyCom.boolComBusy = True
End If
End Sub
strReciveData は正しくは strReceiveData ですね。(^^;
詳しい回答ありがとうございます。
ご足労おかけして大変申し訳ありません。
我龍院さんのおかげでプログラムを完成させることができました。
私の知らない知識がまだまだたくさんあり勉強する部分が多く、我が身を一段階も二段階も成長することができましたのも我龍院さんのおかげです。
私も早く我龍院さんのレベルまで追いつけるように勉強していきたいと思います。
今回は助けていただいて本当にありがとうございました!
ツイート | ![]() |