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

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

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

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

Q&A

解決済

1回答

4061閲覧

COM イベント受信 並列

xasax0404

総合スコア27

C++

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

0グッド

0クリップ

投稿2016/10/26 06:15

COMポートを開放し、受信イベントを並列で行いたいです。
流れ
外部機器Aから受信し、処理
外部機器Aを受信している最中に外部機器Bから受信したら外部機器Aの受信処理をとめる

openmpで並列化させ、受信イベントを2つ作成しても、ひとつしか正常に受信できません。

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

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

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

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

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

guest

回答1

0

ベストアンサー

COMポートは1つだけ(例えばCOM1だけ)ですか?一つのCOMポートに2つの外部機器という1:多は無理だと思います。
それとも外部機器AとCOM1、外部機器BとCOM2という風にCOMポートを二つ仕様ですか?

できれば該当部分のソース記載お願い致します。

追記

visual studio Comunity 2015のコンソールアプリケーションとしてビルド

c

1// ConsoleApplication1.cpp : コンソール アプリケーションのエントリ ポイントを定義します。 2// 3 4#include "stdafx.h" 5#include <windows.h> 6 7int mainthread(void); 8 9DWORD WINAPI ThreadFunc(LPVOID arg) 10{ 11 HANDLE hPort; 12 char cRcv; 13 DWORD dwSendSize; 14 DWORD lRead; 15 16 hPort = CreateFile( 17 _T("COM2"), 18 GENERIC_READ | GENERIC_WRITE, 19 0, 20 NULL, 21 OPEN_EXISTING, 22 FILE_ATTRIBUTE_NORMAL, 23 NULL 24 ); 25 26 27 while (1) 28 { 29 WriteFile(hPort, _T("2"), 1, &dwSendSize, NULL); 30 31 Sleep(100); 32 33 cRcv = '\0'; 34 35 ReadFile(hPort, &cRcv, 1, &lRead, NULL); 36 37 if (lRead > 0) 38 printf("%c", cRcv); 39 40 Sleep(100); 41 } 42 43 44 return 0; 45} 46 47 48 49int main() 50{ 51 HANDLE hThread; 52 DWORD dwThreadId; 53 54 //スレッド起動 55 hThread = CreateThread( 56 NULL, 57 0, 58 ThreadFunc, 59 NULL, 60 0, 61 &dwThreadId); 62 63 mainthread(); 64 return 0; 65} 66int mainthread() 67{ 68 HANDLE hPort; 69 char cRcv; 70 DWORD dwSendSize; 71 DWORD lRead; 72 73 hPort = CreateFile( 74 _T("COM1"), 75 GENERIC_READ | GENERIC_WRITE, 76 0, 77 NULL, 78 OPEN_EXISTING, 79 FILE_ATTRIBUTE_NORMAL, 80 NULL 81 ); 82 83 84 while (1) 85 { 86 WriteFile(hPort,_T("1"),1,&dwSendSize,NULL); 87 88 Sleep(100); 89 90 cRcv = '\0'; 91 92 ReadFile(hPort,&cRcv,1,&lRead,NULL); 93 94 if(lRead > 0) 95 printf("%c", cRcv); 96 97 Sleep(100); 98 } 99 100 return 1; 101 102} 103

・追記の補足

酔った状態で回答してから翌日あまりにもはしょりすぎたサンプルなので少しだけ補足させてください。

各シリアルポートがたったこれだけで送信受信しているのはループバックアダプタを各COMポートの先につけているから、ボーレート等すべて同じ事が保証されているからで、実際に外部の機器と通信する場合はそのあたりの設定をしてください。

記載したソースはどちらかというとコメントのやりとりでスレッドを作成してマルチスレッドで動作するやり方があまりご存知でないという事でしたのでスレッドの作り方のサンプルとしてみていただければと、、、

骨組みだけ記載しておくと

c

1 2// サブスレッド 3DWORD WINAPI ThreadFunc(LPVOID arg) 4{ 5 while(!iFlg) 6 { 7 // サブスレッドの処理 8 } 9 10 return 1; 11} 12 13int main() 14{ 15 HANDLE hThread; 16 DWORD dwThreadId; 17 int iFlg = 0; // たとえばこれを終了するためのフラグとする 18 19 //サブスレッド作成 20 hThread = CreateThread( 21 NULL, 22 0, 23 ThreadFunc, 24 NULL, 25 0, 26 &dwThreadId); 27 28   // 割り込みでもなんでも良いのですが、何か外的要因でiFlgを1に変更するとプログラムが終了できる 29 while(!iFlg) 30 { 31 // mainスレッドでの処理 32 33    // 現在このmainスレッドとサブスレッドが並行して実行されている段階 34 } 35 36  // サブスレッドがiFlgを検知して終了するまでまつ 37  // これをしなくとも不具合があるとはいいきれないけど(変な終了してメモリリークとかなってもあれなので。。) 38  // あくまでメインスレッドはサブスレッドの終了をまってから終了する 39  WaitForSingleObject(hThread, INFINITE); 40 41 return 0; 42} 43

今回、メインとサブスレッドの2つですが、COM1をサブスレッド1、COM2をサブスレッド2というふうにメインスレッド、サブスレッド1、サブスレッド2と3スレッド構成で各サブスレッドは通信するためだけのスレッド、メインスレッドは各サブスレッドのハンドルを管理し、調停役のような役割で組んでも良いと思います。

