• 締切済み

シリアルポートの初期化がおかしい?応答がないんです。

こんにちは、どうか僕の問題を解決してくださいませんか。いまシリアルポートを会したハードウェアの処理を行っています。しかし、ハードウェアに反応があるときと、ないときがあるのです。自分のプログラムで制御しようとすると、コマンドの応答がまったくなく、テラタームでコマンドを送信すると、応答があります。その後、再度自分のプログラムで制御すると、今度は反応があり、うまく制御できます。この状況を経験した方はいませんでしょうか。以下が初期化部分のコードです。 /////////******** 以下の関数でポートを開きます。 ***************://///////// CreateFileCom(comFileName, &phCom, lBaudRate, lDataByteSize, lParity, lStopBit) ///////*******省略 { DCB dcb; GetCommState((*phCom),&dcb); dcb.BaudRate = lBaudRate; dcb.ByteSize = (BYTE)lDataByteSize; dcb.Parity = (BYTE)lParity; dcb.StopBits = (BYTE)lStopBit; SetCommState((*phCom),&dcb); } } /////////////********* 以下がメイン関数の初期化部分です。 **************///////////// FILE* fp; LPCSTR comFileName = "COM1"; long lBaudRate = CBR_9600; long lDataByteSize = 8; long lParity = NOPARITY; long lStopBit = ONESTOPBIT; int returnValue; char str[1024]; char end_str[2] = "\r"; int j; fRetVal = CreateFileCom(comFileName, &phCom, lBaudRate, lDataByteSize, lParity, lStopBit); よろしくお願いいたします。

みんなの回答

  • Haizy
  • ベストアンサー率40% (404/988)
回答No.1

もしかして、SetCommStateがうまく働いていないのでは? Cはいいのですが、何Cで組んでます? ちょっと、DCB が何をカプセル化したものかわからないので、確かとはいえませんが・・。 ただ、テラターム 処理後に 動作するということは、当該命令だけでは、ACTIVE 状態 にはなりきっていないと思われますね。 つまり、COMが活性状態では無いので、いくら呼び出してもダメとか、OSへの通知が必要な場合などが、考えられませんか。 なにか、もうワンアクション必要なのではないでしょうか?? とりあえず、ハードがらみで、環境がわからないのは、キツイです 補足要求: ・使用機器(パソコンの機種。せめて、PC98かDOS/Vか) ・OS(DOSか、Winかすらわかりません) ・Cのバージョン(この場合コンパイラのバージョンというより、製品名+製品バージョンで)

tokitokitoki
質問者

お礼

お返事が遅れまして申し訳ありません。やはり、おっしゃるとおり、COMポートの初期化が問題でした。(DCBの設定を、しらみつぶしに変えたらできました。)C言語の経験が浅く、C言語といってもさまざまな種類があり、それぞれに違った拡張機能を持っているんですね。これからはそのあたりを明記して質問させていただきます。これからもよろしくお願いします。今回の場合は、MSのVC++6.0で、WINDOWS NT4.0 でプログラミングしました。

