教えて! goo のコンテンツに対する取り組みについて

こんにちは、VC++初心者です。
現在、下記サイトのプログラムをもとにシリアル通信用プログラムを作成しています。
http://www.takebay.net/~daigo-ao/paddlewiki.pl/t …

例えば、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);
}

gooドクター

A 回答 (4件)

>普通、皆さんはシリアル通信の際、どのように変数使用していらっしゃるのでしょうか。


すでに回答にありますが、「文字列」が「NULL(0x00)終端」であることが問題の為、CString型は使えません。
char型配列のように内容に限らず(バイナリー)データとして扱える型を使用します。
質問のソースでは、
・2桁の文字列を数値(バイナリー値)に変化する処理(sprinfのあたり)
・Send()の引数の型の変更
を行えば対処可能です。
    • good
    • 0
この回答へのお礼

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

お礼日時:2009/08/18 17:04

>普通、皆さんはシリアル通信の際、どのように変数使用していらっしゃるのでしょうか。


通常は固定電文を仕様化した上で通信を行うので、大概は構造体をごそっと送る方が多いですね。
ただ、質問されたようなケースでは(もちろん動的なエリア確保をする手もありますが…)、手っ取り早く全文字コードを送信する為には、変数「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; //カウントもリセット
}

// 後略
---------------
    • good
    • 0
この回答へのお礼

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

お礼日時:2009/08/18 18:41

「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以外の変数を使う事をお勧めします。
    • good
    • 0
この回答へのお礼

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

お礼日時:2009/08/18 14:45

 「CSerialCommunication::Send()」は文字列を送信する関数です。


0x00は文字ではない為,送信できません。
 送信するデータに0x00が含まれている場合はその時点で文字列終端(\0)と同じ意味になります。

どうしても文字ではない,0x00を送信するのであればバイナリデータを送信する関数をクラスに追加するか,別途バイナリ送信に対応したシリアル通信用プログラムを用意するしかありません。また,メインソースのstrSendCMDもバイナリデータが扱える配列に変更する必要があります。
    • good
    • 0
この回答へのお礼

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

お礼日時:2009/08/18 14:44

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています

gooドクター

このQ&Aを見た人がよく見るQ&A

人気Q&Aランキング