MSCOMMでWバイトの半分だけを送信するには?

解決


すーさん  2002-08-14 19:07:34  No: 104688  IP: [192.*.*.*]

MSCommで通信しています。ヘルプを見たのですが
書いてなさそうでしたので、質問させてください。

MSCommでバイナリデータをやりとりさせています。
英数字などの半角(1バイト)文字は送信するとこまでは行ったのですが、
漢字などのWバイト(2バイト)の文字は、文字の前半部分(1バイト目)を
送信すると半角スペースになってしまいます。
(Wバイトの両方を続けて送ると送信できます。)
VBの仕様なのかMSCommの仕様なのか分かりませんが、
どなたかMSCommについて詳しい方、教えてください。
よろしくお願いします。

編集 削除
あき☆彡  2002-08-14 22:31:05  No: 104689  IP: [192.*.*.*]

InputMode プロパティはcomInputModeBinaryで、
送信はバイト配列で行っているんですよね?

送受信をどのように書かれているのですか?

編集 削除
すーさん  2002-08-14 23:12:12  No: 104690  IP: [192.*.*.*]

あき☆彡様、相談にのっていただいてありがとうございます。

> 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バイトを
送信できるかが疑問でしたので質問させていただきました。
ややこしい説明ですが、お分かりいただけましたでしょうか?
ご存知でしたら教えてください。
よろしくお願い致します。

編集 削除
あんちゃん  2002-08-15 11:36:57  No: 104691  IP: [192.*.*.*]

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

編集 削除
すーさん  URL  2002-08-15 13:35:22  No: 104692  IP: [192.*.*.*]

あんちゃんさんご返答ありがとうございます。
バイト配列ってのがよく分かりませんが、
以下のように書いてみました。
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
***************************************************

編集 削除
あんちゃん  2002-08-15 14:44:43  No: 104693  IP: [192.*.*.*]

相手先にはバイナリデータで送信できれば問題ないという事ですよね?
相手先はバイナリデータを見て、”全角文字””半角文字”を識別していると思いますので

送信側の対応として
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文字を判別する処理についてですが、
これはどうしても必要なのでしょうか?
伝送の事を考えると難しくなると思います。

編集 削除
訂正  2002-08-15 14:50:06  No: 104694  IP: [192.*.*.*]

Get #1, ReadByte, Byte_line
          ↓
Get #intFno, ReadByte, Byte_line

編集 削除
訂正  2002-08-15 15:39:52  No: 104695  IP: [192.*.*.*]

’∽∽∽ 伝送関係 ∽∽∽
        If I Mod 256 = 0 Then                  ’256Byteの確認
'            MSComm2.Output = Byte256data
            Debug.Print Byte256data
            Byte01data = ""                    ’クリア
            Byte256data = ""
           
            伝送プログラム(256Byte単位)
            
        End If

編集 削除
すーさん  2002-08-16 10:04:11  No: 104696  IP: [192.*.*.*]

あんちゃんありがとうございます。
こんなに全部書いていただいて恐縮です。
昨日それを試してみたのですが、全部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にしてしまうのかと思っているのですが、
そこらへんもお分かりでしたらご教授願いたいのですが・・・。

  よろしくお願いいたします。

編集 削除
あんちゃん  2002-08-16 13:00:12  No: 104697  IP: [192.*.*.*]

>VBが漢字コードを認識した場合、半分の1バイトでは処理できず・・・
1バイトでは何の文字か判断できないのでは?
送信データが1バイト余る場合は、ダミーデータ(1バイト)を付加するのも
1つの手段と思えます。


この手の方法はダメでしょうか?

’バッファ(Byte配列)
バッファ(0) = CByte(&H2)   'STX
バッファ(1) = ・・・他のコマンド
バッファ(2) = ・・・他のコマンド
バッファ(n) = Byte256data
バッファ(?) = ・・・他のコマンド



MSComm1.Output = バッファ
Do While MSComm1.OutBufferCount <> 0
Loop

編集 削除
すーさん  2002-08-16 23:58:50  No: 104698  IP: [192.*.*.*]

あんちゃんさん何度もありがとうございます。

> 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()に戻してあげる作業が発生します。
それって可能ですかね?

編集 削除
あんちゃん  2002-08-19 17:27:34  No: 104699  IP: [192.*.*.*]

送信先のデータ形式、256(データ)+256(データ)+256(データ)………
でしょうか?
この状態で変更をと考えると少々難しいかと思います。
受信側は識別プログラムを入れることは可能なのでしょうか?
可能なら、ヘッダ部とデータ部に分けることをオススメします。
識別プログラムはヘッダ部をみて、データ部を変換(Chr()に戻す)します。

編集 削除
すーさん  2002-08-22 19:32:58  No: 104700  IP: [192.*.*.*]

あんちゃんさんいつもありがとうございます。
お礼が遅れて申し訳ございません。

いろいろ試してみたのですが、ようやく解決しました!
やはり、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

編集 削除