アプリ版:「スタンプのみでお礼する」機能のリリースについて

初心者です。XPとVC++ 6.0で開発しています。
シリアル通信プログラムを作成しておりますが、クロスケーブルでPC同士をつないで、片方はハイパーターミナル(以下H)を立ち上げて、もう片方は、作成しているプログラム(以下P)を走らせて通信しようとしています。Pから、Hへの送信はできるのですが、Hを走らせているPCのキーボードをたたいても、Pで受信ができません。WaitForMultipleObjects関数のところで待機状態になったままです。DEBUGの進め方についてアドバイスをいただけますでしょうか。
Pを実行した際には、GetLastError関数がERROR_IO_PENDINGを返しており、IOからのデータ待機状態に入っています。(※P,H共に、COM1,9600bps,8bit,NONEに設定しています。)ご教示お願いいたします。
// PURPOSE: This is the starting point for the Read Thread.
DWORD WINAPI StartReadThreadProc(LPVOID lpvParam)
{
char szInputBuffer[INPUTBUFFERSIZE];
DWORD nNumberOfBytesRead;
HANDLE HandlesToWaitFor[3];
DWORD dwHandleSignaled;
DWORD fdwEvtMask;
OVERLAPPED overlappedRead = {0, 0, 0, 0, NULL};
OVERLAPPED overlappedCommEvent = {0, 0, 0, 0, NULL};
overlappedRead.hEvent = CreateEvent(NULL, TRUE, TRUE, NULL);
overlappedCommEvent.hEvent = CreateEvent(NULL, TRUE, TRUE, NULL);
// We will be waiting on these objects. このイベントが立つまでRX動作は待機状態になる。
HandlesToWaitFor[0] = g_hCloseEvent1;
HandlesToWaitFor[1] = overlappedCommEvent.hEvent;
HandlesToWaitFor[2] = overlappedRead.hEvent;
// Keep looping until we break out.
while (TRUE)
{
// Wait until some event occurs (data to read; error; stopping).
dwHandleSignaled = WaitForMultipleObjects(3,HandlesToWaitFor, FALSE, INFINITE);
switch(dwHandleSignaled)
{
case WAIT_OBJECT_0: // Signal to end the thread.
{
// Time to exit.
}
case WAIT_OBJECT_0 + 1: // CommEvent signaled.
{
// Handle the CommEvent.
// Start waiting for the next CommEvent.
break;
}
case WAIT_OBJECT_0 + 2: // Read Event signaled.
{
// Get the new data!
break;
}
case WAIT_FAILED: // Wait failed. Shouldn't happen.
{
goto EndReadThread;
}
default: // This case should never occur.
{
OutputDebugString("Unexpected Wait return value");
goto EndReadThread;
}
} // End of switch(dwHandleSignaled).
} // End of while(TRUE) loop.
// Time to clean up Read Thread.
EndReadThread:
OutputDebugString("Read thread shutting down\n");
PurgeComm(g_hCommFile1, PURGE_RXABORT | PURGE_RXCLEAR);
CloseHandle(overlappedRead.hEvent);
CloseHandle(overlappedCommEvent.hEvent);
g_dwReadThreadID1 = 0;
CloseHandle(g_hReadThread1);
g_hReadThread1 = 0;
return 0;
}

A 回答 (4件)

ところで、誰がイベントをシグナル状態にするんですか?


誰も何もしていないような気がします。
普通は受信割り込み処理の中でSetEventします。

この回答への補足

えーと、退職した前任者からのひきつぎなので、勉強しながらのプログラミングなのですが、overlappedCommEvent.hEvent = CreateEvent(NULL, TRUE, TRUE, NULL); でシリアルからデータが来た場合にイベントが立つんじゃないんでしょうか?
接続先のPCのキーボードをたたいて、データが飛んできて、それに反応する割り込み処理?が必要なのでしょうか。
すみません、勉強しながらなので、いまいちシーケンスの深い理解が得られておりません。

補足日時:2009/08/20 13:00
    • good
    • 0

>overlappedCommEvent.hEvent = CreateEvent(NULL, TRUE, TRUE, NULL); でシリアルからデータが来た場合にイベントが立つんじゃないんでしょうか?



「シリアルからデータが来た場合にイベントが立つ」んじゃなくて「シリアルからデータが来た場合に『自分で』イベントを立てなきゃならない」のです。

イベントを立てるには「SetEvent()を使う」ので、必ず、受信ルーチンのソースのどこかにSetEvent()がある筈です。

