我的 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 中找到的一些代码可以解决我的问题(但遗憾的是它什么也没做)。
我确定这不是硬件问题,因为在同一台计算机上运行的官方软件工作得很好。
我希望有人能找出问题所在:)。 我现在不知道我能做什么,请帮助我。