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

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

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

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

Q&A

解決済

1回答

9617閲覧

c言語を用いたRS232C通信が停止してしまいます

jagaimo

総合スコア6

C++

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

0グッド

0クリップ

投稿2015/02/08 01:20

c言語を用いてRS232C通信を行うプログラムが安定動作しません。
オシロスコープからの電圧値をpcに取り込むプログラムが必要となり,作成しています。現在,一応のところ送受信が出来ており,希望とする機能は実現できているのですが,しばらくプログラムを動作させていると,以下のような問題が発生します。

・数千件程度データを受信したところでプログラムが完全に応答しなくなる(ウインドウも閉じない,通信用ケーブルを物理的に外すとプログラムの停止は出来ます。)
・プログラム動作中に突然ブルースクリーンになる(エラーメッセージはまだ確認できていません)

使用している環境は以下のとおりです。

OS : win7 32bit
コンパイラ : Borland C++ Compiler 5.5
使用ケーブル : UC-SGT

ソースコードはいかに添付します。
私自身プログラミングには疎く,問題の原因がソフトなのか,ハードなのか検討も付いていない状態です。何かこれらの問題の原因について,気づいた事が有りましたら教えていただけると幸いです。

#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <process.h>
#include <string.h>

HANDLE h;

//クリップボードへのデータ受け渡し関数
void wclip(char a[]){
HGLOBAL hMem = GlobalAlloc(GMEM_FIXED, 256);
strcpy((LPTSTR)hMem, a);
OpenClipboard(NULL);
EmptyClipboard();
SetClipboardData(CF_TEXT, hMem);
CloseClipboard();
}

//データ送信用スレッド
void sub( void *dummy ) {

unsigned long nn; char ch1[22]=":MEAS:SOUR1 CH1\n"; char ch2[22]=":MEAS:SOUR1 CH2\n"; char ave[16]=":MEAS:MEAN?\n"; int DataSize; COMSTAT Comstat; // 通信デバイス情報構造体 DWORD dwErrorMask; // エラーコードを受け取る変数 while( 1 ){ DataSize = strlen( ch1 ); //データのサイズ取得 do{ ClearCommError( h , &dwErrorMask , &Comstat ); }while( (128 - Comstat.cbOutQue) <= DataSize ); WriteFile( h, ch2, 22, &nn, 0); do{ ClearCommError( h , &dwErrorMask , &Comstat ); }while( (128 - Comstat.cbOutQue) <= DataSize ); WriteFile( h, ave, 16, &nn, 0); do{ ClearCommError( h , &dwErrorMask , &Comstat ); }while( (128 - Comstat.cbOutQue) <= DataSize ); WriteFile( h, ch1, 22, &nn, 0); do{ ClearCommError( h , &dwErrorMask , &Comstat ); }while( (128 - Comstat.cbOutQue) <= DataSize ); WriteFile( h, ave, 16, &nn, 0); }

}

//メイン文
void main() {
int i=0;
int j;
int ret,count=0,DataSize;
double voltage;
char sBuf[1];
char test[7]= "*idn?\n";

char str[100]; char out[100],output[100]; unsigned long nn; DCB dcb; COMMTIMEOUTS cto; unsigned long dummy; clock_t now; /* ---------------------------------------------- ファイルのクリエイト/オープン ---------------------------------------------- */ // クリエイトしたファイルのファイルハンドラを返す h = CreateFile( "COM3", GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0 ); if ( h == INVALID_HANDLE_VALUE ) { printf("Open Error of COM3 Port\n"); } /* ---------------------------------------------- シリアルポートの状態操作 ---------------------------------------------- */ GetCommState( h, &dcb ); // シリアルポートの状態を取得 dcb.BaudRate = 115200; // 速度 dcb.ByteSize = 8; // データ長 dcb.Parity = NOPARITY; // パリティ(Even) dcb.StopBits = 1; // ストップビット長 SetCommState( h, &dcb ); // シリアルポートの状態を設定 /* ---------------------------------------------- シリアルポートのタイムアウト状態操作 ---------------------------------------------- */ GetCommTimeouts( h, &cto ); // タイムアウトの設定状態を取得 cto.ReadIntervalTimeout = 35; cto.ReadTotalTimeoutMultiplier = 0; // 1Byte毎のタイマ cto.ReadTotalTimeoutConstant = 35; // 1関数コール毎のタイマ cto.WriteTotalTimeoutMultiplier = 0; // 1Byte毎のタイマ cto.WriteTotalTimeoutConstant = 0; // 1関数コール毎のタイマ SetCommTimeouts( h, &cto ); // タイムアウトの状態を設定 // スレッド作成と起動 _beginthread( sub, 0, &dummy ); now = clock(); /* ---------------------------------------------- 受信データの読み出し(1行分の文字列) ---------------------------------------------- */ while(1) { ReadFile( h, sBuf, 1, &nn, 0 ); // シリアルポートに対する読み込み if ( nn==1 ) { if ( sBuf[0]==10 || sBuf[0]==13 ) { // '\r'や'\n'を受信すると文字列を閉じる if ( i!=0 ) { str[i] = '\0'; i=0; now = clock(); printf("%5d%10d %s\n",count,now,str); voltage = atof(str); sprintf(output, "%d,%d,%.3f", count , now, voltage * 1000); wclip(output); //クリップボードへ出力 count++; } } else { str[i] = sBuf[0]; i++; } } //ret = PurgeComm( h, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR ); }

}

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

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

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

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

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

guest

回答1

0

ベストアンサー

以前DOSやマイコンボードでシリアル通信を行った経験ベースなので、参考程度にしかならないかと思いますが書かせて頂きます。
ケーブルを外すことでプログラムが停止することから、フロー制御ができておらずバッファオーバーフローが起きているような気もするので、1案としてBaudRateを下げてみるというのが有ります。
ケーブルはUSBシリアル変換なのですね。シリアルポートを直接接続する方式の方が相性が良いような気がしますが、PC側にポートが有るかがネックですね。
あとケーブルのドライバが有るようです。最新版にしてみてはどうでしょうか。
以上、ご参考までに。

投稿2015/02/08 04:57

BlueMoon

総合スコア1339

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

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

jagaimo

2015/02/08 17:09

回答ありがとうございます。 まだ問題は未解決ですが,ご指摘の件について確認した結果について報告させていただきます。 まず,ケーブルのドライバについてですが,デバイスマネージャーにて確認を行ったとこと,最新のものをインストールしていたようです。 また,BaudRateを下げることについては,2400まで下げますと,動作自体は安定するようになりましたが,結局数千件データを受信すると停止してしまいます。また,ブルースクリーンが発生する件も未解決でした。 また,通信対象であるオシロスコープや,使用しているケーブルにより,フロー制御は行えない状態になります。 他の要素についても,自分なりに検討を進めてみます。
jagaimo

2015/02/09 21:00

フリーズとブルースクリーンの原因について調査し,一応の問題解決が出来ましたので報告します。 ReadFileの行でフリーズが起きているようでした, UC-SGTのドライバファイルに問題があったようです。 ドライバを変更してテストするため,OSをXPに変更しXP用のドライバを使用して, 再度同じプログラムを実行しましたが,50000件以上データの送受信を行ってもフリーズが起きないので,この状態で使用してみたいと思います。 ありがとうございました。
BlueMoon

2015/02/09 23:25

解決に至って何よりです。お疲れ様でした。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問