関連するQ&A

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

    シリアル通信で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);

  • 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"); }

  • 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); }

  • 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; }

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

    シリアル通信にてデータを連続的に受信するプログラムを つくりたいと思っています. 以下のプログラムを作成して, main関数のcountを増やして,繰り返しreadを行おうとすると, 出力結果として, 時,分,秒,ID,値B,値C,値Dというフォーマットで 0, 9,30, 1,514,708,542,290 0, 9,30, 2,515,707,542,288 0, 9,30, 3,514,709,542,287 0, 9,30, 4,514,707,543,289 0, 9,30, 5,514,708,542,289 0, 9,30, 6,514,708,542,292 0, 9,30, 7,514,708,542,291 0, 9,30, 8,514,708,542,289 0, 9,30, 9,514,708,543, 0, 9,39,35,514,708,542,289 (この後フが連続) フフフフフフフフフフフフフフフ ク 0, 9,39,36,514,708,542,290 0, 9,39,37,515,709,541,291 0, 9,39,38,514,707,542,286 0, 9,39,39,514,708,542,281 0, 9,39,40,514,708,542,284 0, 9,39,41,514,707,542,286 0, 9,39,42,514,707,542,290 0, 9,39,43,514,709,542,290 0, 9,30, 9,514,708,543, 0, 9,39,35,514,708,542,289 フフフフフフフフフ・・・再びフ となってしまいます. 問題としては ・フがたくさんでてきてしまう. ・1サイクルの最後で改行ができていない ・1サイクルが終わって次のサイクルに入る時までの 間にデータが失われている. ・2サイクル目になぜか1サイクル目の値が残っている? などがあります. どなたか解決方法を教えていただけると大変助かります. よろしくお願いします. ------------------------------- #include "stdafx.h" #include <stdlib.h> #include <windows.h> #include <string.h> #include <stdio.h> #define COM_PORT_NAME "COM2" #define BAUD_RATE 57600 #define BYTE_SIZE 5000 //250 #define PARITY NOPARITY //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 ReadData(char *buff, unsigned int max_size) { DWORD dwErrors; /* エラー情報 */ COMSTAT ComStat; /* デバイスの状態 */ DWORD dwCount; /* 受信データのバイト数 */ DWORD dwRead; /* ポートから読み出したバイト数 */ ClearCommError(hComm, &dwErrors, &ComStat); dwCount = ComStat.cbInQue; FILE *fid; fid=fopen("test.txt", "w"); printf("%d %d\n", dwCount, max_size); fprintf(fid,"%d %d\n", dwCount, max_size); fclose(fid); if (dwCount > max_size) { printf("バッファサイズが足りません。\n"); return false; } if(hComm != NULL){ ReadFile(hComm, buff, dwCount, &dwRead, NULL); if (dwCount != dwRead) { printf("データの受け取りに失敗しました。\n"); return false; } } return dwRead; } int main(int argc, char* argv[]) { char buff[BYTE_SIZE]; int count = 0; int data_length; FILE *fid2; fid2=fopen("test2.txt","w"); ComInit(); while(1){ if(count == 2) break; count++; data_length=ReadData(buff, strlen(buff)); printf("%s ",buff); fprintf(fid2, "%s ",buff); } fclose(fid2); ComEnd(); return 0; }

  • C言語でのRS232Cとの通信

    今後,電動ステージをRS232Cを持つコントローラとVisual studio2008で動かすことになったのですが, プログラム初心者のため,動かし方がわかりません. 一応,いくつかのサイトで調べた方法を試したのですが,動かすことができませんでした. 下に現在のプログラムソースを張ってあります. また,コントローラの諸元は, ボーレート:9600 データ長:8ビット ストップビット:1ビット パリティ:なし です. 皆さんのアドバイスを頂けたら,幸いです. また,このような質問は初めてなので,どういった情報がわかれば尚良いかを教えて頂けると幸いです. [プログラムソース] #include <stdio.h> #include <windows.h> #include <stdlib.h> #include <string.h> #include <math.h> #include <time.h> #define CR 0x0d #define LF 0x0a HANDLE hCom; void init(char *com, int baudrate); void m_move(double pos); int main() { double pos; init("COM1", 9600); printf("移動量 = ");scanf("%lf", &pos); m_move(pos); CloseHandle(hCom); } void init(char *com, int baudrate) { DCB dcb; hCom = CreateFile("COM1", GENERIC_WRITE | GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); GetCommState(hCom, &dcb); dcb.BaudRate = baudrate; dcb.ByteSize = 8; dcb.Parity = NOPARITY; dcb.StopBits = ONESTOPBIT; SetCommState(hCom, &dcb); } void m_move(double pos) { int Send_Res, SendLen; char Send_Buf[4000]; char cmd[256]; DWORD wbyte; sprintf(cmd, "LMA ,,%.2lf", pos); //LMA はステージを動かすコマンド printf("%s", cmd); strcpy(Send_Buf, cmd); SendLen = strlen(Send_Buf); Send_Buf[SendLen] = CR; Send_Buf[SendLen + 1] = LF; Send_Res = WriteFile(hCom, Send_Buf, SendLen+2, &wbyte, NULL); fflush(stdout); Sleep(100); }

  • バイナリ送信で出るエラーコードの意味が分かりません

    シリアルポートでバイナリを非同期で送信するプログラムを作成しています。 以下のソースで実行すると、「重複したI/O処理を実行しています」というエラーがでました。 何が間違っているのか分りません・・。 どうかご指摘お願いします。 void CMyDlg::OnReset() { //COMポートオープン HANDLE hCom; hCom = CreateFile( "COM4", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL ); //通信設定 DCB dcb; GetCommState(hCom,&dcb); dcb.BaudRate = 9600; dcb.ByteSize = 8; dcb.Parity = NOPARITY; dcb.StopBits = ONESTOPBIT; SetCommState(hCom,&dcb); OVERLAPPED old; // オーバーラップ構造体の初期化 ZeroMemory( &old, sizeof(old) ); old.Offset = 0; old.OffsetHigh = 0; old.hEvent = NULL; //データ送信 char wbuf[7] = {0x02,0x00,0x01,0x00,0x31,0x15,0x12}; DWORD wbyte; WriteFile(hCom,wbuf,sizeof(wbuf),&wbyte,&old); //エラーコード取得&文字列に変換&表示 LPVOID lpMessageBuffer; FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(),//エラーコード取得 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &lpMessageBuffer, 0, NULL ); MessageBox((LPCTSTR)lpMessageBuffer); //メッセージボックス LocalFree( lpMessageBuffer ); //COMポートクローズ CloseHandle(hCom); }

  • 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); }

  • OSのコマンドを呼び出すとき、CPUを最大限に使いたい

    OS(ディストリビューション)はUbuntu、言語はC++を用いています。 以下のプログラム: int main(void) { unsigned long int cnt_max=ULONG_MAX; for(unsigned long int i=2;i<=cnt_max;i++){ string str =":"; char c[1024]; strcpy( c, str.c_str() ); FILE *fp = popen(c, "r");・・・※ pclose(fp);・・・※ } } では、確かに実行したいこと(ここでは何もしませんが)が行われます。 ところが、topコマンドで見るとCPUを数%しか用いていません。 ※の部分を消すと、100%使いますので、 どうやらOSのコマンド(ここでは「:」)を実行するときには100%使ってくれないようです。 では、100%使ってくれるようにするにはどうしたらよいでしょうか?

  • C++でArduinoをコントロールしたいのですが

    VC++から数値データ(0-100)を送信し、Arduinoに接続されているファンを受信した数値でPWMコントロールしたいのですが、接続を確立したその後からプログラミングの仕方がわかりません。 どのようにしてデータを送信すればよいのでしょうか? 以下のようにして接続を行っています。 //COMポートハンドル HANDLE hComm; hComm = CreateFileA("\\\\.\\COM3", GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0); //ポートの接続確認 printf("Arduino COM") ; if (hComm == INVALID_HANDLE_VALUE) printf(":not opened\n") ; else{ DCB lpTest; GetCommState(hComm,&lpTest); lpTest.BaudRate = CBR_9600; lpTest.ByteSize = 8; lpTest.Parity = NOPARITY; lpTest.StopBits = ONESTOPBIT; SetCommState(hComm,&lpTest); printf(":OPENED\n") ; WriteFile(hComm, buf,strlen(buf),&write, NULL); } //COMポートハンドルの解放 CloseHandle(hComm); なおArduino側のプログラムは以下のものを使用しています。 //読み取り値の変数 int val=0; void setup(){ //シリアル通信開始 Serial.begin(9600); } void loop(){ //データが0個より多いときの時 if(Serial.available()>0){ //データの読み込み val=Serial.read(); //合図用データ送信(1バイト) Serial.print(65,BYTE); } //アナログ出力(11番ピン)に読み込み値を入れる analogWrite(11,val); }