1

WIN32 API を使用して C++ のシリアル ポートに書き込もうとしましたが、WriteFile は ERROR_IO_PENDING を返しませんが、何も起こりません。書き込みコードです:

static DCB dcb = {0};
static HANDLE hComm;
static int _tmain(int argc, _TCHAR* argv[])
{
    hComm = CreateFile(
    L"\\\\.\\COM3",
    GENERIC_WRITE | GENERIC_READ,
    0,
    NULL,
    OPEN_EXISTING,
    NULL,   
    NULL
    );

if (hComm == INVALID_HANDLE_VALUE) // error opening port; abort
    printf_s("INVALID_HANDLE_VALUE\n");

if (GetCommState(hComm, &dcb))// DCB is ready for use.
{
    dcb.BaudRate = CBR_19200; //19200 Baud
    dcb.ByteSize = 8; //8 data bits
    dcb.Parity = NOPARITY; //no parity
    dcb.StopBits = ONESTOPBIT; //1 stop
    printf_s("set UP DCB\n");
}
else // Error getting current DCB settings
    printf_s("ERROR getting \n"+GetLastError());

osWrite.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);

    WriteABuffer("!serialCMDtoSend\r",sizeof("!serialCMDtoSend\r");
}
static BOOL WriteABuffer(char * lpBuf, DWORD dwToWrite)
{
        // Issue write.
        if (!WriteFile(hComm, lpBuf, dwToWrite, &dwWritten, &osWrite)) 
        {
            if (GetLastError() != ERROR_IO_PENDING) { // WriteFile failed, but it isn't delayed. Report error and abort.
                fRes = FALSE;
            }
            else {
                // Write is pending.
                if (!GetOverlappedResult(hComm, &osWrite, &dwWritten, TRUE))
                    fRes = FALSE;
                else
                    fRes = TRUE;// Write operation completed successfully.
            }
        }
        else
            fRes = TRUE;        // WriteFile completed immediately.
    return fRes;
}

誰でも私のバグを見ることができますか?

4

2 に答える 2

2

これは偶然に機能します。CreateFile 呼び出しで FILE_FLAG_OVERLAPPED を指定するのを忘れたので、重複した I/O を取得できません。エラー処理が壊れているため、おそらくこれについて知らなかったでしょう。GetLastError が ERROR_IO_PENDING を返さないときのエラー コードがどのように見えるかわかりません。データがドライバーの送信バッファーに収まるため、WriteFile をブロックする必要がない場合、偶然に機能します。ベンが説明したように、ハンドシェイクの設定をモジュロします。

重複した I/O を使用して GetOverlappedResult(TRUE) をすぐに呼び出しても、まったく意味がありません。オーバーラップしていない I/O を使用する方がはるかに簡単です。他に何か役に立つことがあり、WaitForMultipleObjects() を呼び出して書き込みが完了したかどうかを確認できる場合にのみ使用してください。非同期コードを書くのは簡単ではありません。

于 2013-04-13T16:30:43.157 に答える
0

を使用するよりも、クリーンな DCB から開始する方がよい場合がありGetCommStateます。たとえば、フロー制御をオフにしていないため、動作は最後のプログラムがどのように終了したかによって異なります。

フロー制御フィールドを正しく設定する必要があります。

fOutxCtsFlow
fOutxDsrFlow
fDtrControl
fDsrSensitivity
fOutX
fInX
fRtsControl

一般に、GetCommStateプログラムを以前の設定に依存させたくない場合は、使用しないことをお勧めします。代わりに、すべてゼロから始めます。

DCB dcb = { sizeof dcb };
dcb.fBinary = TRUE;
dcb.BaudRate = 19200; //19200 Baud
dcb.ByteSize = 8; //8 data bits
dcb.Parity = NOPARITY; //no parity
dcb.StopBits = ONESTOPBIT; //1 stop

以前の設定への依存に加えて、設定GetCommStateしていないために失敗していますDCBlength(ドキュメントには、これは呼び出し元であるあなたが設定する必要があると明確に記載されています。 GetCommState最初に指定したサイズを確認せずにバッファを埋めることはできません)。

于 2013-04-13T15:36:25.220 に答える