• ベストアンサー

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変換をしているため, 送信に対する受信データのやり取りができなくて困っています. どなたか先生教えてください.

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

  • ベストアンサー
  • Gizensha
  • ベストアンサー率34% (207/608)
回答No.1

s_com_Bufの型がわからないのですが、unsigned charでしょうか。 確実に8bitしか読まなくていいなら FF と とってしまってもいいような気がします。

beginnerSU
質問者

お礼

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関数を入れて待機状態をつくっているのですが, うまくいきません.何かいいアイデアがあれば教えてください.

その他の回答 (3)

noname#144013
noname#144013
回答No.4

度々すみません。#2&#3です。 PC側の受信処理で受信完了まで受信処理を繰り返す場合ですが、   PIC側の不具合または、ハード障害(ケーブル不良、接続抜けなど)等 により受信ができない(受信バッファにデータが入ってこない)場合も考えられ、 受信処理が終わらない可能性もありますので、その対策として、   タイムアウト処理(設定した時間、受信がなければ受信処理を止めてエラー表示等を行なうなど) を設けた方がより安全かもしれません。 以上です。

beginnerSU
質問者

お礼

丁寧に教えてくださりありがとうございます. 以下の回路で再度実験したところ,ほぼ,多チャンネルの受信ができるようになりました. PIC側にAD変換値を出力してから,終了命令として出力していたデータを消し,かつ,if文で"else"を"else if"にして,想定外なデータはPIC側からPC側へ送信しないようにしたらほぼ多チャンネル受信ができるようになりました.

noname#144013
noname#144013
回答No.3

すみません。#2です。 #2のコメント中の「■送信処理の例」と「■受信処理の例」に記述している下記2行、   DWORD dwErrorMask;   COMSTAT comstat; は余分でした(コピペミスです)、無視して下さい。失礼致しました。m(__)m

beginnerSU
質問者

お礼

丁寧に 教えてくださりありがとうございました.

noname#144013
noname#144013
回答No.2

こんにちは。 まず、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();    :    : } 以上です。参考になれば幸いです。

beginnerSU
質問者

お礼

おしえてくれてありがとうございます. 命令が WM_TIME内ですので, do~while を使うと処理がとまってしまうので 外してやってみようと思います.

