【问题标题】:read from serial port c++从串口 C++ 读取
【发布时间】:2011-12-24 06:47:39
【问题描述】:

我有以下 C++ 代码,当我运行该程序时,有时它可以工作,有时它不能!

我认为当我在有数据要读取的情况下尝试打开串行端口时会出现问题。

有时运行此程序后,会导致 Windows XP 意外重启!它不会蓝屏,它只是重新启动。

我正在使用 Visual Studio 2010 来编译它。

main()
{
    while(0) { // BIG FAT WARNING: MIGHT SUDDEN REBOOT YOUR MACHINE IF ENABLED
        read_from_serial(_data);
    }
}

bool read_from_serial(octed_string &_data)
{
    HANDLE hSerial;
    hSerial = CreateFile(TEXT("COM2"),
                         GENERIC_READ|GENERIC_WRITE,0,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);

    if (hSerial == INVALID_HANDLE_VALUE)
    {
        if (GetLastError() == ERROR_FILE_NOT_FOUND)
        {
            cout << "1:";
            return false;
        //serialportdoesnotexist.Informuser.
        }
        cout << "2:";
        return false;

        //someothererroroccurred.Informuser.
    }

    DCB dcbSerialParams = {0};
    dcbSerialParams.DCBlength=sizeof(dcbSerialParams);

    if(!GetCommState(hSerial,&dcbSerialParams))
    {
        cout<<"3:";
        return false;
        //errorgettingstate
    }

    dcbSerialParams.BaudRate=CBR_9600;
    dcbSerialParams.ByteSize=7;
    dcbSerialParams.StopBits=ONESTOPBIT;
    dcbSerialParams.Parity=EVENPARITY;

    if (!SetCommState(hSerial,&dcbSerialParams))
    {
        cout<<"4:";
        return false;
        //errorsettingserialportstate
    }

    COMMTIMEOUTS timeouts={0};
    timeouts.ReadIntervalTimeout=50;
    timeouts.ReadTotalTimeoutConstant=10;
    timeouts.ReadTotalTimeoutMultiplier=10;
    timeouts.WriteTotalTimeoutConstant=50;
    timeouts.WriteTotalTimeoutMultiplier=10;

    if (!SetCommTimeouts(hSerial,&timeouts))
    {
        cout<<"5:";
        return false;
        //erroroccureed.Informuser
    }

    const int n=1;

    DWORD dwBytesRead=0;

    char_t tmp_receive[255]={0};

    char_t buff[255];

    int len=255;

    if (!ReadFile(hSerial,tmp_receive,len,&dwBytesRead,NULL))
    {
        cout<<"6:";
        CloseHandle(hSerial);
        return false;
    }

    CloseHandle(hSerial);

    tmp_receive[dwBytesRead+1]=END_OF_STRING;
    string tmp_buff_str=tmp_receive;
    _data.append(tmp_buff_str);
    return true;
}

【问题讨论】:

  • 这是为你编译的吗?你真正的程序是什么样的?
  • sometimes running this program makes my XP os restart! - 哇。我建议你不要运行它。会蓝屏吗?错误是什么?事件日志中有什么? Windows 更新?
  • 这个程序没有被编译。也许编译器会让你的 XP 操作系统重新启动?考虑使用其他编译器。
  • 扔掉适配器。换一个更好的司机。

标签: c++ visual-studio-2010 winapi serial-port windows-xp


【解决方案1】:

原因

我怀疑你的程序在这条线上崩溃了

tmp_receive[dwBytesRead+1]=END_OF_STRING;

您使用255 元素定义了tmp_receive 数组,这使得可能的索引0 变为254。然后将len 初始化为255。如果在调用ReadFile(...) 时有255 个字节可供读取,那么dwBytesRead 将等于255,并且我上面提到的行实际上如下所示,这意味着您正在尝试写入内存在tmp_receive 数组的范围之外。

tmp_receive[256] = END_OF_STRING;

至于重新启动,我不确定,但是当您的程序尝试写入无效内存并且您将 Windows XP 配置为重新启动而不是显示BSOD 时,它可能会导致系统崩溃。


解决方案

为了防止您的程序崩溃,我看到您有 2 个选项。我不能说哪个更好,因为我不知道您期望收到的数据格式是什么,因此您必须分析每个选项的结果并自己决定。

选项 #1

在定义 tmp_receive 数组时使用元素计数 257

选项 #2

拨打ReadFile(...)时从len中减去2

if (!ReadFile(hSerial,tmp_receive,len-2,&dwBytesRead,NULL))

其他信息

  • 查看 ReadFile(...) 上的 MSDN 文档,了解有关 ReadFile(...) Windows API 行为的更多信息。

  • 如果您想了解有关字符串如何存储在内存中的更多信息,我建议您查看www.cplusplus.com 上的Character Sequences 文章。

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多