- ベストアンサー
PICのシリアル通信のWIN_APIプログラムについて
PICとPCとのシリアル通信の WIN_APIプログラムについてどなたかご存知の方は教えてください. 現状,API関数を用いて,シリアル通信をできるようにプログラムを作成したのですが,送信はできるのですが,受信データが"C0"をPICから送付しているのに,"FFFFFFFC0"と受信されてしまいます. 先の"FFFFFFF"をとるにはどうしたらいいでしょうか? 現状:受信プログラム // シリアルポートに対する書き込み(PICに送信命令) WriteFile(hCom, w_com_Buf,lstrlen(w_com_Buf), &n, 0 ); // シリアルポートに対する読み込み ReadFile(hCom, s_com_Buf,1, &n, 0 ); mikroC上のUSARTターミナルでは送受信は適正で, 上記のプログラマで 送信はPIC側で受信していることは7SEGを使って確認しています. しかし,PC側では, s_com_Buf[0]には,"C0"が入ったり,"FFFFFFC0"が入ったりします. PICは現状,多チャンネルAD変換をしているため, 送信に対する受信データのやり取りができなくて困っています. どなたか先生教えてください.
- みんなの回答 (4)
- 専門家の回答
質問者が選んだベストアンサー
s_com_Bufの型がわからないのですが、unsigned charでしょうか。 確実に8bitしか読まなくていいなら FF と とってしまってもいいような気がします。
その他の回答 (3)
度々すみません。#2&#3です。 PC側の受信処理で受信完了まで受信処理を繰り返す場合ですが、 PIC側の不具合または、ハード障害(ケーブル不良、接続抜けなど)等 により受信ができない(受信バッファにデータが入ってこない)場合も考えられ、 受信処理が終わらない可能性もありますので、その対策として、 タイムアウト処理(設定した時間、受信がなければ受信処理を止めてエラー表示等を行なうなど) を設けた方がより安全かもしれません。 以上です。
お礼
丁寧に教えてくださりありがとうございます. 以下の回路で再度実験したところ,ほぼ,多チャンネルの受信ができるようになりました. PIC側にAD変換値を出力してから,終了命令として出力していたデータを消し,かつ,if文で"else"を"else if"にして,想定外なデータはPIC側からPC側へ送信しないようにしたらほぼ多チャンネル受信ができるようになりました.
すみません。#2です。 #2のコメント中の「■送信処理の例」と「■受信処理の例」に記述している下記2行、 DWORD dwErrorMask; COMSTAT comstat; は余分でした(コピペミスです)、無視して下さい。失礼致しました。m(__)m
お礼
丁寧に 教えてくださりありがとうございました.
こんにちは。 まず、PIC~PC間の通信プロトコル&通信仕様の詳細が判らないので、以下はすごく当てずっぽうな コメントになりますので 見当違い or 間違い などがあればすみません。 > 本来2chや3chのデータが入る変数に > 1chのデータが入るのですが, 上記の件ですが、 PC側の受信コマンド ReadFile( hCom, s_com_Buf, 1, &n, 0 ); で使用している受信バッファ "s_com_Buf" に前の受信データが残っている可能性はないでしょうか? PC側の送信コマンド WriteFile( hCom, w_com_Buf, lstrlen(w_com_Buf), &n, 0 ); でPICへ制御&設定コマンドなどを送信していると思われますが、 この送信コマンドを実行する前に、受信バッファをクリアした方が良いかもしれません。 ■受信バッファクリアの例 // 以下ではダミー受信を行なってアプリケーションより上位レベル(ドライバ側より)の受信バッファ // のクリアを行なっています。1回で掃けないかもしれないのでここでは最大4回リトライしています。 int cnt; BOOL bsts; DWORD dwLen; DWORD dwErrorMask; COMSTAT comstat; dwLen = 0; cnt = 0; do { ClearCommError( hCom, &dwErrorMask, &comstat ); bsts = ReadFile( hCom, s_com_Buf, sizeof(s_com_Buf), &dwLen, NULL ); cnt++; } while ( dwLen>0 && cnt<4 ); それと、送信コマンドおよび、受信コマンドを実行した後で、実際に送信または、受信が成功したか 否かの判定処理を行なった方が良いかもしれません。 ※失敗時には、リトライ送信などの処理を行なうようにする。 ■送信処理の例 BOOL bsts; DWORD dwLen; DWORD dwErrorMask; COMSTAT comstat; bsts = WriteFile( hCom, w_com_Buf, lstrlen(w_com_Buf), &dwLen, NULL ); if ( bsts ) { //送信成功時の処理 : : } else { //送信失敗時の処理 DWORD err = GetLastError(); : : } ■受信処理の例 BOOL bsts; DWORD dwLen; DWORD dwErrorMask; COMSTAT comstat; bsts = ReadFile( hCom, s_com_Buf, 1, &dwLen, NULL ); if ( bsts ) { //受信成功時の処理 //注1)実際に受信したデータ長は dwLen に入っているのでその値をチェックして受信の // 有無(成否)を確認した方が良いかもしれません。 //注2)期待する受信データが1回の受信コマンドで受信できるとは限らないので、規定の // データ長または、規定のデータ終端コードに達するまで、受信処理を繰り返すように // した方が良いかもしれません。 : : } else { //受信失敗時の処理 DWORD err = GetLastError(); : : } 以上です。参考になれば幸いです。
お礼
おしえてくれてありがとうございます. 命令が WM_TIME内ですので, do~while を使うと処理がとまってしまうので 外してやってみようと思います.
お礼
Gizensha 先生 ありがとうございました. s_com_Bufの型がchar型でした. unsigned charに変えると FFFFFFがでなくなりました. しかし,今他チャンネルのAD変換を行なっているのですが, 送信データ a → 1chデータ受信 b → 2chデータ受信 c → 3chデータ受信 d → 4chデータ受信 としているのですが, 本来2chや3chのデータが入る変数に 1chのデータが入るのですが, WriteFile(hCom, w_com_Buf,lstrlen(w_com_Buf), &n, 0 ); ReadFile(hCom, s_com_Buf,1, &n, 0 ); 関数の間にSleep関数を入れて待機状態をつくっているのですが, うまくいきません.何かいいアイデアがあれば教えてください.