Windows 和 Dini Argeo 称重指示器之间的串行通信问题

问题描述 投票:0回答:0

我的 C++ 程序和指标之间存在通信问题: 我使用 Windows API 使用 CreateFileA 连接到它,我也尝试过 Boost.asio 但它给了我与这段实际代码相同的结果。

指示器连接到 USB 抛出一个 RS232 到 USB 适配器。

我的程序只是不断发送命令并检索答案。

发送我的第一个命令时,一切正常,但是当发送第二个命令时,指示器给我一个错误(ERR04 翻译为“不存在的命令已传输”)。

为了让它工作,我必须让我的 Thread 休眠超过 1 秒,然后再与指示器对话。

很明显,我不能使用那么长的延迟,我知道50ms对于指标来说是可以的,因为官方软件可以快速读写。

这是我的代码:

#include "USBConnection.hpp"

using namespace std;

USBConnection::USBConnection(char* comPort)
{
    this->keepRunning = true;
    this->baudrate = 9600;

    char comPath[20] = { 0 };
    sprintf_s(comPath, sizeof(comPath), "\\\\.\\%s", comPort);

    this->serialHandle = CreateFileA(comPath, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
    if (this->serialHandle == INVALID_HANDLE_VALUE)
    {
        cerr << "ERROR OPEN !" << endl;
        exit(EXIT_FAILURE);
    }

    SetupComm(this->serialHandle, DEVICE_BUFFER_SIZE, DEVICE_BUFFER_SIZE);
    purgeCommunication();

    COMMTIMEOUTS timeout = { 0 };
    timeout.ReadIntervalTimeout = -1;
    timeout.ReadTotalTimeoutConstant = 0;
    timeout.ReadTotalTimeoutMultiplier = 0;
    timeout.WriteTotalTimeoutConstant = 0;
    timeout.WriteTotalTimeoutMultiplier = 0;
    SetCommTimeouts(this->serialHandle, &timeout);

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

    GetCommState(serialHandle, &serialParams);
    serialParams.BaudRate = baudrate;
    serialParams.ByteSize = BYTE_SIZE;
    serialParams.StopBits = ONESTOPBIT;
    serialParams.Parity = NOPARITY;

    // Désactivation du mode binaire
    serialParams.fBinary = FALSE;

    // Désactivation des drapeaux de contrôle de flux matériels
    serialParams.fOutxCtsFlow = false;
    serialParams.fOutxDsrFlow = false;
    serialParams.fDtrControl = DTR_CONTROL_DISABLE;
    serialParams.fDsrSensitivity = false;

    // Désactivation des drapeaux de contrôle de flux logiciels
    serialParams.fOutX = false;
    serialParams.fInX = false;
    serialParams.fNull = false;

    if (!SetCommState(serialHandle, &serialParams))
    {
        cerr << "ERROR SETTING " << comPort << " !" << endl;
        exit(EXIT_FAILURE);
    }

    this->commThread = new thread(&USBConnection::communicationThread, this);
}

void USBConnection::stop(void)
{
    keepRunning = false;
    this->commThread->join();
    CloseHandle(this->serialHandle);
}

void USBConnection::purgeCommunication(void)
{
    if (!PurgeComm(this->serialHandle, PURGE_RXABORT | PURGE_RXCLEAR | PURGE_TXABORT | PURGE_TXCLEAR))
    {
        cout << "ERROR PURGE !" << endl;
    }
}

void USBConnection::readSerial(char* buffer, DWORD len)
{
    OVERLAPPED osRead = { 0 };
    DWORD dwRead;

    osRead.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
    if (osRead.hEvent == NULL)
    {
        cerr << "ERROR CREATE READ EVENT !" << endl;
        return;
    }

    if (!ReadFile(this->serialHandle, buffer, len, &dwRead, &osRead))
    {
        cerr << "ERROR READ !" << endl;
    }
}

void USBConnection::writeSerial(char* data, DWORD len)
{
    purgeCommunication();

    OVERLAPPED osWrite = { 0 };
    DWORD dwWritten;

    osWrite.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
    if (osWrite.hEvent == NULL)
    {
        cerr << "ERROR CREATE WRITE EVENT !" << endl;
        return;
    }

    if (!WriteFile(this->serialHandle, data, len, &dwWritten, &osWrite))
    {
        if (GetLastError() != ERROR_IO_PENDING)
        {
            cerr << "ERROR WRITE !" << endl;
            return;
        }
        else
        {
            if (!GetOverlappedResult(this->serialHandle, &osWrite, &dwWritten, TRUE))
            {
                cerr << "ERROR OVERLLAPED WRITE !" << endl;
                return;
            }
        }
    }
}

void USBConnection::communicationThread(void)
{
    while (keepRunning)
    {
        writeSerial((char*) DAC_COMMAND, sizeof(DAC_COMMAND));
        Sleep(500);

        char buffer[30] = { 0 };
        readSerial(buffer, 30);

        cout << buffer << endl;
        Sleep(500);
    }
}

还有标题:

#pragma once

#include <Windows.h>
#include <cstdbool>
#include <iostream>
#include <cstdio>
#include <thread>

#define DEVICE_BUFFER_SIZE  2048
#define BYTE_SIZE           8

#define READ_BUFFER_SIZE    30

#define DAC_COMMAND     "RAZF\r\n"

#define ERROR_WRITE     "ERROR: USB WRITE"
#define ERROR_READ      "ERROR: USB READ"

class USBConnection
{
public:
    USBConnection(char* comPort);
    void stop(void);
private:
    bool keepRunning;
    int baudrate;
    HANDLE serialHandle;
    std::thread* commThread;

    void purgeCommunication(void);
    void readSerial(char* buffer, DWORD len);
    void writeSerial(char* data, DWORD len);
    void communicationThread(void);
};

我监视了我的程序和原始软件的通信(使用 com0com 和在 github 上找到的 python 脚本),结果似乎没问题,但命令答案不同。

我尝试了一些疯狂的事情,希望复制我在官方软件的 dll 中找到的一些代码可以解决我的问题(但遗憾的是它什么也没做)。

我确定这不是硬件问题,因为在同一台计算机上运行的官方软件工作得很好。

我希望有人能找出问题所在:)。 我现在不知道我能做什么,请帮助我。

c++ winapi serial-port
© www.soinside.com 2019 - 2024. All rights reserved.