投稿2016/10/26 06:21

編集2016/10/29 02:24
hiim

総合スコア1689

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

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

xasax0404

2016/10/26 06:31

そうです、COMポートは2つ使ってます。 #pragma omp parallel #pragma omp sections { #pragma omp section { while (i <= sousin){ //データ受信 // COMポートの受信イベント作成 OVERLAPPED ovRead2; memset(&ovRead2, 0, sizeof(ovRead2)); ovRead2.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); if (ovRead2.hEvent == NULL){ printf("RS232C CreateEvent Error\n"); //return -1; } // COMポートの受信イベントマスク if (SetCommMask(Rs232c2, EV_RXCHAR) == FALSE){ printf("RS232C SetCommMask Error\n"); //return -1; } // COMポートの受信待ち DWORD EvtMask = 0; DWORD Transfer = 0; if (WaitCommEvent(Rs232c2, &EvtMask, &ovRead2) == FALSE){ if (GetLastError() == ERROR_IO_PENDING) { GetOverlappedResult(Rs232c2, &ovRead2, &Transfer, TRUE); } else{ printf("RS232C WaitCommEvent Error\n"); //return -1; } } // COMポートの受信イベントチェック if ((EvtMask & EV_RXCHAR) == EV_RXCHAR){ // COMポートの受信データチェック COMSTAT comstZ; DWORD dwErrZ; ClearCommError(Rs232c2, &dwErrZ, &comstZ); // COMポートからデータ受信 if (ReadFile(Rs232c2, RcvBuf, comstZ.cbInQue, &dwSize, &ovRead2) == FALSE){ printf("RS232C ReadFile Error\n"); //return -1; } else{ // 受信成功 printf("%d\n", i); } } i++; } } #pragma omp section { // COMポートの受信待ち DWORD dwEvtMask = 0; DWORD dwTransfer = 0; if (WaitCommEvent(Rs232c1, &dwEvtMask, &ovRead) == FALSE){ if (GetLastError() == ERROR_IO_PENDING) { GetOverlappedResult(Rs232c1, &ovRead, &dwTransfer, TRUE); } else{ printf("RS232C WriteFile Error\n"); //return -1; } } // COMポートの受信イベントチェック if ((dwEvtMask & EV_RXCHAR) == EV_RXCHAR){ // COMポートの受信データチェック COMSTAT comst; DWORD dwErr; ClearCommError(Rs232c1, &dwErr, &comst); // COMポートからデータ受信 if (ReadFile(Rs232c1, RcvBuf, comst.cbInQue, &dwSize, &ovRead) == FALSE){ printf("RS232C ReadFile Error\n"); //return -1; } else{ // 受信成功 printf("%s", RcvBuf); } } } } こんな感じで書いてます。
hiim

2016/10/26 07:24

現在、実行環境が無い為、先ほどからソースレベルで追っていますが(まだ未解決)、その前に確認していただきたいのですが、 COM1、とCOM2を仕様していると想定したとして この並列処理ですが、Rs232c1、Rs232c2のそれぞれを並列でなくシングルで走らせた場合は正常動作していますか?また プログラム起動前にmodeコマンドでCOM状態を確認しCOM1、COM2ともに利用可能状態、、プログラム起動後はmodeコマンドでCOM1もCOM2も表示されない(使用中)になりますか?
xasax0404

2016/10/26 07:48

シングルで走らせたら正常に動いています。 modeコマンドでそこの確認は出来ました。
hiim

2016/10/26 08:18

ソースレベルで追っているだけではどこでこけているのかわからない為、帰宅後もしくは後日windows機(今手元にはmacのみ)で試してみます。 ところで根本的な疑問ですが、 CreateThreadをで一報を別スレッドにして、メインスレッドでCOM1もう一方のスレッドでCOM2というのではダメなのでしょうか? あくまでopenmpの並列でという条件でしょうか?
xasax0404

2016/10/27 00:47

ありがとうございます。よろしくお願いします。 すみません。。。スレッドを別にするやり方や意味?がよく分かっていないため試していないどころか思いつきもしてません。 目的の動作さえ出来ればいいとばかり考えていたので。。。 openmp以外の手法で他にあるならそれでも大丈夫です
hiim

2016/10/28 16:38

後日確認して回答すると言っておきながらおそくなりすいません。 ここ6,7年は完全にwindowsから離れlinux。web系の事ばかりしているため、windows環境の構築から行わないといけなかったり、会社の飲み会等でなかなかwindows機を開くことができずおそくなりました。 さきほどまで会社の飲み会だったため、酔っ払いながらのコーディングなので細かい設定、エラー処理等まったくすっとばして、単にメインスレッドからサブスレッドを立てそれぞれのスレッドで各ポートでループバック通信しているだけのソースになりますが、COM1、COM2で同時に並列に通信はしております。 またこの各すれっどの関数をopenmpの#pragma omp sectionに書いても並列で通信できているのは確認いたしましたのでご参考にしてください。 ただし飲酒コーディングなので細かい所は適宜直してください。。。
hiim

2016/10/28 16:44

CreateThread等でマルチスレッドとしてプログラムを組むときは変数の扱い等、スレッドセーフに気をつけて使用してください、同じリソースを両スレッドから使う場合、つぶしあわないように。。。。
hiim

2016/10/29 02:24

昨夜は酔った状態でのかなりはしょりすぎのサンプルだったため少しだけ補足をいれさせていただきました
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問