简体   繁体   English

如何使用 Windows 从 C++ 中的 RS485 COM 端口读取数据?

[英]How can I read from an RS485 COM port in C++ with Windows?

I try to control a voltage source via RS485 (via a USB to RS485 converter).我尝试通过 RS485(通过 USB 到 RS485 转换器)控制电压源。 I use Standard C++ in Visual Studio.我在 Visual Studio 中使用标准 C++。 I wrote the following code.我写了以下代码。 Writing works fine, the voltage source responds to all input, but reading back bytes is difficult for me.写入工作正常,电压源响应所有输入,但读回字节对我来说很困难。 For example, the answer might be the following string: "12.000" (31 32 2E 30 30 30 0A)例如,答案可能是以下字符串:"12.000" (31 32 2E 30 30 30 0A)

#include <iostream>
#include <string.h>
#include <windows.h>
#include <msports.h>
#include <stdlib.h>

const unsigned char oe = static_cast<unsigned char>(148);

int main()
{

    //create new handle
    HANDLE hComm;
    hComm = CreateFile(L"\\\\.\\COM5",
        GENERIC_READ | GENERIC_WRITE,
        0,
        0,
        OPEN_EXISTING,
        FILE_FLAG_OVERLAPPED,
        0);
    if (hComm == INVALID_HANDLE_VALUE)
        printf("CreateFile handle failed ERROR: %d.\n", GetLastError());

    /*
    //Timwouts
    COMMTIMEOUTS CTO;
    CTO.ReadIntervalTimeout = 500;
    CTO.ReadTotalTimeoutConstant = 500;
    CTO.ReadTotalTimeoutMultiplier = 500;
    CTO.WriteTotalTimeoutConstant = 500;
    CTO.WriteTotalTimeoutMultiplier = 500;

    //build DCB strukture
    DCB dcb;

    if (!BuildCommDCB(L"COM5 baud=115200 parity=N data=8 stop=1", &dcb))
    {
        MessageBox(0, L"Error BuildCommDCB", L"Test", MB_OK);
    }

    if (!SetCommTimeouts(hComm, &CTO))
    {
        MessageBox(0, L"Error CommTimeouts", L"Test", MB_OK);
    }
    */

    //Variables for read RS485
    char sBuffer[1024];

    //Variables for user input values
    char parameter1;
    float floatV;
    char parameter2;

    while (true) {
        std::cout << "Hallo, was m" << oe << "chten Sie tun?\n";
        std::cin >> parameter1 >> floatV >> parameter2;
        //std::cout << "parameter1: " << parameter1 << "\n";
        //std::cout << "floatV: " << floatV << "\n";
        //std::cout << "parameter2: " << parameter2 << "\n";
        //system("cls");

        if (parameter1 == 'Q' && parameter2 == 'V') {
            uint32_t Voltage = (uint32_t)(floatV * 1000);
            char myString[30];
            sprintf_s(myString, "%f", floatV);

            //Set new voltage
            //VSET:
            TransmitCommChar(hComm, 'V');
            TransmitCommChar(hComm, 'S');
            TransmitCommChar(hComm, 'E');
            TransmitCommChar(hComm, 'T');
            TransmitCommChar(hComm, ':');
            //Wert
            TransmitCommChar(hComm, myString[0]);
            TransmitCommChar(hComm, myString[1]); 
            TransmitCommChar(hComm, myString[2]);
            TransmitCommChar(hComm, myString[3]);
            TransmitCommChar(hComm, myString[4]);
            TransmitCommChar(hComm, myString[5]);
            //ENTER
            TransmitCommChar(hComm, 0x0A);

            //Get the voltage of the source
            //Control V
            //56 53 45 54 3F 0A
            TransmitCommChar(hComm, 'V');
            TransmitCommChar(hComm, 'S');
            TransmitCommChar(hComm, 'E');
            TransmitCommChar(hComm, 'T');
            TransmitCommChar(hComm, '?');
            TransmitCommChar(hComm, 0x0A);

            //Sleep(100);
            /*
            LPVOID buffRead = 0;
            DWORD dwBytesRead = 0;
            if (!ReadFile(hComm, &buffRead, 6, &dwBytesRead, NULL))
            {
                printf("error reading from input buffer \n");
            }
            printf("Data read from read buffer is \n %s \n", (char*)buffRead);
            */

            DWORD dwBytesRead = 0;
            char bytes_to_receive[7];

            if (!ReadFile(hComm, bytes_to_receive, 7, &dwBytesRead, NULL)) {
                printf("SetCommState failed. Error: %d.\n", GetLastError());
                //CloseHandle(hComm);
                //return (4);
            }
            else {
                printf("Bytes read %d -> %s\n", dwBytesRead, bytes_to_receive);
            }

            /*if (ReadFile(hComm, sBuffer, 7, NULL, NULL)) {
                printf("%s \n", sBuffer);
            }
            else {
                printf("Reading file fails! \n");
            }*/

            /*UINT numberBytesRead = _lread(
                HFILE  hFile,
                LPVOID lpBuffer,
                UINT   uBytes
            );*/
        }
    }
}

