• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:シリアル通信でのデータ受信)

シリアル通信でのデータ受信

このQ&Aのポイント
  • シリアル通信にてデータを連続的に受信するプログラムを作成する際に、フが多く表示される、最後の改行がされていない、データが失われる、1サイクルの値が2サイクル目にも残るという問題が発生しています。解決方法を教えていただきたい。
  • シリアル通信にてデータを連続的に受信するプログラムを作成する際に、フが多く表示される、最後の改行がされていない、データが失われる、1サイクルの値が2サイクル目にも残るという問題が発生しています。解決方法を教えていただけると助かります。
  • シリアル通信にてデータを連続的に受信するプログラムを作成している際に問題が発生しています。フが多く表示され、最後の改行がされていない、データが失われる、1サイクルの値が2サイクル目にも残るという問題があります。解決方法を教えていただけますか?

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

  • ベストアンサー
  • hidebun
  • ベストアンサー率50% (92/181)
回答No.4

先ほどの訂正と追加です。 3.dcb.Bytesizeを8にして、while文を無限ループにし (countのif~break文を削除し), strlen(buff)のところを BYTE_SIZEにしてみてください。データが取りこぼしなく 表示されませんか。 #通信が終わらないという問題は、受信ができない問題 とは別問題なので、今は考えていません 4.3.でデータの取りこぼしがあれば、送信側・受信側とも、 BaudRateを低く(9600bpsとか)してみて改善されるかどうか、 確認してください。 データの取りこぼしが通信速度によるものなら、フロー制御など も考えないといけませんね。ところで、今頃聞くのもなんなんですが、 送信側・受信側は、どのような環境をお使いなんでしょう?

全文を見る
すると、全ての回答が全文表示されます。

その他の回答 (3)

  • hidebun
  • ベストアンサー率50% (92/181)
回答No.3

もう少し具体的に情報を書いてもらったほうが、 回答するのが楽になります。 とりあえず、以下の点については、どうでしょうか? 確認事項 1.COM2に正常にデータが送信されてきていますか?  (ハイパーターミナル等を起動して、データ受信を確認する) 2.dcb.Bytesizeを7、8にすると受信に失敗するとありますが、  具体的にはどういう風に失敗するのでしょうか? #やはり5000という値は、おかしいと思います。  なぜに5000?化けたり、ロストとしたりは、   この辺りが原因のような気もしますが。 3.dcb.Bytesizeを8にして、while文を無限ループにし (countのif~break文を削除し), strlen(buff)のところを 100とすると、受信したデータが画面に表示されませんか?

全文を見る
すると、全ての回答が全文表示されます。
  • hidebun
  • ベストアンサー率50% (92/181)
回答No.2

#defineでSTOP_BITとF_PARITYの名前と値の対応関係がおかしい気がしますが、 とりあえず、値をセットする側でうまく(?)吸収されてますね。 ところで、dcb.ByteSizeが5000になりますが、ここは、1バイトのビット数を 指定する場所ですね。通常7か8を指定するはずですが、5000としているのは、 何か理由があるのでしょうか。 また、main関数のReadData(buff, strlen(buff))の部分ですが、buffが 初期化されていないので、strlen(buff)がどのような値になるかわからない 気がするのですが、その辺りはいかがですか。 strlen(buff)の部分を100とかの固定値にすると、結果はどのようになりますか? シリアル通信について、私も初心者なので、この辺りからのアプローチしか できませんが、問題解決の一助になれば幸いです。

HIIYO
質問者

お礼

たびたびありがとうございます. お礼が遅くなり申し訳ありません. dcb.bytesizeを7あるいは8とすると データの受け取りで失敗してしまうのです・・・

全文を見る
すると、全ての回答が全文表示されます。
  • hidebun
  • ベストアンサー率50% (92/181)
回答No.1

ReadFileで取得したデータの最後に、 buff[dwRead] = '\0'; を忘れているから、print文でおかしな場所まで 表示してしまっているのではないでしょうか。

HIIYO
質問者

お礼

ご回答ありがとうございます. 確かに配列の文字列の最後を記すのを わすれていました.ありがとうございます. \0をつけてみました. フの表示はなくなったのですが, 今度は各行の先頭に■がつくようになりました. また,データがサイクルごとにロストする. のはなおっていません.

全文を見る
すると、全ての回答が全文表示されます。

