【问题标题】:Serial Comm using WriteFile/ReadFile使用 WriteFile/ReadFile 的串行通信
【发布时间】:2011-08-27 13:27:39
【问题描述】:
//#include "StdAfx.h"
#include <stdio.h> 
#include <windows.h> 
#include <winbase.h>
#include <iostream>
#include <tchar.h>
using namespace std;

int main()
{

    int com = 'COM2';
    string data = "\n 010400 \n";
    char output[32];
    //unsigned int length = 0;
    DCB config = {0};
    bool abContinue = true;
    DWORD dwBytesWritten;
    DWORD  dwBytesRead;
    int isRead = false;

    HANDLE m_hCommPort = ::CreateFile(L"COM2",
        GENERIC_READ|GENERIC_WRITE,//access ( read and write)

        0,    //(share) 0:cannot share the COM port                        

        0,    //security  (None)                

        OPEN_EXISTING,// creation : open_existing

        0,    // we dont want overlapped operation

        0// no templates file for COM port...

        );

    config.DCBlength = sizeof(config);


    if((GetCommState(m_hCommPort, &config) == 0))
    {
        printf("Get configuration port has a problem.");
        return FALSE;
    }

    config.BaudRate = 9600;
    config.StopBits = ONESTOPBIT;
    config.Parity = PARITY_NONE; 
    config.ByteSize = DATABITS_8;
    config.fDtrControl = 0;
    config.fRtsControl = 0;

    if (!SetCommState(m_hCommPort, &config))
    {

        printf( "Failed to Set Comm State Reason: %d\n",GetLastError());
        //return E_FAIL;
    }

    printf("Current Settings\n Baud Rate %d\n Parity %d\n Byte Size %d\n Stop Bits %d", config.BaudRate, 
        config.Parity, config.ByteSize, config.StopBits);

    int isWritten = WriteFile(m_hCommPort, &data,(DWORD) sizeof(data), &dwBytesWritten, NULL);


    //memset(output, 0, sizeof(output));
    while (abContinue) 
    {

        isRead = ReadFile(m_hCommPort, output, sizeof(output), &dwBytesRead, NULL);

        if(!isRead)
        {
            abContinue = false;
            break;
        }

    }

    cin.get();
}

我无法从 com 端口读取数据。如果我单步执行代码,它会进入“isRead = ReadFile(m_hCommPort, output, sizeof(output), &dwBytesRead, NULL);”并且没有回来......这是我第一次尝试但没有成功。

【问题讨论】:

  • 我的问题恰恰相反。 ReadFile 不等待任何内容,只返回读取 0 字节并返回值 TRUE -.-

标签: c++ visual-studio serial-port


【解决方案1】:

您可以在打开文件后尝试使用类似这样的代码,但在尝试使用它之前:

COMMTIMEOUTS timeouts;

timeouts.ReadIntervalTimeout = 1;
timeouts.ReadTotalTimeoutMultiplier = 1;
timeouts.ReadTotalTimeoutConstant = 1;
timeouts.WriteTotalTimeoutMultiplier = 1;
timeouts.WriteTotalTimeoutConstant = 1;
if (!SetCommTimeouts(m_hCommPort, &timeouts))
    // setting timeouts failed.

编辑:也许从一些可以工作的代码开始,然后让它做你想做的事情,而不是试图让你的代码工作更容易。这是一个简单的终端程序。它是极端的极简主义,但确实有效(例如,至少足以让我看到 GPS 的输出)。这距离任何人(至少我)所说的复杂还有很长的路要走,但至少应该给出一些如何开始的想法。

#include <stdio.h>
#include <conio.h>
#include <string.h>

#define STRICT
#define WIN32_LEAN_AND_MEAN
#include <windows.h>

void system_error(char *name) {
// Retrieve, format, and print out a message from the last error.  The 
// `name' that's passed should be in the form of a present tense noun 
// (phrase) such as "opening file".
//
    char *ptr = NULL;
    FormatMessage(
        FORMAT_MESSAGE_ALLOCATE_BUFFER |
        FORMAT_MESSAGE_FROM_SYSTEM,
        0,
        GetLastError(),
        0,
        (char *)&ptr,
        1024,
        NULL);

    fprintf(stderr, "\nError %s: %s\n", name, ptr);
    LocalFree(ptr);
}

