質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

2回答

4286閲覧

pc plc間通信

xasax0404

総合スコア27

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2016/10/24 07:18

plcから送信された文字列をpcで表示させるといった簡単なことができません。。。
////////////////////////////////////
pcからplcへbw命令を送信

bw命令を受信したplcが設定した文字列("00ff0001")をオンデマンドで送信

pcが受信・表示
////////////////////////////////////

以下プログラム
///////////////////////////////////
sprintf(SndBuf, "\0");
strcat(SndBuf, "\005");
strcat(SndBuf, "00FFBWAM00");
strcat(SndBuf, "71");
strcat(SndBuf, "011");
strcat(SndBuf, "\r\n");
printf("%s\n", SndBuf);

OVERLAPPED ovWriteS; memset(&ovWriteS, 0, sizeof(ovWriteS)); if (WriteFile(Rs232c2, SndBuf, strlen(SndBuf), &dwSize, &ovWriteS) == FALSE){ printf("RS232C WriteFile Error\n"); return -1; } else{ // 送信成功 printf("RS232C WriteFile Success\n"); } memset(SndBuf, 0, sizeof(SndBuf)); //データ受信 (初期) // COMポートの受信イベント作成 OVERLAPPED ovReadZ; memset(&ovReadZ, 0, sizeof(ovReadZ)); ovReadZ.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); if (ovReadZ.hEvent == NULL){ printf("RS232C CreateEvent Error\n"); return -1; } // COMポートの受信イベントマスク if (SetCommMask(Rs232c2, EV_RXCHAR) == FALSE){ printf("RS232C SetCommMask Error\n"); return -1; } // COMポートの受信待ち DWORD EvtMask = 0; DWORD Transfer = 0; if (WaitCommEvent(Rs232c2, &EvtMask, &ovReadZ) == FALSE){ if (GetLastError() == ERROR_IO_PENDING) { GetOverlappedResult(Rs232c2, &ovReadZ, &Transfer, TRUE); } else{ printf("RS232C WaitCommEvent Error\n"); return -1; } } // COMポートの受信イベントチェック if ((EvtMask & EV_RXCHAR) == EV_RXCHAR){ // COMポートの受信データチェック COMSTAT comstZ; DWORD dwErrZ; ClearCommError(Rs232c2, &dwErrZ, &comstZ); // COMポートからデータ受信 if (ReadFile(Rs232c2, RcvBuf, comstZ.cbInQue, &dwSize, &ovReadZ) == FALSE){ printf("RS232C ReadFile Error\n"); return -1; } else{ // 受信成功 printf("通信可能です\n"); } } memset(SndBuf, 0, sizeof(SndBuf)); memset(RcvBuf, 0, sizeof(RcvBuf)); CloseHandle(ovReadZ.hEvent);

////////////////////////////////////////////////////////////////イメージ説明
このように最後の"通信可能です"まで出ているので何かしら受信はできているのに表示がうまくいきません。。。
どなたかご教授お願いします

ちなみに、プログラムではなく、テラタームでなら00ff0001は表示の確認は出来ています。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

// 受信成功 のところで、RcvBufの中身を表示したいけどうまくいかない、という質問でしょうか。
本来ならうまくいかないコードを提示してもらいたいところですが、とりあえず回答してしまいます。

RcvBufの型がわからないので、char型と仮定します。

まずは単純に、

c

1printf("%s\n",RcvBuf);

これで表示されないのであれば、何が原因かを探る必要があります。

c

1printf("comstZ.cbInQue=%d\n",comstZ.cbInQue); 2printf("dwSize=%d\n",dwSize); 3for(int i = 0; i < dwSize; i++){ 4 printf("%02x,",RcvBuf[i]); 5} 6printf("\n");

これくらい出しておけば、何バイト受信出来ていて、何がRcvBufに格納されているかわかるでしょう。

投稿2016/10/24 08:02

ttyp03

総合スコア16996

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

xasax0404

2016/10/24 08:34

すみません、printf("%s\n",RcvBuf);をした結果が実行画面です。
ttyp03

2016/10/24 08:56

提示のコードにはなかったので書いたまでです。 表示できていないときの確認方法も書いてますので、お試しください。
xasax0404

2016/10/26 00:46

上記の方法を試してみました。結果、comstZとdwsizeは5,rcvbufは{06,30,30,46,46}と表示され、10進数で6,48,48,70,70となりました。勉強不足でこの結果からピンと来ないのですがどうなっているのでしょうか。。。 
ttyp03

2016/10/26 00:56

アスキーコード表をご覧ください。 http://www9.plala.or.jp/sgwr-t/c_sub/ascii.html 最初の0x06は「ACK(受信OK)」ですね。 送信に対して正常に受信できたという相手からの応答と思われます。 次の0x30からが実際の応答文字列だと思います。 0x30='0' 0x46='F' つまり"00FF"が返ってきているようですね。
xasax0404

2016/10/26 01:23

なるほど。。。 という事はPLCからの送信内容{00ff0001}の00ffまで受け取れているということですね!そして受信したバイト数は5であるので0001まで表示されないという解釈でよろしいですか?この解釈ならどんづまりですけどね。。。
ttyp03

2016/10/26 01:26

シリアル通信なので、おそらく一気に受信できるわけではなく、また続けてReadFileすれば後続のデータが受信できると思います。 ClearCommError関数で、comstZ.cbInQueが0になるまでループさせればいいんじゃないですかね。
xasax0404

2016/10/26 02:23

if (ReadFile(Rs232c2, RcvBuf, comstZ.cbInQue, &dwSize, &ovReadZ) == FALSE){ printf("RS232C ReadFile Error\n"); return -1; } else{ // 受信成功 printf("%s\n",RcvBuf); printf("通信可能です\n"); } を3回書いたら、1回目00ffと通信可能です。2回目00feと通信可能です。3回目0001と通信可能です。でした。しかし、00feの最初と0001の最後に文字化けのようなものがくっついています。00feの1番目の0の前にはLを逆にしたような物が、0001の最後の1の後にはLのようなものがあるんです。判断させるときに邪魔なので知りたいのですがわかりますでしょうか?
ttyp03

2016/10/26 02:32

先ほどのACKと同じように、何か制御コードが送られてきているのではないでしょうか。 また16進数で表示してみればわかると思います。 というかplcのマニュアルか何かに、どういった手順で何が送信されるかという説明はないのでしょうか。
xasax0404

2016/10/26 02:46

0x03というテキスト終了コードでした。 そうなんです。plc送信は自分が担当していなくて、作成者が文字型とだけしか分からないらしいので手順等は分からないんです。。。
ttyp03

2016/10/26 02:52

そうですか…。では解析しながら進めるしかないですね。 これまでの情報でだいたい次のような感じの実装にすれば良いと思われるのでお試しください。 (1)送信 (2)ACKを待つ。NAKが来たら再送。 (3)ETXが来るまで受信を続ける。 ETXが来るということはSTXも来てそうですが、そこらへんも再度確認しつつ実装してみてください。
xasax0404

2016/10/26 06:07

わかりました。自分は最後のテキスト終了コードをNULLにすることで消しました。 判断するには十分なのでこれでいこうと思います。ありがとうございました。
guest

0

こんにちは。

RcvBufに返ってきているように思います。
RcvBufの内容を表示してみてはどうでしょう?
受信したバイト数はdwSizeに入っています。

ただ、同期通信しているのにOVERLAPPEDを指定しているのは気になります。その辺りの制御が間違っているようです。
第107章 オーバーラップ・ファイルI/O その1が参考になると思います。

後、ソースは、質問欄の上の方にある<code>を押して出て来る'''の間に貼り付けて貰った方が助かります。インデントを付けることができるようになりますし、#includeなども適切に表示されます。
このあたりはteratailのヘルプにかかれてますので一度目を通されると良いと思いますよ。

投稿2016/10/24 08:02

Chironian

総合スコア23272

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

xasax0404

2016/10/24 08:34

すみません、printf("%s\n",RcvBuf);をした結果が実行画面です。
Chironian

2016/10/24 08:53

そのコードはどこに書いてます? 提示されているソースには記載がないようです。 memset(RcvBuf, 0, sizeof(RcvBuf));より後に書いてたら、当然何も出ないです。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問