関連するQ&A

  • PIC同士のシリアル通信について

    PIC初心者なのですが 現在↓サイトでPIC-PIC間のシリアル通信を勉強中です。 http://kuri6005.sakura.ne.jp/pic/index.php?PIC-PIC%A4%CE%C4%CC%BF%AE(USART) その中で通信設定の   Usart_Init(2400); //通信速度を2400 band rateに設定   do {     if(PORTA.F0 == 1) {       Usart_Write('A'); //RA0=1なら'A'を送信     } else {       Usart_Write(0); //RA0=0なら 0 を送信     } の部分でコンパイルエラーがでます。 たぶんヘッダーファイルのようなものが必要で指定されてないからエラーが出るのだとは思いますが、 どこからとってきて?またはどこにあるものなのかがわかりません。 わかる方教えて下さい。 ※テストで使っているPICの種類が違ってPIC16F877Aです

  • PIC-PCシリアル通信プログラム

    PICとPCでRS232のシリアル通信を行おうとしているんですけれど、 PICからPCに文字列を送ろうと たとえば PIC側からプログラムで puts("A\0");とデータを送信して ReadFile()関数でPC側で受信しているんですけれど、 受信したデータを画面表示されると Aフフフフフフフフフフフフフフフフフフフフフフフフと表示されてしまいます。 ちなみに送信データをNULLだけにしても フフフフフフフフフフフフフフフフフフフフフフフフフを表示されます。 これを解決する方法がわかりません。 どなたか教えてください。

  • シリアル通信について。

    PICからPCにデータ(電圧:最大値5)を受信させようとしています。 受信には C++を用いたプログラムを自作したいのですが、 どうしてもうまくいかなかったため投稿させていただきました。 症状としては、まずポートを開く事すら出来ていません。 RS232c {USBで変換) が接続されているポートはCOM1です。 ポートが開くか確かめるプログラムとしては、次のようなソースを使いました。 #include<windows.h> #include<iostream> using namespace std; int main(void){ HANDLE hCom; hCom = CreateFile( (LPCWSTR)"COM1", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); if (hCom == INVALID_HANDLE_VALUE) { cout<<"シリアルポートを開くことが出来ませんでした。\n"<<endl; return false; } CloseHandle( hCom ); return 0; } これを実行すると「シリアルポートを開くことが出来ませんでした。」としかなりません。 ( (LPCWSTR)"COM1"となっているのは、「'CreateFileW' : 1 番目の引数を 'const char [5]' から 'LPCWSTR' に変換できません。」  と出てしまったためです。) ハイパーターミナルを用いてCOM1からデータを受信できていることは確認しましたので、 通信が出来ていないわけではないようなのです。 ありふれた質問である事は重々承知の上ですが、 このソースでシリアルポートが開けない理由を教えていただければ幸いです。 環境:Visual C++ 2008 Express Edition Microsoft Windows XP Version 2002 Service Pack 3

  • pic 同士のシリアル通信

    picから別のpicにシリアル通信でデータを送ることは可能なのでしょうか? また、出来るとしたらどのようなプログラムになるでしょうか? 上記質問に追記です。 送信側はtxピン、受信側はrxピンという接続で可能でしょうか?

  • Win32APIでシリアル通信をするには?

    Win32APIとVB.NETを使ってシリアル通信をするプログラミングを考えています。概要はGPS端末からのデータをVBで受信して表示できるようなプログラムを目指していますが、APIの使い方が分からないので詳しく教えていただける方がいましたら、サンプルソースまたは参考Webサイトの教示をお願いします。 VB6.0のクラス(MSComm)を追加する方法ではなく、APIを使う方向で回答お願いします。

  • PIC間通信

    http://kuri6005.sakura.ne.jp/pic/pukiwiki.php?PIC-PIC%A4%CE%C4%CC%BF%AE%28USART%29 現在上記のサイトを利用してPICの勉強中です。 上記サイトでは、'A'という文字を転送していますが、数字や'AA'など複数文字ではうまく動作しません。 なにか良い方法があるのでしょうか? 下記 Usart_Write(1); の1の部分を'A'にするとうまく動作します。 (もちろん、送信・受信両方のPICは書き換えています。) できれば、変数にして受信側に送りたいのですが、可能でしょうか? よきアドバイスをお願い致します。 void main() { Kmode=0; PORTA=0b00000000; //PORTAの中身をきれいにする PORTB=0b00000000; //PORTBの中身をきれいにする CMCON=0b00000111; //PORTAをデジタル入出力使用に設定 TRISA=0b00000001; //RA0を1:入力に、他を0:出力に設定 TRISB=0b00000010; //PORTB RB1:入力、他7ヶは出力設定 Usart_Init(2400); //通信速度を2400 band rateに設定 do { if(Button(&PORTA, 0, 1, 0)) { //スイッチONの場合 Usart_Write(1); }else{ Usart_Write(0) } while(1); }

  • PIC USART 全二重通信

    2つのPIC(A, B)間でUSART機能を使用し、全二重通信を行いたいと考えています。 PIC(A)で送信を開始し、同じタイミングでPIC(B)からのデータを受信したい場合、 PIC(B)は送信レジスタにデータを入れておくだけで自動的に送信されるされるのでしょうか?それとも、受信を開始した直後くらいに何か送信設定を行う必要があるのでしょうか?

  • PIC16F1823 SPI通信

    PIC16F1823をマスターとして、スレーブデバイスから、SPI通信にてデータを読み込もうとしています。オシロスコープで波形を見ると、期待したデータをスレーブ側は出力しています。しかし、PICでは、0x00のデータしか受信されません。 PIC側のマスター受信では、SSP1BUFをダミーで読み込み、SPIでコマンドを送信、SSP1BUF.BFをみて、さらにSSP1BUFをダミーで読み込み、次にデータ受信用にダミーデータと受信を行い、SSP1BUF.BFをみて、SSP1BUFを読んでいます。気を付けて確認しなけらばならないレジスタ等あったら教えてください。

  • PICのUSARTについて

    PICのUSARTについて PICのUSART機能を使おうかと思い色々読んでいてPICのUSART(非同期の場合)は (1)基本的に1対1でしか接続できない。 (2)(非同期では)互いは平等でマスター、スレーブ関係はない (3)それぞれ送信側を制御し意図的に受信をする事はできない。 (その場合は相手に取り決めたコードを送ってデータを要求する) という感じでよろしいのでしょうか。 またPICの通信機能としてはSSPのSPIに近いような感じはしますがどちらが簡単でしょうか?

  • vb.net 2010からPICへのデータ送信

    vb.net2010のシリアルポートコントロールを使用してPICへデータを送り、受信した文字によって,制御を変えようとしています。 先日、こちらで質問させていただき,文字の送信はできるようになり、受信した文字によって制御を変えることができるようになりました。 しかし、文字列(例えば01やABなど)を送信した場合がうまくいきません。 文字列がきちんと受信できていないのかと思い、PCからデータ受信後、PICからPC文字列をそのままリターンすると問題なく受信できているようです。 このような場合、どういったことが原因と考えられるでしょうか? PIC側は受信割り込み内で、以下のようなコードです。      char buf[10]; buf[i]=getc(); if(buf[i] == '\r')//改行を受信するまで、配列に文字を格納 { buf[i]= '\0'; printf(buf);//PCに受信文字列をリターン if (i == 'ABC') { //受信文字列がABCの場合の処理 } else{           //受信文字列がABC以外の場合の処理 } }