• ベストアンサー

シリアル通信で0x00を送信したいのですが。

こんにちは、VC++初心者です。 現在、下記サイトのプログラムをもとにシリアル通信用プログラムを作成しています。 http://www.takebay.net/~daigo-ao/paddlewiki.pl/title_A5B7A5EAA5A2A5EBC4CCBFAE2852532D3233324329A4C7C1F7BFAEA1A6BCF5BFAEA4F2B9D4A4A6A5D7A5EDA5B0A5E9A5E0.html 例えば、editboxに02 31 32 33 03と入力したら、0x02 0x31 0x32 0x33 0x03として送信するところまではできました。 ただし、00と入力したとき、0x00として送信することができません。 どうすれば0x00を送信できるか、ご教授お願いいたします。 m_editSend.GetWindowText()にて入手したstrSendのデータから、SPACEを除いて、 0xをつけてhexにしてから、Send()にて送信しています。 void CSerial2Dlg::OnBnClickedButtonSend() { CString strSend; CString strSendCMD; CString bw; int i, n, i2; unsigned int hex; m_editSend.GetWindowText(strSend); // ポート名を取得 char *buff = new char[strSend.GetLength()+1]; if(strSend.GetLength() == 0 || strSend == " "){ //送るものが無ければ終了 AfxMessageBox("送信するコマンドがありません。"); } else{ strcpy(buff, strSend); //editboxのデータをbuff[]へコピー i = 0; n = 0; bw = "\0"; while (buff[i] != '\n'){ if( buff[i] == ' ' || buff[i] == ':' || buff[i] == ',')//SPEACEorコロンorカンマをSKIPして送信する。 else{ bw += buff[i];//2文字ためる n++; } if(n == 2){ sscanf(bw, "%x", &hex); //bwに2文字溜まったら、hexに変換 strSendCMD += hex; bw = "\0"; //変換が終わったらClear n = 0; //カウントもリセット } i++; } m_serial->Send(strSendCMD, strlen(strSendCMD)); } delete [] buff ; //bufferの開放 } 下記のプログラムで、 WriteFileにて送信しています。 void CSerialCommunication::Send(LPCSTR str, DWORD strLength) { if (m_hComm == NULL) { AfxMessageBox("COMポートが開かれていません"); return; } // ** 送信! ** DWORD dwWrite; // COMポートに送ったバイト数 WriteFile(m_hComm, str, strLength, &dwWrite, NULL); }

質問者が選んだベストアンサー

  • ベストアンサー
回答No.3

>普通、皆さんはシリアル通信の際、どのように変数使用していらっしゃるのでしょうか。 すでに回答にありますが、「文字列」が「NULL(0x00)終端」であることが問題の為、CString型は使えません。 char型配列のように内容に限らず(バイナリー)データとして扱える型を使用します。 質問のソースでは、 ・2桁の文字列を数値(バイナリー値)に変化する処理(sprinfのあたり) ・Send()の引数の型の変更 を行えば対処可能です。

cpptext
質問者

お礼

ご丁寧にまとめていただきましてありがとうございます。 理解が深まりました。 あとは参考書を読みながらがんばってみます。

すると、全ての回答が全文表示されます。

その他の回答 (3)

  • yamaj_biz
  • ベストアンサー率71% (10/14)
回答No.4

>普通、皆さんはシリアル通信の際、どのように変数使用していらっしゃるのでしょうか。 通常は固定電文を仕様化した上で通信を行うので、大概は構造体をごそっと送る方が多いですね。 ただ、質問されたようなケースでは(もちろん動的なエリア確保をする手もありますが…)、手っ取り早く全文字コードを送信する為には、変数「hex」(sscanfにて取得したデータ)を1文字ずつ送る手もありますね。 例: --------------- char  send[2]={0,0};   // 変数追加 // 中略 if(n == 2){  sscanf(bw, "%x", &hex); //bwに2文字溜まったら、hexに変換  send[0] = (char) hex;  m_serial->Send(send,1); // ここで1バイト送ってしまう  bw = "\0"; //変換が終わったらClear  n = 0; //カウントもリセット } // 後略 ---------------

cpptext
質問者

お礼

ご丁寧な説明ありがとうございます。 固定電文を仕様化してプログラムを作成したいところですが、 汎用性を持たせるために、あえてeditboxにいちいち電文を入れる様式でやっております。 char型でないと0x00は送信できないということも理解できました。 ご教示いただいた方法で挑戦してみます。 アドバイスありがとうございました。

すると、全ての回答が全文表示されます。
  • yamaj_biz
  • ベストアンサー率71% (10/14)
回答No.2

「CSerialCommunication::Send」はご自分で作られた関数ですので、このままでOKだと思います。 それよりも問題はCStringを使用している事にあります。 0x00(NULL)は文字列の終端として扱われますので、いくらCStringに追加しても文字数としては増えません。 例: --------------- CString strText; strText += '1'; strText += '2'; strText += '3'; strText += (char)0x00; strText += (char)0x00; strText += (char)0x00; ASSERT(strText.GetLength() == 3); // 3が返る --------------- 文字コードを全て送りたい場合にはCString以外の変数を使う事をお勧めします。

cpptext
質問者

お礼

ご回答ありがとうございます。 普通、皆さんはシリアル通信の際、どのように変数使用していらっしゃるのでしょうか。 データ通信をするのに、0x00が遅れないんでは制御すらできないので、なんとかプログラムを作り上げたいのですが。 お知恵を拝借できれば幸いです。

すると、全ての回答が全文表示されます。
  • goosyu
  • ベストアンサー率58% (36/62)
回答No.1

 「CSerialCommunication::Send()」は文字列を送信する関数です。 0x00は文字ではない為,送信できません。  送信するデータに0x00が含まれている場合はその時点で文字列終端(\0)と同じ意味になります。 どうしても文字ではない,0x00を送信するのであればバイナリデータを送信する関数をクラスに追加するか,別途バイナリ送信に対応したシリアル通信用プログラムを用意するしかありません。また,メインソースのstrSendCMDもバイナリデータが扱える配列に変更する必要があります。

cpptext
質問者

お礼

早速のご回答ありがとうございました。 配列を使うのですね。 アドバイスありがとうございました。

すると、全ての回答が全文表示されます。

関連するQ&A