int main(int argc, char **argv) {

    int ch;
    char buffer[1];
    HANDLE file;
    COMMTIMEOUTS timeouts;
    DWORD read, written;
    DCB port;
    HANDLE keyboard = GetStdHandle(STD_INPUT_HANDLE);
    HANDLE screen = GetStdHandle(STD_OUTPUT_HANDLE);
    DWORD mode;
    char port_name[128] = "\\\\.\\COM3";
    char init[] = ""; // e.g., "ATZ" to completely reset a modem.

    if ( argc > 2 )
        sprintf(port_name, "\\\\.\\COM%c", argv[1][0]);

    // open the comm port.
    file = CreateFile(port_name,
        GENERIC_READ | GENERIC_WRITE,
        0, 
        NULL, 
        OPEN_EXISTING,
        0,
        NULL);

    if ( INVALID_HANDLE_VALUE == file) {
        system_error("opening file");
        return 1;
    }

    // get the current DCB, and adjust a few bits to our liking.
    memset(&port, 0, sizeof(port));
    port.DCBlength = sizeof(port);
    if ( !GetCommState(file, &port))
        system_error("getting comm state");
    if (!BuildCommDCB("baud=19200 parity=n data=8 stop=1", &port))
        system_error("building comm DCB");
    if (!SetCommState(file, &port))
        system_error("adjusting port settings");

    // set short timeouts on the comm port.
    timeouts.ReadIntervalTimeout = 1;
    timeouts.ReadTotalTimeoutMultiplier = 1;
    timeouts.ReadTotalTimeoutConstant = 1;
    timeouts.WriteTotalTimeoutMultiplier = 1;
    timeouts.WriteTotalTimeoutConstant = 1;
    if (!SetCommTimeouts(file, &timeouts))
        system_error("setting port time-outs.");

    // set keyboard to raw reading.
    if (!GetConsoleMode(keyboard, &mode))
        system_error("getting keyboard mode");
    mode &= ~ ENABLE_PROCESSED_INPUT;
    if (!SetConsoleMode(keyboard, mode))
        system_error("setting keyboard mode");

    if (!EscapeCommFunction(file, CLRDTR))
        system_error("clearing DTR");
    Sleep(200);
    if (!EscapeCommFunction(file, SETDTR))
        system_error("setting DTR");

    if ( !WriteFile(file, init, sizeof(init), &written, NULL))
        system_error("writing data to port");

    if (written != sizeof(init))
        system_error("not all data written to port");

    // basic terminal loop:
    do {
        // check for data on port and display it on screen.
        ReadFile(file, buffer, sizeof(buffer), &read, NULL);
        if ( read )
            WriteFile(screen, buffer, read, &written, NULL);

        // check for keypress, and write any out the port.
        if ( kbhit() ) {
            ch = getch();
            WriteFile(file, &ch, 1, &written, NULL);
        }
    // until user hits ctrl-backspace.
    } while ( ch != 127);

    // close up and go home.
    CloseHandle(keyboard);
    CloseHandle(file);
    return 0;
}

【讨论】:

  • 好的,这似乎解决了线程问题,但我似乎无法让 ReadFile() 填充我的输出数组。
  • 我应该澄清一下,我正在尝试通过串行与嵌入式系统进行通信,其请求/响应协议基于字符串。我让它在超级终端上工作,但我正在尝试创建自己的代码,它基本上做同样的事情。
  • 好的,我已经更彻底地查看了您的代码。真的很有帮助,谢谢!
【解决方案2】:

如果您不explicitly set the timeouts,则 ReadFile 将无限期阻塞,直到数据可用。

【讨论】:

    【解决方案3】:

    ReadFile 函数可能会阻塞您的线程,如果是这样,它将一直阻塞,直到可以从串行端口读取一些数据。这是link 看看它是否有帮助。祝你好运。

    【讨论】:

      【解决方案4】:

      我在设置了超时的读取文件上遇到了这个问题。这让我大吃一惊,所以我最终从网上获得了一些确实有效的代码,然后逐行更改以查看错误在哪里。

      原来他的 readfile 没问题。我的问题是 WaitCommEvent 在端口断开连接时挂起,因为没有收到任何 com 事件...

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-04-07
        • 1970-01-01
        • 1970-01-01
        • 2021-12-18
        • 1970-01-01
        • 2016-10-30
        相关资源
        最近更新 更多