タイトル : Re: VB シリアル通信で受けた文字列を配列に格納したい 投稿日 : 2017/08/31(Thu) 15:55 投稿者 : 魔界の仮面弁士
> No1868でお助けいただき順調に進めてきたのですが それを言うなら No11868 ですよね。 No1868 は下記ですが、レスはついていないようで。 [2005/07/01 15:04](aa さん)【VBからエクセルのシートにラベルを作成】 http://www.hanatyan.sakura.ne.jp/vbnetbbs/wforum.cgi?mode=allread&no=1868 > SerialPort1.Read(receivedData, 0, receivedData.L使い方ength) 化けてますね。(^^; > 最後に書き込んだBandRegSTR(3,3)は以下のように格納されています 各行のインデックスが不明ですが、こういう状態なのでしょうか? BandRegSTR(0, 0) = "1" BandRegSTR(0, 1) = "2" BandRegSTR(0, 2) = "3" BandRegSTR(0, 3) = "1" BandRegSTR(1, 0) = "2" BandRegSTR(1, 1) = "3" BandRegSTR(1, 2) = "3 FD23000085080085080000000203000702000(以下略)" BandRegSTR(1, 3) = Nothing BandRegSTR(2, 0) = Nothing BandRegSTR(2, 1) = Nothing BandRegSTR(2, 2) = Nothing BandRegSTR(2, 3) = Nothing BandRegSTR(3, 0) = Nothing BandRegSTR(3, 1) = Nothing BandRegSTR(3, 2) = Nothing BandRegSTR(3, 3) = Nothing > Dim StrCov As String = BitConverter.ToString(data).Replace("-", "") > Dim Lenx As Integer = Len(StrCov) > For i = 1 To Lenx Step 2 > DD = Mid(StrCov, i, 2) > RecStr = DD & RecStr > Next おそらくは、 Dim data As Byte() = {1, 2, 3, 4, 5, 6, 7, 8, 9} というデータがあった場合に、 Dim RecStr As String = "090807060504030201" を得ることが目的なのだと思いますが、それならばループ処理などせずとも、 Dim RevData As Byte() = data.Reverse().ToArray() Dim RecStr As String = BitConverter.ToString(RevData).Replace("-", "") だけで済みますよ。 あるいは、data そのものの順番も逆転して良いのであれば、 Array.Reverse(data) Dim RecStr As String = BitConverter.ToString(data).Replace("-", "") と書くこともできます。 > X = RecStr.IndexOf("011A6600FEFE") ' 条件 2 この検索方法だと、4bit 分の桁ずれが生じる可能性がありそうですが、大丈夫でしょうか? RecStr = "11A6600FEFE000" 'X = -1 が返される(想定どおり) RecStr = "011A6600FEFE00" 'X = 0 が返される(想定どおり) RecStr = "0011A6600FEFE0" 'X = 1 が返されるが、本来は X = -1 になるべきでは? RecStr = "00011A6600FEFE" 'X = 2 が返される(想定どおり) RecStr = "00011A6600FE00" 'X = -1 が返される(想定どおり) あえてそういう仕様にしているのならば良いのですが、もしもそうではなく、 1 バイト単位(16進数表現で 2 文字分)の位置を調べたかったのであれば、 たとえば BitConverter の "-" をあえて潰さずに、 Dim RevData As Byte() = data.Reverse().ToArray() Dim RecStr As String = "-" & BitConverter.ToString(RevData) X = RecStr.IndexOf("-01-1A-66-00-FE-FE") Y = RecStr.IndexOf("-FD") のように探索するという手もあります。これなら桁ズレは発生しません。 この方法では、1 バイトが 2 文字ではなく 3 文字で表現されているので、 変数 X (と Y) の使いみちによっては、上記の後に追加で If X >= 0 Then X = 2 * X \ 3 End If のような補正が必要かも知れません。適宜調整してください。 > If CC > 40 And X > 10 Then And 演算子ではなく、AndAlso 演算子を使う癖をつけましょう。 > 疑問1 何故 最後の配列変数のみにまとめてを格納されるのでしょうか > どこで6個の文字列を連結されるのでしょうか ここが原因? 『BandRegSTR(n,m) に文字列を格納する処理』が書かれているのは、 > If CC > 40 And X > 10 Then > BandRegSTR(BandRegBandNo, BandRegOld) = BandRegOld & RecStr > End If の部分だけなのですね。であればこの部分を If CC > 40 AndAnslo X > 10 Then Debug.Write(BandRegBandNo) Debug.Write(", ") Debug.Write(BandRegOld) Debug.Write(" = 文字数:") Debug.WriteLine((BandRegOld & RecStr).Length) BandRegSTR(BandRegBandNo, BandRegOld) = BandRegOld & RecStr End IF のように書き換えて、それぞれの変数(特に BandRegBandNo と BandRegOld)の値が どの時点で期待から外れた値になってしまうのか、出力ウィンドウで確認してみましょう。 > 疑問2 コマンドをPortに書き込む間隔を System.Threading.Thread.Sleep(200)で > 制御しないとまったく取り込めないのですが SerialPort1.Read はそうした > 動きをするものでしょうか 何か他の方法で確実に受け取ることはできないもの > でしょうか(時間200が最適かは試していませんがこの使い方は正しいでしょうか) 正しい使い方ではありません。 コンソール アプリケーションで Sleep を呼ぶような使い方は OK ですが、 UI スレッド(Form/Button/TextBox などを利用するスレッド)から Sleep メソッドを呼び出すことは タブー です。 そもそも Sleep は待機のための命令ではなく、自分自身を一定時眠らせることで、 処理を他のスレッドに明け渡すことを目的としています。 対処方法としては: (対処案A) メインスレッドから書き込むために、 Timer を使って Tick イベントから Write する。 (対処案B) 送信処理専用のワーカースレッドを用意し、 その中で Sleep で待ち合わせて Write する。 > お願い コマンンドを書き込む方法 下記コード ***1 以降はもっとスマートに > できないものでしょうか 9×3 で27回分を記述しなければなりませんので 下記を見る限り、それぞれの変更箇所は一部分だけなのですよね? > 以下 配列のBandRegBandNo BandRegOld と > RbytOut(6) = &H2 > RbytOut(7) = &H2 を変更するのみなので内容は省略します その場合、それぞれの差異となる部分のみを切り出して、 それを引数として渡すようにすれば、処理をまとめることができるでしょう。 BandRegInfGet( データ1, データ2, … ) 引数を使う方法では、渡すデータが多くなりすぎるというのであれば、 データ受け渡しのためのクラス(または構造体)を設けて、 Dim arg As New Hoge() arg.SetOut(6, &H2) arg.SetOut(7, &H2) : BandRegInfGet( arg ) などという構成にすることもできるかと思います。 そして、その引数セットが 27 回あるというのなら、 Dim args(0 To 26) As Hoge などで管理しておけば済むでしょう。 また、送信するコマンド情報は、現在のコード内に埋め込んでおく方法のほか、 外部ファイルなどから読み込ませる方式にするということもできるかと思います。 |