- 締切済み
C++Builder6.0でのシリアル通信
つい先日より、C++Borland6.0を用いて、シリアル通信で外部機器とのやりとりを行なえるものを作成することになりました。 これまで、VBでのシリアル通信は行なったことがあるのですが…同様に考えていたのですがC言語が初心者なためまったくと言っていいほど今回のものはわかりません。 そこで、色々なサイトを探した結果、文字数&送信文字を限定すれば送信でき、受信バイト数を限定すればできるものが出来上がりました。(サイトのものをほぼそのまま活用している感じですけど) しかし、 1、ボタン1を押すと「Edit1に書かれているものに<CR><LF>を加えたものを送信したい」 2、ボタン2を押すと「Edit2に書かれているものに<CR><LF>を加えたものを送信したい」(1と2は、送信バイト数が違うため、送信バイト数で引っかかる) 3、「受信文字数は、受信バイト数を指定ではなく全てを受信したい」 4、「受信したものを<CR><LF>で分けたい」 などになるとさっぱりできません。 「?Ver<CR><LF>」と送ると「*.**<CR><LF>」と外部機器から返ってきて、 「?PARAMETER<CR><LF>」と送ると「PARAMETER 1=***<CR><LF>PARAMETER 2=***<CR><LF>PARAMETER 3=***<CR><LF>OK<LF>」と外部機器から返ってくるとします。 現在のソースは回答1,2に書きます。ボタン1を押すと送信され、受信されたものをメモに加えられるというものになっています。 これを、上に書かれているような4つの機能を加えたものにしたいのですが…。 (?PARAMETERに関しては送信文字数が合わずにできなかったため、ソースに記入しておりません。また、通信設定に関しては省略しております) ご教授くださる方おりましたらよろしくお願いします。
- みんなの回答 (4)
- 専門家の回答
みんなの回答
- 麻野 なぎ(@AsanoNagi)
- ベストアンサー率45% (763/1670)
> while (pszBuf[ptr++] != "\x0a"); > pszBuf[ptr - 2] = "\0"; この部分、" ではなくて、' です。 while (pszBuf[ptr++] != '\x0a'); pszBuf[ptr - 2] = '\0'; C++ では、'a' と "a" は別物ですので、ご注意ください。(おおざっぱに言えば、文字列をくくるのが、" " で、1文字をくくるのが ' ' です。ただ、"a" のように、1文字からなる文字列もあったりします)
- 麻野 なぎ(@AsanoNagi)
- ベストアンサー率45% (763/1670)
ちょっと知り合いを拝み倒してきました。 http://www.asahi-net.or.jp/~ig5k-fjhr/tec/ifline.h http://www.asahi-net.or.jp/~ig5k-fjhr/tec/winrs.h http://www.asahi-net.or.jp/~ig5k-fjhr/tec/winrs.cpp なんかいかがでしょうか? #include "winrs.h" でインクルードすると、WinRS というクラスが使えるようになります。 詳細は、WinRS.h を読んで、解読してください。 一応、 WinRS *port = new WinRS(1, 9600); で、COM1 を 9600bps, データ区切りは、crlf として開きます。 これで、 port->talk(Edit1->Text.c_str()); とすれば、Edit1 内容に、勝手に crlf を付加して送信します。 char buff[1024]; unsigned int len = 1024; // これは、受信できる「最大」バイト数の設定 を使って、 port->talk(buff, len); とすると、buff のなかに、crlf までのデータを(crlf をはじいて)持って帰ってきます。 帰ったときには、len の中に、実際に取得したバイト数が入っています。 くれぐれも「無保証」だそうですが。
- 麻野 なぎ(@AsanoNagi)
- ベストアンサー率45% (763/1670)
まず、<CR><LF> は、私は、それぞれ、'\x0d' '\x0a' を使います。 '\n' の取り扱いにちょっと不安があるので。 Write( "?Ver\r\n" ); //←Edit1の内容+<CR><LF>で送れるようにしたい ↓ Write( (Edit1->Text + "\x0d\x0a").c_str()); if(hCom != NULL){ fResult = WriteFile(hCom, pszBuf, 6, &dw, NULL); //↑固定数ではなく送信する文字数に変更したい ↓ #include <cstring> fResutl = WriteFile(hCom, pszBuf, std::strlen(pszBuf)), &dw, NULL); あと、受信文字数を規定しない=受信パラメータの区切りがはっきりしているということですね。 そうでなければ、何処まで受信して良いかわからないので。 この場合、「1バイトずつ受信して、'\x0d\x0a' で区切る」でしょうか。 if(ReadFile( hCom, pszBuf,7, &dw, NULL )){ //←固定数ではなく全てに変更したい ↓ int ptr = 0; do{ ReadFile(hCom, pszBuff[ptr++], 1, &dw, NULL) }while (pszBuff[ptr - 1] != '\x0a'); // ここまで来ると、受信文字列+"\x0d\x0a" になっている pszBuff[ptr - 2] = '\0'; // '\x0d' が入っているはずのところに、ターミネータを入れる 概ね、こんな感じでしょう。
- taka-sh_march
- ベストアンサー率0% (0/0)
質問者です。友人からID借りてます。初期省略。 void __fastcall TForm1::Button1Click(TObject *Sender) { char buf[256]; FChPort = 1; Write( "?Ver\r\n" ); //←Edit1の内容+<CR><LF>で送れるようにしたい Read(buf); Memo1->Lines->Add(buf); //<CR><LF>以前までの文字を取り出して記入したい。 //それ以降の文字はMemo2へ CommClose(); } BOOL Write(LPCSTR pszBuf) { DWORD dw; BOOL fResult = FALSE; if(hCom != NULL){ fResult = WriteFile(hCom, pszBuf, 6, &dw, NULL); //↑固定数ではなく送信する文字数に変更したい if(fResult) fResult = (dw==(DWORD)lstrlen(pszBuf)); } return fResult; } DWORD Read(LPTSTR pszBuf) { DWORD dw; DWORD dwErrors; COMSTAT ComStat; DWORD dwResult = 0; if(hCom != NULL){ if(ReadFile( hCom, pszBuf,7, &dw, NULL )){ //←固定数ではなく全てに変更したい pszBuf[dw]=0; dwResult=dw; } } return dwResult; }
補足
回答ありがとうございました。早速試したところ、無事送信ができました! 受信のほうでエラーが発生してしまうのですが、 }while (pszBuf[ptr++] != "\x0a"); pszBuf[ptr - 2] = "\0"; 上記箇所で 'char'型は'char*'型に変換できない。また、その逆のエラーが出てしまいます。 これはシリアル通信云々ではなく、受渡しの部分とは思いますが、まだまだその辺すら理解出来ておらず修正できません。よろしければ教えてください…。 また、受信の最後は必ず"\x0a"になります。