Как я могу читать с COM-порта RS485 в C ++ с Windows? - PullRequest
0 голосов
/ 16 марта 2020

Я пытаюсь управлять источником напряжения через RS485 (через преобразователь USB в RS485). Я использую Стандарт C ++ в Visual Studio. Я написал следующий код. Запись работает нормально, источник напряжения реагирует на все входные данные, но чтение байтов мне сложно. Например, ответом может быть следующая строка: «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
            );*/
        }
    }
}

Вывод, который я получаю:

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

Источник напряжения перепрыгивает на 12 В, поэтому она получила команду.

РЕДАКТИРОВАТЬ: я изменил 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?

Так что в принципе это работает, но я получаю много странные признаки.

РЕДАКТИРОВАТЬ 2: Еще одна проблема, с которой я все еще сталкиваюсь, заключается в том, что после перезагрузки компьютера больше ничего не работает, и мне нужно запустить HTerm, нажать кнопку подключения и отключения, что, по-видимому, делает несколько инициализаций, которые я пропускаю в моем программа. После этого он работает до следующей перезагрузки компьютера. Есть ли у вас какие-либо идеи, которых у меня может не быть в моей программе?

Ответы [ 2 ]

1 голос
/ 16 марта 2020

Вы получите странные знаки, потому что bytes_to_receive не является строкой с нулевым символом в конце. printf продолжает читать байты, пока не увидит нулевой (0) байт. Вы не помещаете нулевой байт в bytes_to_receive, поэтому он продолжает печатать, пока не выйдет из конца и не найдет его где-то еще.

ReadFile сообщает вам, сколько байтов было прочитано, в dwBytesRead Таким образом, вы можете добавить нулевой байт для printf: bytes_to_receive[dwBytesRead] = '\0';.

Убедитесь, что размер bytes_to_receive увеличен до 8 , потому что теперь вы пишете один дополнительный байт. Тем не менее, передайте 7 в ReadFile, потому что вы не хотите читать 8 байтов - вы добавляете нулевой байт самостоятельно после чтения данных.

0 голосов
/ 25 марта 2020

Хорошо, пока я решил проблему. Нужен дополнительный код, я надеюсь, что смогу помочь следующему, у которого возникла та же проблема, в противном случае я открыт для предложений по улучшению. Спасибо за вашу поддержку, я раздал голоса всем, кто мне помог.

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);
...