The output I get is:我得到的输出是:

Hallo, was möchten Sie tun?
Q12V
SetCommState failed. Error: 87.
Hallo, was möchten Sie tun?

The voltage source jumps to 12V, so she got the command.电压源跳到12V,所以她得到了命令。

EDIT: I changed FILE_FLAG_OVERLAPPED to FILE_ATTRIBUTE_NORMAL, now I get:编辑:我将 FILE_FLAG_OVERLAPPED 更改为 FILE_ATTRIBUTE_NORMAL,现在我得到:

Hallo, was möchten Sie tun?
Q12V
Bytes read 7 -> 12.000
╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠G┤°V
Hallo, was möchten Sie tun?

So it basically seems to work, but I get a lot of strange signs.所以它基本上似乎有效,但我得到了很多奇怪的迹象。

EDIT 2: Another problem that I still face is that after restarting the computer nothing works anymore and I need to start HTerm, press connect and disconnect, what apparently makes a few initializations that I miss in my program.编辑 2:我仍然面临的另一个问题是,重新启动计算机后没有任何工作,我需要启动 HTerm,按连接和断开连接,这显然使我在程序中错过了一些初始化。 After that it works till the next restart of the computer.之后它会一直工作到下一次重新启动计算机。 Do you have any ideas what I might not have in my program?你有什么想法我的程序中可能没有吗?

You get strange signs because bytes_to_receive is not a null-terminated string.你会得到奇怪的符号,因为bytes_to_receive不是以空字符结尾的字符串。 printf keeps reading bytes until it sees a null (0) byte. printf继续读取字节,直到它看到空 (0) 字节。 You don't put a null byte in bytes_to_receive , so it keeps printing until it goes off the end and finds one somewhere else.您没有在bytes_to_receive放置空字节,因此它会一直打印,直到它结束并在其他地方找到一个。

ReadFile tells you how many bytes were read, in dwBytesRead , so you can add a null byte for printf : bytes_to_receive[dwBytesRead] = '\\0'; ReadFile告诉您在dwBytesRead中读取了多少字节,因此您可以为printf添加一个空字节: bytes_to_receive[dwBytesRead] = '\\0'; . .

Make sure to increase the size of bytes_to_receive to 8 because now you are writing one extra byte.确保将bytes_to_receive的大小增加到8,因为现在您正在写入一个额外的字节。 Still pass 7 to ReadFile because you don't want to read 8 bytes - you are adding the null byte yourself after reading the data.仍然将 7 传递给 ReadFile 因为您不想读取 8 个字节 - 您在读取数据后自己添加了空字节。

Ok, in the meantime I solved the problem.好的,同时我解决了这个问题。 Some extra code is needed, I hope I can help the next one who has the same problem, otherwise I am open to suggestions for improvement.需要一些额外的代码,我希望我可以帮助下一个遇到同样问题的人,否则我愿意接受改进的建议。 Thank you for your support, I have distributed upvotes to all who have helped me.感谢您的支持,我已经向所有帮助过我的人分发了upvote。

DCB Dcb;
COMMTIMEOUTS Cto;
HANDLE hComm;

//Create file Handle
hComm = CreateFile(L"\\\\.\\COM5",
    GENERIC_READ | GENERIC_WRITE,
    0,
    0,
    OPEN_EXISTING,
    FILE_ATTRIBUTE_NORMAL,
    0);
if (hComm == INVALID_HANDLE_VALUE) {
    printf("CreateFile handle failed ERROR: %d.\n", GetLastError());
}

//Data Center Bridging
Dcb.DCBlength = sizeof(Dcb);
GetCommState(hComm, &Dcb);
Dcb.BaudRate = CBR_115200;
Dcb.fParity = false;
Dcb.fNull = false;
Dcb.StopBits = ONESTOPBIT;
Dcb.Parity = NOPARITY;
Dcb.ByteSize = 8;
SetCommState(hComm, &Dcb);

//Timeouts
Cto.ReadIntervalTimeout = 0;
Cto.ReadTotalTimeoutMultiplier = 0;
Cto.ReadTotalTimeoutConstant = 0;
Cto.WriteTotalTimeoutMultiplier = 0;
Cto.WriteTotalTimeoutConstant = 0;
SetCommTimeouts(hComm, &Cto);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM