MSCommで通信しています。ヘルプを見たのですが
書いてなさそうでしたので、質問させてください。
MSCommでバイナリデータをやりとりさせています。
英数字などの半角(1バイト)文字は送信するとこまでは行ったのですが、
漢字などのWバイト(2バイト)の文字は、文字の前半部分(1バイト目)を
送信すると半角スペースになってしまいます。
(Wバイトの両方を続けて送ると送信できます。)
VBの仕様なのかMSCommの仕様なのか分かりませんが、
どなたかMSCommについて詳しい方、教えてください。
よろしくお願いします。
InputMode プロパティはcomInputModeBinaryで、
送信はバイト配列で行っているんですよね?
送受信をどのように書かれているのですか?
あき☆彡様、相談にのっていただいてありがとうございます。
> InputMode プロパティはcomInputModeBinaryで、
> 送信はバイト配列で行っているんですよね?
InputModeはBinary設定してますが、
送信はバイト配列にしてませんでした。
実は昔のCで書かれたサーバーとの通信をやっているのですが、
英数字とWバイトの文字との混合データを送信したいのです。
<DLE><STX><01>・・・<DLE><ETX>CRC '<01>はブロックナンバー
<DLE><STX><02>・・・<DLE><ETX>CRC
という規則に従って送るのですが、
・・・の部分は256バイトで送らないとエラーになります。
そこで、英数字は1バイトで計算できるのですが、
文字の場合は2バイトで計算するのがややこしいんです。
というのも、256バイトで切るとどうしても最後の文字(Wバイト)が
1バイトになってしまうため、Wバイトを切り離して送る必要が
あるのです。ところがWバイトを1バイトづつにした場合、
MSCommでそれを表現すると半角のNULLになってしまいます。
CRCの計算もさせたいのですがそれも無理でして・・・。
でもその前に、MSCommでWバイトの半分の1バイトを
送信できるかが疑問でしたので質問させていただきました。
ややこしい説明ですが、お分かりいただけましたでしょうか?
ご存知でしたら教えてください。
よろしくお願い致します。
Hex関数で送信対象データをバイナリ変換し、
・・・の部分を256Byteにセットするのはダメなのでしょうか?
Dim バイト配列()as Byte
Dim I as Long
バイト配列()= ”あ”
For I = 0 TO データサイズ
送信1バイトデータ = Hex(バイト配列(I))
送信256バイトデータ = 送信256バイトデータ & 送信1バイトデータ
If I Mod 256 = 0 Then
Call 256時の処理
End If
Next
あんちゃんさんご返答ありがとうございます。
バイト配列ってのがよく分かりませんが、
以下のように書いてみました。
strBuffにファイルから読み込んだ文字列を代入し、
それを変換させています。一応全角文字で変換できてそうです。
間違っていたらまた教えてくださいm(__)m
ただ、strBuffに"12345あいうえお"という文字列が入ったときは
以下のコードで正しいのかが分かりません。
「1」が「310」と2バイトで変換されてしまいますが、
それでも正しいのでしょうか?
またまたよろしくお願いします。
***************************************************
Private Sub Btn_byte_Click()
Dim Byte_line() As Byte
Dim I As Long
intFno = FreeFile
Open strFname For Input As #intFno
Line Input #intFno, strBuff
Close #intFno
Byte_line() = strBuff
For I = 0 To LenB(strBuff) - 1
Byte01data = Hex(Byte_line(I))
Byte256data = Byte256data & Byte01data
Debug.Print Hex(Byte01data)
If I Mod 256 = 0 Then
' MSComm2.Output = Byte256data
Debug.Print Byte256data
End If
Next
***************************************************
相手先にはバイナリデータで送信できれば問題ないという事ですよね?
相手先はバイナリデータを見て、”全角文字””半角文字”を識別していると思いますので
送信側の対応として
1.送信元データを全てバイナリデータに変換する
2.256Byte単位にデータをまとめ伝送用のパーツ(<DLE><STX><CRC>など)と結合
3.該当データ(256+αByte)を伝送プログラムに乗っける
4.2、3を繰り返す
こんな感じになるのではないでしょうか?
Private Sub Btn_byte_Click()
Dim Byte_line() As Byte ’全読込データ格納
Dim I As Long ’1Byte単位に処理する
Dim ReadSize As Integer
const ReadByte as Integer = 1 ’先頭からデータを読む
’∽∽∽ FD読込(全データのバイナリ値を取得) ∽∽∽
ReadSize = FileLen(strFname)
ReDim Byte_line(0 To ReadSize - 1) ’ファイルサイズ取得
intFno = FreeFile
Open strFname For For Binary As #intFno
Get #1, ReadByte, Byte_line
Close #intFno
’∽∽∽ データ処理 ∽∽∽
For i = 0 To ReadSize - 1
Byte01data = Hex(Byte_line(I)) ’バイナリデータ(1Byte)取得
Byte256data = Byte256data & Byte01data ’256Byteまで加算
Debug.Print Hex(Byte01data)
’∽∽∽ 伝送関係 ∽∽∽
If I Mod 256 = 0 Then ’256Byteの確認
' MSComm2.Output = Byte256data
Debug.Print Byte256data
伝送プログラム(256Byte単位)
End If
Next
End Sub
1Byte文字、2Byte文字を判別する処理についてですが、
これはどうしても必要なのでしょうか?
伝送の事を考えると難しくなると思います。
Get #1, ReadByte, Byte_line
↓
Get #intFno, ReadByte, Byte_line
’∽∽∽ 伝送関係 ∽∽∽
If I Mod 256 = 0 Then ’256Byteの確認
' MSComm2.Output = Byte256data
Debug.Print Byte256data
Byte01data = "" ’クリア
Byte256data = ""
伝送プログラム(256Byte単位)
End If
あんちゃんありがとうございます。
こんなに全部書いていただいて恐縮です。
昨日それを試してみたのですが、全部HEXにすると、
その数字が<DLE>や<STX>と被ってしまうため、エラーになりました。
現状では、以下のように送っています。
*********************************************************************
MSComm1.Output = Chr(&H10) & Chr(&H2) & Chr(lngLoop + 1) & Chr(&HFC) _
・・・文字列(数値+Wバイト文字)・・・Chr(&H10) & Chr(&H3) & CRC
*********************************************************************
※lngLoopはループナンバー
※DLE = Chr(&H10),STX = Chr(&H2),ETX = Chr(&H3)
このようにすると、Wバイト文字を半分にした時と同様、
Chr(&HFC)は半角のNULLに変化してしまい、通信エラーになります。
HEXで送れば何とかなると思ったのですが、Chr(&H・・)の形が
送れたらと思うのですが、お分かりになりますか?
例えば「あ」はバイナリで「82 A0」ですが、
それをChr(&H82)とChr(&HA0)に分けると半角のNULLになってしまいます。
それはVBが漢字コードを認識した場合、半分の1バイトでは処理できず、
半角NULLにしてしまうのかと思っているのですが、
そこらへんもお分かりでしたらご教授願いたいのですが・・・。
よろしくお願いいたします。
>VBが漢字コードを認識した場合、半分の1バイトでは処理できず・・・
1バイトでは何の文字か判断できないのでは?
送信データが1バイト余る場合は、ダミーデータ(1バイト)を付加するのも
1つの手段と思えます。
この手の方法はダメでしょうか?
’バッファ(Byte配列)
バッファ(0) = CByte(&H2) 'STX
バッファ(1) = ・・・他のコマンド
バッファ(2) = ・・・他のコマンド
バッファ(n) = Byte256data
バッファ(?) = ・・・他のコマンド
・
・
MSComm1.Output = バッファ
Do While MSComm1.OutBufferCount <> 0
Loop
あんちゃんさん何度もありがとうございます。
> 1バイトでは何の文字か判断できないのでは?
236バイトで切っただけでは何の文字か判別できませんが、
全部で2300バイトあるため、次のパケットで送られてくる1バイトと
合わせて1文字にするようです。(なんとややこしい・・・)
そこで、VBでは漢字コードの最初の1バイトだけにすると
NULLになってしまうので、vbFromUnicodeなどに変換し、1バイト
取ったとき、その値が漢字コードの最初の1バイト目であれば、
保持しておく必要があります。いろいろ調べたところ、どうやら
VB(MSComm)では実現不可能っぽいのです。ActiveCommとかいうのを
入れると(有償)、漢字コードの1バイト目を送ることができるらしく、
3パケット目のブロックナンバーの反転文字であるChr(&HFC)も
それで送ることができました。ただ、それは決まった文字であるから
送る場所なりタイミングを決めることができますが、
256バイトで切れた漢字コードはChr()ではない何かのコードで
保持しておかなくてはならないっぽいのです。
つまり、漢字コード表というのを別で設けて、それと一致したものは
16進数などに変換しておいておき、送信するときにその1バイトだけ
アウトプットしてあげないと・・・。VBってそんなややこしい・・・。
って、とこまで分かったのですが、それを作るのは一苦労ですよね・・・。
でも仕事なんで仕方ないんです・・・。
後の課題は、vbFromUnicodeで切り取った漢字コードの1バイト目を、
どのように保持しておくかです。vbUnicodeではない何かで・・・。
更にそれを最終的にChr()に戻してあげる作業が発生します。
それって可能ですかね?
送信先のデータ形式、256(データ)+256(データ)+256(データ)………
でしょうか?
この状態で変更をと考えると少々難しいかと思います。
受信側は識別プログラムを入れることは可能なのでしょうか?
可能なら、ヘッダ部とデータ部に分けることをオススメします。
識別プログラムはヘッダ部をみて、データ部を変換(Chr()に戻す)します。
あんちゃんさんいつもありがとうございます。
お礼が遅れて申し訳ございません。
いろいろ試してみたのですが、ようやく解決しました!
やはり、MSCommでの1バイト送信はバイト配列に格納することでした。
半角英数+Wバイトの混合文字列を、vbFromUnicodeに変換し、
それをバイト配列でしかも16進数に変換・・・
以下のコードで可能になりました。
**********************************************************
strBuff = (半角英数+Wバイトの混合文字列)
strSendWork = strConv(strBuff,vbFromUnicode)
If LenB(strSendWork) >= 256 Then
strBuff = LeftB$(strSendWork, 256)
strSendWork = MidB$(strSendWork, 257)
Else
strBuff = strSendWork
End If
Length = LenB(strBuff)
For cnt = 1 To Length
'1バイト取り出して、文字コードに変換
Ascii = AscB(MidB(strBuff, cnt, 1))
If ascii <> 0 Then
' 文字コードを16進数の文字列に変換
chgHex = Right("00" + Hex(Ascii), 2)
End If
PacketData(0) = "&H" & chgHex
MSComm2.Output = PacketData
Next cnt
**********************************************************
バイト配列にした後、Chr(&H??)の形にするのではなく、
"&H" & chgHex(変数)で実現可能となりました。
上記の If ascii <> 0 Then の部分が怪しいですが、
とりあえずはこれで通過いたしました。
今までありがとうございました。
本当に助かりました。また何かあったら
ご教授お願いいたします m(__)m