関連するQ&A

  • PICとPCでのシリアル通信

    PICとPC間でのシリアル通信を行ってるんですけどうまくいきません。ハイパーターミナル使えばうまくいくんでPIC側のソース(C)はうまくいってると思います。ハイパーターミナルを使わずにシリアルの送受信のプログラム(C++)を組んでるんですけどうまくいかなくて。。。 アドバイスなどお願いします!!どこが違うんでしょうか。。。 ●PC側のソース(C++) #include "stdafx.h" #include <stdlib.h> #include <windows.h> #include<iostream> using namespace std; #define COM_PORT_NAME "COM1" #define BAUD_RATE 9600 #define BYTE_SIZE 8 #define PARITY EVENPARITY #define STOP_BIT TRUE #define F_PARITY ONESTOPBIT HANDLE hComm; // シリアルポートとの通信ハンドル bool ComInit() { // シリアルポートを開ける hComm = CreateFile( COM_PORT_NAME, /* シリアルポートの文字列 */ GENERIC_READ | GENERIC_WRITE, /* アクセスモード:読み書き */ 0, /* 共有モード:他からはアクセス不可 */ NULL, /* セキュリティ属性:ハンドル継承せず */ OPEN_EXISTING, /* 作成フラグ: */ FILE_ATTRIBUTE_NORMAL, /* 属性: */ NULL /* テンプレートのハンドル: */ ); if (hComm == INVALID_HANDLE_VALUE) { printf("シリアルポートを開くことが出来ませんでした。\n"); return false; } // 通信属性を設定する DCB dcb; GetCommState(hComm, &dcb); /* DCB を取得 */ dcb.BaudRate = BAUD_RATE; dcb.ByteSize = BYTE_SIZE; dcb.Parity = PARITY; dcb.fParity = STOP_BIT; dcb.StopBits = F_PARITY; SetCommState(hComm, &dcb); /* DCB を設定 */ return true; } void ComEnd() { // ハンドルを閉じる CloseHandle(hComm); } bool WriteData(char *buff, unsigned int data_size) { DWORD dwWritten; /* ポートへ書き込んだバイト数 */ WriteFile(hComm, buff, data_size, &dwWritten, NULL); if (dwWritten!=data_size) { printf("データの送信に失敗しました。\n"); return false; } return true; } bool ReadData(char *buff, unsigned int max_size) { DWORD dwErrors; /* エラー情報 */ COMSTAT ComStat; /* デバイスの状態 */ DWORD dwCount; /* 受信データのバイト数 */ DWORD dwRead; /* ポートから読み出したバイト数 */ ClearCommError(hComm, &dwErrors, &ComStat); dwCount = ComStat.cbInQue; if (dwCount > max_size) { printf("バッファサイズが足りません。\n"); return false; } ReadFile(hComm, buff, dwCount, &dwRead, NULL); if (dwCount != dwRead) { printf("データの受け取りに失敗しました。\n"); return false; } return true; } int main(int argc, char* argv[]) { char ch; while(1){ cin >> ch; printf("入力 %c\n", ch); ComInit(); WriteData(&ch, strlen(&ch)); ReadData(&ch, strlen(&ch)); ComEnd(); } return 0; }

  • シリアル通信の受信待ちについて

    シリアル通信で10Byte受信するまで待ち続けたいのですが、0ByteでReadFileが抜けてしまいます。 ReadFileの最後のパラメタが、NULLならば第3パラメタの値まで待ち続けると思っていたのですが、なにか設定が足りないのでしょうか? タイムアウト値は0にしています。(色々変えて見ましたが同じでした) HANDLE hComm; /* シリアルポートのハンドル */ DCB dcb; char* pszBuf="1234567890"; /* 書込・読込領域 */ hComm = CreateFile("COM1", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); GetCommState(hComm, &dcb); /* DCB を取得 */ dcb.BaudRate = 9600; dcb.ByteSize = 8; dcb.Parity = NOPARITY; dcb.StopBits = ONESTOPBIT; dcb.ReadIntervalTimeout = 100; dcb.ReadTotalTimeoutMultiplier = 0; dcb.ReadTotalTimeoutConstant = 0; dcb.WriteTotalTimeoutMultiplier = 10; dcb.WriteTotalTimeoutConstant = 500; SetCommState(hComm, &dcb); /* DCB を設定 */ DWORD dwRead; /* ポートから読み出したバイト数 */ ReadFile(hComm, pszBuf, 10, &dwRead, NULL);

  • シリアル通信のポートオープン

    シリアル通信のテストプログラムを作成中でして、一通り動作するようになったのでエラー処理を確認しようとしたところ、存在しないCOMポート?なのにオープンが成功したと処理してしまいます。 環境  P社のノートパソコン  Windows XP Pro SP3  Visual C++6.0 SP6  USB接続のRS-232C変換アダプタを使用  デバイスマネージャでは、拡張ポートはCOM4のみとなっている  ハイパーターミナルの「接続の設定」では、接続方法の選択肢にCOM3とCOM4の2つがある ・COM4を使うと、オープン後、正常に通信できます。 ・COM3を使うと、オープンは出来るが、通信は出来ません。 ソースを記載します。 if(HANDLE_CHECK(m_hComm) == FALSE){ ss.Format("COM%d", m_nRsPort); m_hComm = ::CreateFile(ss, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); if(HANDLE_CHECK(m_hComm) == TRUE){ dcb.DCBlength = sizeof(DCB); if(::GetCommState(m_hComm, &dcb) != FALSE){ dcb.BaudRate = m_nRsBaudrate; dcb.Parity = m_nRsParity; ・ ・ ・ ・ ・ ・ if(::SetCommState(m_hComm, &dcb) != FALSE){ COM3の場合もCOM4の場合もここを通っている。 } else{ } } } } COM3のオープン時、エラーの検知は出来ないのでしょうか? よろしくお願いします。

  • COM1ポート開き,9600,8,なし,1,HWの設定で垂れ流しデータ読むだけのCプログラム作って

    ください。Borland C v5.5 無料版 on windows2000 on thinkpadのDOS窓で動いて欲しいだけ、です。基本が解れば、あとは自分で改造したいですので、どなたか、お優しい方、何卒お願いします! 本もないのに、無謀ですが、たとえば以下のは参考になりますか?以下のはC++ですので、ちょっと私には解りません。C++でなく、Cで、書き下して欲しいです。 #include <windows.h> #include <iostream> #include <stdio.h> using namespace std; int main() { HANDLE hComm; char buff[190]; DWORD size; hComm = CreateFile( "COM1", GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0 ); if( hComm == INVALID_HANDLE_VALUE ) exit( 1 ); ReadFile(hComm, buff, 200, &size, NULL); cout << buff << endl; getchar(); CloseHandle(hComm); return 0; }

  • シリアル通信プログラム(受信)について

    現在、シリアル通信をする(受信のみ)プログラムを作成しています。 接続先は1秒ごとに10バイトのデータを自動で送信してきます。 現段階でPC側でデータを受信できることは確認できました。 しかし、受信データが文字化け(出力結果が{や■などがでています)しており、その原因がわかりません。 どこが問題なのか教えていただけないでしょうか? また、接続先からは10バイトのうち最初の2バイトは固定の値(0x2b,0x22)がでてくるはずなのですが、それもでてきていません。これも文字化けで見えていないだけでしょうか? 文字化けしても周期的に固定の値に対応した文字がでてくるものだと思ったのですが、でてきていません。 (ソースで50バイトまでみているのはこの周期性を確認するためです) シリアル通信を初めてさわるので、考え方自体間違っているかもしれませんが 配列pszBufに1つずつ、受信された1バイトのデータが格納されていると思っています。 個人的にはprintfでの表記(%cがいけない?)に間違いがあるかと疑っています。 ご回答よろしくお願いいたします。 (環境) Visual C++ 2008 (C/C++) (シリアルポート設定) ボーレート 9600bps パリティ   なし ストップビット 1 データビット 8 (ソース) ※ポートの設定は省略。受信部のみ記述 HANDLE hComm; DWORD dwErrors; COMSTAT ComStat; char pszBuf[1024]; DWORD dwRead; ClearCommError(hComm, &dwErrors, &ComStat); ReadFile(hComm, pszBuf, 50, &dwRead, NULL);  //50バイトまでデータを取得 for(int i=0;i<50;i++){ printf("%c\n",pszBuf[i]); } (参考URL) http://www.geocities.jp/terukat/_geo_contents_/win/comm.html

  • VC++でrs232c通信

    ハイパーターミナルで試したところ、以下のプログラムにも書いてありますが C,OL,1と入力すると OKという文字が返ってくるというものなのですが、 printf("%s,オンラインに失敗しました\n",l);の所で lがnoneのままでした。 説明書にはC,OL,1[CR][LF]と入力すると OK<CR><LF>またはER,n<CR><LF>と返ってくると書いてありました。 色々調べはしたのですが、わかりません。 根本から間違っているような気もします。 何処が間違っているかご指摘をお願いします。 ************************************* HANDLE COMHandle; DWORD dwRoad,dwWrite,dwError,dwCount; COMSTAT ComStat; char *l="none"; COMHandle=CreateFile("COM3",GENERIC_READ | GENERIC_WRITE,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);//ハンドルの取得 if ( COMHandle == INVALID_HANDLE_VALUE ) { printf("COMport Open Error!\n"); getch(); exit(1); } DCB dcb; GetCommState(COMHandle,&dcb);//シリアルポートの状態を取得 dcb.BaudRate=2400;//ボーレート,伝達速度,bps dcb.ByteSize = 8; // データサイズ,bit dcb.Parity = NOPARITY; // パリティ:エラー検出 dcb.StopBits = ONESTOPBIT; // ストップビット SetCommState(COMHandle,&dcb); // シリアルポートの状態を設定 ncf1="C,OL,1\r\n";//入力コマンド WriteFile(COMHandle,ncf1,strlen(ncf1),&dwWrite,NULL); ClearCommError(COMHandle,&dwError,&ComStat); dwCount=ComStat.cbInQue; ReadFile(COMHandle,l,dwCount,&dwRoad,NULL); if(l!="OK\r\n"){ printf("%s,オンラインに失敗しました\n",l); getch(); exit(1); }

  • VC++でシリアル通信

    質問 VC++をはじめて2ヶ月程度のものです。 現在、計測装置からのデータをシリアル通信でパソコンに取り込もうとしています。 ホームページなどを参考にコードを書きましたが、 以下のようではだめでしょうか? 環境はWinXP、VC++6.0でダイアログベース。 実行結果はボタンを押すとエディットボックスに以下のように表示がでてきます。 フフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフ・ よろしくお願いいたします。 ボタンに割り当てたコード void CTest_commDlg::OnButton1() {     HANDLE hComm; //通信ハンドル DCB myDCB; //----------ポートオープン hComm = CreateFile("COM2", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL ); //----------DCB構造体を使って通信設定をする BuildCommDCB("9600,n,8,1",&myDCB); //----------DCB構造体セット SetCommState(hComm, &myDCB); //----------タイムアウト設定 COMMTIMEOUTS CommTimeout; GetCommTimeouts(hComm,&CommTimeout); CommTimeout.ReadIntervalTimeout = 500; CommTimeout.ReadTotalTimeoutMultiplier = 0; CommTimeout.ReadTotalTimeoutConstant = 500; CommTimeout.WriteTotalTimeoutMultiplier = 0; CommTimeout.WriteTotalTimeoutConstant = 500; SetCommTimeouts(hComm,&CommTimeout); //----------受信 char RecBuff[64]; DWORD ReadLen; ReadFile(hComm,RecBuff,64,&ReadLen,NULL); //----------エディットボックスに表示 m_ed1.SetWindowText(RecBuff); }

  • VC++でのシリアル通信が上手くいきません。

    ArduinoからPCへ送られてくる信号を表示するコンソールアプリケーションを VC++で試作しているのですが、ReadFile()関数でデータを読み取ろうとするとうまくいきません。 どうすればうまくいくでしょうか? どなたかお詳しい方がおられましたら回答をよろしくお願いします。 コードは以下の通りです。 #include <Windows.h> #include <stdlib.h> #include <stdio.h> HANDLE arduino; bool Ret; void main(void){ BYTE data = 1; //1.ポートをオープン arduino = CreateFile("COM3",GENERIC_WRITE,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL); if(arduino == INVALID_HANDLE_VALUE){ printf("PORT COULD NOT OPEN\n"); system("PAUSE"); exit(0); } //2.送受信バッファ初期化 Ret = SetupComm(arduino,1024,1024); if(!Ret){ printf("SET UP FAILED\n"); CloseHandle(arduino); system("PAUSE"); exit(0); } Ret = PurgeComm(arduino,PURGE_TXABORT|PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR); if(!Ret){ printf("CLEAR FAILED\n"); CloseHandle(arduino); exit(0); } //3.基本通信条件の設定 DCB dcb; GetCommState(arduino,&dcb); dcb.DCBlength = sizeof(DCB); dcb.BaudRate = 9600; dcb.fBinary = TRUE; dcb.ByteSize = 8; dcb.fParity =NOPARITY; dcb.StopBits = ONESTOPBIT; Ret = SetCommState(arduino,&dcb); if(!Ret){ printf("SetCommState FAILED\n"); CloseHandle(arduino); system("PAUSE"); exit(0); } //4.受信 DWORD dwSendSize; DWORD dwErrorMask; int i=0; while(i<30) { Ret = ReadFile(arduino,&data,1,&dwSendSize,NULL); if(!Ret){ printf("RECEIVE FAILED\n"); CloseHandle(arduino); system("PAUSE"); exit(0); } printf("data=%c\n",data); i++; Sleep(100); } printf("FINISH\n"); CloseHandle(arduino); system("PAUSE"); }

  • 通信(送信)のプログラム

    bool WriteData(char *buff, unsigned int data_size) {     DWORD dwWritten; /* ポートへ書き込んだバイト数 */ WriteFile(hComm, buff, data_size, &dwWritten, NULL); if (dwWritten!=data_size) { printf("データの送信に失敗しました。\n"); return false; } return true; } 上の関数はシリアル通信の送信する関数なんですが、これに数値などを入れたいんですが、char型のため、一文字しか入れれません。たとえば、01ならchar型の0とchar型の1を別々に送らないとだめなんですが、このようにするしか無理なんでしょうか?int型の数値を好きなように入れて送りたいんですが。あと、OxFFのように16進数も入れれると便利なんですが。駄文ですいません。プログラムの知識が浅はかですいません。

  • SONY製カメラ 制御

    カメラを右に0.07度動かすプログラムを作ろうとしています. カメラはSONY製EVI-HD1を用いて,openCVで実装しています. うまく動作しないので,以下のプログラムに足りない命令行を教えていただいてもよろしいでしょうか. #include <stdio.h> #include "windows.h" #include <dshow.h> //RS232C 制御用 #define ASCII_BEL 0x07 #define ASCII_BS 0x08 #define ASCII_LF 0x0A #define ASCII_CR 0x0D #define ASCII_XON 0x11 #define ASCII_XOFF 0x13 void main(int argc, char* argv[]) { HANDLE hCom; //RS232C制御用 RS232C の初期化 hCom = CreateFile("COM3", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); if (hCom == INVALID_HANDLE_VALUE) { return; } DCB dcb; BOOL fRetVal ; BYTE bSet ; bSet = 0; dcb.DCBlength = sizeof(DCB) ; GetCommState(hCom, &dcb) ; dcb.BaudRate = 9600; // 通信速度 dcb.ByteSize = 8; // データ長 dcb.Parity = NOPARITY; // パリティビット:EVENPARITY,MARKPARITY,NOPARITY,ODDPARITY dcb.StopBits = ONESTOPBIT; // ストップビット:ONESTOPBIT,ONE5STOPBITS,TWOSTOPBITS dcb.fOutxDsrFlow = bSet ; if (bSet) { dcb.fDtrControl = DTR_CONTROL_HANDSHAKE ; } else { dcb.fDtrControl = DTR_CONTROL_ENABLE ; } dcb.fInX = dcb.fOutX = bSet ; dcb.XonChar = ASCII_XON ; dcb.XoffChar = ASCII_XOFF ; dcb.XonLim = 100 ; dcb.XoffLim = 100 ; dcb.fBinary = TRUE ; dcb.fParity = TRUE ; SetCommState(hCom, &dcb); //RS232Cの初期化ここまで int i,j; unsigned long len; // 送信用 char send[32]; int send_length; //受信 b用 unsigned char resv[32]; int resv_length; unsigned char buff; char in; //カメラを右に向ける----------------------------------------------------------------------- sprintf(send,"\x88\x30\x01\xff"); send_length=4; //アドレス設定 sprintf(send,"\x88\x01\x00\x01\xff"); send_length=5; //インタフェイスクリア sprintf(send,"\x81\x01\x06\x03\x18\x18\x00\x00\x00\x01\x00\x00\x00\x00\xff"); //右に0.07度 send_length=15; WriteFile(hCom,send,send_length,&len,NULL); //書き込み for(i=0;i<32;i++) { ReadFile(hCom,&buff,1,&len,NULL); //1つずつ受信 resv[i]=buff; printf("%02x ",buff); if(buff==0xff) { if(resv[0]==0x90 && resv[1]==0x41) i=0; else i=32; } } //----------------------------------------------------------------------------------------- //後処理 CloseHandle(hCom); }