もし、SetEvent()が無いのであれば「質問者さん自身が、必要な場所に的確にSetEvent()を書き加えなければならない」ので、自分で書き加えましょう。

この回答への補足

chie65535様、nda23様 失礼致しました。プログラムが長かったので、はしょった部分に、下記の処理が入ってました。
一応非同期通信に必要?なWaitCommEventとReadFile関数が入ってました。SetCommMask関数が入っていなかったのですがこれも必要でしょうか?
HandlesToWaitFor[2] = overlappedRead.hEvent;
*
*
// Setup CommEvent handling.
// Start waiting for CommEvents (Errors)
if (!SetupCommEvent(&overlappedCommEvent, &fdwEvtMask))
//SetupCommEvent内部でWaitCommEvent関数を設定しています。
{ goto EndReadThread; }

// Start waiting for Read events.
if (!SetupReadEvent(&overlappedRead,
//SetupReadEvent内部でReadFile関数を設定しています。
szInputBuffer, INPUTBUFFERSIZE,
&nNumberOfBytesRead))
{ goto EndReadThread; }
*
*
// Keep looping until we break out.
while (TRUE)

補足日時:2009/08/20 14:48
    • good
    • 0

う~ん・・・ 初心者にマルチスレッドの同期制御はハッキリ言って荷が


重過ぎますね。スレッドだとか同期だとか聞いてピンときますか?

とりあえず、次の点を調べてみて下さい。
(1)CreateFile
FILE_FLAG_OVERLAPPED が指定されていますか?
(2)ReadFile
第5パラメータのhEventメンバに作成したイベントがセットされて
いますか?

いずれも指定通りなら、イベントが発生するはずです。

>goto EndReadThread
こういうコーディングを見ると、コメントのしようがありません。
さいとう たかを のマンガではないけど、「・・・」です。
大変な仕事を引き受けられたご様子、お察し申し上げます。

この回答への補足

nda23様 アドバイスありがとうございます。
もう脳みそがゆでだこ状態です。オーバーヒート気味です(笑)カーニハン,リッチーのプログラミング言語Cから初めて、ただいまVC++に足を突っ込んでいます。

CreatFile, ReadFileについては、下記の様に作成されており問題ないようです。
(1)hComm = CreateFile( port,GENERIC_READ | GENERIC_WRITE,0, NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
NULL);

(2)ReadFile(g_hCommFile1,lpszInputBuffer, dwSizeofBuffer,lpnNumberOfBytesRead, lpOverlappedRead)
PARAMETERSの説明・・・
// lpOverlappedRead - address of overlapped structure to use.
// lpszInputBuffer - Buffer to place incoming bytes.
// dwSizeofBuffer - size of lpszInputBuffer. </code></pre>
// lpnNumberOfBytesRead - address of DWORD to place the number of read bytes.

イベントが発生すれば、プログラムはWaitForMultipleObjects関数から次のステップに進むはずですよね?この関数の最後の引数を1000(ms)とかにすると、ちゃんとWAIT_TIMEOUTで抜けて、イベントが発生していないことは確認できました。そもそものパリティの設定がおかしいのかとも思いましたが、送信はできていましたし、NONEにしてもEVENにしても受信できませんでした。他に何を検証したらよろしいでしょうか・・・。

※あと、SetCommMaskもSetupCommEventとSetupReadEventの前に設定さていました。
// Setup CommEvent handling.
// Set the comm mask so we receive error signals.
if (!SetCommMask(g_hCommFile1, EV_ERR))
{ OutputDebugString("Unable to SetCommMask: ");
goto EndReadThread; }

どうやらこちらのサイトのものとそっくりなようです。↓
http://topic.csdn.net/t/20010420/16/101329.html

補足日時:2009/08/20 16:39
    • good
    • 0

見た目はOKですね。


イベントハンドルが渡っているなら、通信エラーが考えられます。
ACEにどんな設定をしたか、調べてみて下さい。
http://www.ys-labo.com/BCB/2007/070512%20RS232C% …
http://members.jcom.home.ne.jp/0434383301/vc10.htm
いきなりではなく、先ず1バイトの送受信を割り込みでなく、
普通に実行してみましょう。
    • good
    • 0
この回答へのお礼

nda23様
ご返答有難うございます。
一歩一歩確認していきます。
ご教示ありがとうございました。

お礼日時:2009/08/21 13:11

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!