重新设置代码格式

This commit is contained in:
2026-06-25 15:44:25 +08:00
parent 4669ba9c6b
commit d1f0f6e836
77 changed files with 9557 additions and 9416 deletions
+205 -228
View File
@@ -4,299 +4,276 @@
#include <thread>
#include <utility>
void serial_log(Log_Type& log_type, const std::string& MSG) {
Frequency_Limit_Multi lm;
bool ok = lm.test(std::to_string(Psc::get_error_code()));
if (!ok) return;
void serial_log(Log_Type &log_type, const std::string &MSG) {
Frequency_Limit_Multi lm;
bool ok = lm.test(std::to_string(Psc::get_error_code()));
if (!ok)
return;
std::ostringstream oss;
oss
<< Psc::get_error_message()
<< BaseLogger::to_log({true, spdlog::level::debug, "", log_type, MSG})
<< std::endl;
if(!Psc::serial::serial_logger)
{
std::cout << oss.str() << std::endl;
} else {
Psc::serial::serial_logger->error(" ", {}, oss.str());
}
std::ostringstream oss;
oss << Psc::get_error_message()
<< BaseLogger::to_log({true, spdlog::level::debug, "", log_type, MSG})
<< std::endl;
if (!Psc::serial::serial_logger) {
std::cout << oss.str() << std::endl;
} else {
Psc::serial::serial_logger->error(" ", {}, oss.str());
}
}
namespace Psc::serial {
BaseLogger* serial_logger = nullptr;
BaseLogger *serial_logger = nullptr;
bool Serial::open() {
fd = Psc::serial::open(serial_name);
if (fd == INVALID_HANDLE_VALUE) {
LOG_ERROR("Serial::open() 打开串口失败!");
return false;
}
serial_info = get_serial_info(fd);
set_binary_mode(serial_info);
std::ostringstream oss;
oss << "\n属性来源:\n";
if (buffer_byte_size == -1) {
buffer_byte_size = serial::get_buffer_byte_size(fd);
oss << "\t获取 buffer_byte_size: " << buffer_byte_size << std::endl;
} else {
serial::set_buffer_byte_size(fd, buffer_byte_size);
oss << "\t设置 buffer_byte_size: " << buffer_byte_size << std::endl;
}
if (baud_rate == -1) {
baud_rate = serial::get_baud_rate(serial_info);
oss << "\t获取 baud_rate: " << baud_rate << std::endl;
} else {
serial::set_baud_rate(serial_info, fd, baud_rate);
oss << "\t设置 baud_rate: " << baud_rate << std::endl;
}
if (dataBits == DataBits::UnknownDataBits) {
dataBits = serial::get_data_bits(serial_info);
oss << "\t获取 dataBits: " << Psc::to_string(dataBits) << std::endl;
} else {
serial::set_data_bits(serial_info, dataBits);
oss << "\t设置 dataBits: " << Psc::to_string(dataBits) << std::endl;
}
if (stopBits == StopBits::UnknownStopBits) {
stopBits = serial::get_stop_bits(serial_info);
oss << "\t获取 stopBits: " << Psc::to_string(stopBits) << std::endl;
} else {
serial::set_stop_bits(serial_info, stopBits);
oss << "\t设置 stopBits: " << Psc::to_string(stopBits) << std::endl;
}
if (parity == Parity::UnknownParity) {
parity = serial::get_parity(serial_info);
oss << "\t获取 parity: " << Psc::to_string(parity) << std::endl;
} else {
serial::set_parity(serial_info, parity);
oss << "\t设置 parity: " << Psc::to_string(parity) << std::endl;
}
if (flow_control == FlowControl::UnknownFlowControl) {
flow_control = serial::get_flow_control(serial_info);
oss << "\t获取 flow_control: " <<Psc::to_string(flow_control) << std::endl;
} else {
serial::set_flow_control(serial_info, flow_control);
oss << "\t设置 flow_control: " << Psc::to_string(flow_control) << std::endl;
}
// oss << "最终设置: " << to_string();
// std::string s = oss.str();
// std::cout << s << std::endl;
fd = Psc::serial::open(serial_name);
if (fd == INVALID_HANDLE_VALUE) {
LOG_ERROR("Serial::open() 打开串口失败!");
return false;
}
serial_info = get_serial_info(fd);
set_binary_mode(serial_info);
std::ostringstream oss;
oss << "\n属性来源:\n";
if (buffer_byte_size == -1) {
buffer_byte_size = serial::get_buffer_byte_size(fd);
oss << "\t获取 buffer_byte_size: " << buffer_byte_size << std::endl;
} else {
serial::set_buffer_byte_size(fd, buffer_byte_size);
oss << "\t设置 buffer_byte_size: " << buffer_byte_size << std::endl;
}
if (baud_rate == -1) {
baud_rate = serial::get_baud_rate(serial_info);
oss << "\t获取 baud_rate: " << baud_rate << std::endl;
} else {
serial::set_baud_rate(serial_info, fd, baud_rate);
oss << "\t设置 baud_rate: " << baud_rate << std::endl;
}
if (dataBits == DataBits::UnknownDataBits) {
dataBits = serial::get_data_bits(serial_info);
oss << "\t获取 dataBits: " << Psc::to_string(dataBits) << std::endl;
} else {
serial::set_data_bits(serial_info, dataBits);
oss << "\t设置 dataBits: " << Psc::to_string(dataBits) << std::endl;
}
if (stopBits == StopBits::UnknownStopBits) {
stopBits = serial::get_stop_bits(serial_info);
oss << "\t获取 stopBits: " << Psc::to_string(stopBits) << std::endl;
} else {
serial::set_stop_bits(serial_info, stopBits);
oss << "\t设置 stopBits: " << Psc::to_string(stopBits) << std::endl;
}
if (parity == Parity::UnknownParity) {
parity = serial::get_parity(serial_info);
oss << "\t获取 parity: " << Psc::to_string(parity) << std::endl;
} else {
serial::set_parity(serial_info, parity);
oss << "\t设置 parity: " << Psc::to_string(parity) << std::endl;
}
if (flow_control == FlowControl::UnknownFlowControl) {
flow_control = serial::get_flow_control(serial_info);
oss << "\t获取 flow_control: " << Psc::to_string(flow_control) << std::endl;
} else {
serial::set_flow_control(serial_info, flow_control);
oss << "\t设置 flow_control: " << Psc::to_string(flow_control) << std::endl;
}
// oss << "最终设置: " << to_string();
// std::string s = oss.str();
// std::cout << s << std::endl;
set_block(fd, false);
set_serial_info(fd, serial_info);
serial_logger->debug("", {}, oss.str());
return true;
set_block(fd, false);
set_serial_info(fd, serial_info);
serial_logger->debug("", {}, oss.str());
return true;
}
void Serial::close() {
serial::close(fd);
fd = INVALID_HANDLE_VALUE;
serial::close(fd);
fd = INVALID_HANDLE_VALUE;
}
int64_t Serial::write(const std::string& data) {
return serial::write(fd, data.c_str(), data.size());
}
std::string Serial::read(int64_t size) {
return read_all(fd);
}
int Serial::get_available_bytes() {
return serial::get_available_bytes(fd);
int64_t Serial::write(const std::string &data) {
return serial::write(fd, data.c_str(), data.size());
}
std::string Serial::read(int64_t size) { return read_all(fd); }
int Serial::get_available_bytes() { return serial::get_available_bytes(fd); }
std::string Serial::to_string() {
std::stringstream oss;
oss << "{" << std::endl;
oss << "\tfd:" << fd << std::endl;
oss << "\tbuffer_byte_size: " << serial::get_buffer_byte_size(fd) << std::endl;
oss << "\tbaud_rate: " << serial::get_baud_rate(serial_info) << std::endl;
oss << "\tdataBits: " << Psc::to_string(serial::get_data_bits(serial_info)) << std::endl;
oss << "\tstopBits: " << Psc::to_string(serial::get_stop_bits(serial_info)) << std::endl;
oss << "\tparity: " << Psc::to_string(serial::get_parity(serial_info)) << std::endl;
oss << "\tflow_control: " << Psc::to_string(serial::get_flow_control(serial_info)) << std::endl;
oss << "}" << std::endl;
return oss.str();
std::stringstream oss;
oss << "{" << std::endl;
oss << "\tfd:" << fd << std::endl;
oss << "\tbuffer_byte_size: " << serial::get_buffer_byte_size(fd)
<< std::endl;
oss << "\tbaud_rate: " << serial::get_baud_rate(serial_info) << std::endl;
oss << "\tdataBits: " << Psc::to_string(serial::get_data_bits(serial_info))
<< std::endl;
oss << "\tstopBits: " << Psc::to_string(serial::get_stop_bits(serial_info))
<< std::endl;
oss << "\tparity: " << Psc::to_string(serial::get_parity(serial_info))
<< std::endl;
oss << "\tflow_control: "
<< Psc::to_string(serial::get_flow_control(serial_info)) << std::endl;
oss << "}" << std::endl;
return oss.str();
}
void Serial::set_serial_name(const std::string& serial_name) {
this->serial_name = serial_name;
void Serial::set_serial_name(const std::string &serial_name) {
this->serial_name = serial_name;
}
std::string Serial::get_serial_name() {
return this->serial_name;
}
std::string Serial::get_serial_name() { return this->serial_name; }
void Serial::set_baud_rate(Baud_Rate_Type baud_rate) {
this->baud_rate = baud_rate;
if (fd != INVALID_HANDLE_VALUE) {
serial::set_baud_rate(serial_info, fd, baud_rate);
set_serial_info(fd, serial_info);
}
this->baud_rate = baud_rate;
if (fd != INVALID_HANDLE_VALUE) {
serial::set_baud_rate(serial_info, fd, baud_rate);
set_serial_info(fd, serial_info);
}
}
Baud_Rate_Type Serial::get_baud_rate() {
return baud_rate;
}
Baud_Rate_Type Serial::get_baud_rate() { return baud_rate; }
void Serial::set_data_bits(DataBits data_bits) {
this->dataBits = data_bits;
if (fd != INVALID_HANDLE_VALUE) {
serial::set_data_bits(serial_info, data_bits);
set_serial_info(fd, serial_info);
}
this->dataBits = data_bits;
if (fd != INVALID_HANDLE_VALUE) {
serial::set_data_bits(serial_info, data_bits);
set_serial_info(fd, serial_info);
}
}
DataBits Serial::get_data_bits() {
return dataBits;
}
DataBits Serial::get_data_bits() { return dataBits; }
void Serial::set_stop_bits(StopBits stop_bits) {
this->stopBits = stop_bits;
if (fd != INVALID_HANDLE_VALUE) {
serial::set_stop_bits(serial_info, stop_bits);
set_serial_info(fd, serial_info);
}
this->stopBits = stop_bits;
if (fd != INVALID_HANDLE_VALUE) {
serial::set_stop_bits(serial_info, stop_bits);
set_serial_info(fd, serial_info);
}
}
StopBits Serial::get_stop_bits() {
return stopBits;
}
StopBits Serial::get_stop_bits() { return stopBits; }
void Serial::set_parity(Parity parity) {
this->parity = parity;
if (fd != INVALID_HANDLE_VALUE) {
serial::set_parity(serial_info, parity);
set_serial_info(fd, serial_info);
}
this->parity = parity;
if (fd != INVALID_HANDLE_VALUE) {
serial::set_parity(serial_info, parity);
set_serial_info(fd, serial_info);
}
}
Parity Serial::get_parity() {
return parity;
}
Parity Serial::get_parity() { return parity; }
void Serial::set_flow_control(FlowControl flow_control) {
this->flow_control = flow_control;
if (fd != INVALID_HANDLE_VALUE) {
serial::set_flow_control(serial_info, flow_control);
set_serial_info(fd, serial_info);
}
this->flow_control = flow_control;
if (fd != INVALID_HANDLE_VALUE) {
serial::set_flow_control(serial_info, flow_control);
set_serial_info(fd, serial_info);
}
}
FlowControl Serial::get_flow_control() {
return flow_control;
}
FlowControl Serial::get_flow_control() { return flow_control; }
void Serial::set_buffer_byte_size(int byte_size) {
this->buffer_byte_size = byte_size;
if (fd != INVALID_HANDLE_VALUE) {
serial::set_buffer_byte_size(fd, byte_size);
}
}
int Serial::get_buffer_byte_size() {
return buffer_byte_size;
this->buffer_byte_size = byte_size;
if (fd != INVALID_HANDLE_VALUE) {
serial::set_buffer_byte_size(fd, byte_size);
}
}
int Serial::get_buffer_byte_size() { return buffer_byte_size; }
std::string read_block_all(Serial_FD fd, int64_t chunkSize) {
std::string result;
// 使用 vector 分配一个缓冲区
std::vector<char> buffer(static_cast<size_t>(chunkSize));
while (true)
{
int64_t bytesRead = read_data(fd, buffer.data(), chunkSize);
// std::cout << "bytesRead " << bytesRead;
if (bytesRead <= 0)
{
// 出错或者没有读取到数据时退出循环
break;
}
// 累积读取的数据
result.append(buffer.data(), static_cast<size_t>(bytesRead));
// 如果本次读取的数据不足 chunkSize,通常认为已经没有更多数据
if (bytesRead <= chunkSize)
{
break;
}
std::string result;
// 使用 vector 分配一个缓冲区
std::vector<char> buffer(static_cast<size_t>(chunkSize));
while (true) {
int64_t bytesRead = read_data(fd, buffer.data(), chunkSize);
// std::cout << "bytesRead " << bytesRead;
if (bytesRead <= 0) {
// 出错或者没有读取到数据时退出循环
break;
}
return result;
// 累积读取的数据
result.append(buffer.data(), static_cast<size_t>(bytesRead));
// 如果本次读取的数据不足 chunkSize,通常认为已经没有更多数据
if (bytesRead <= chunkSize) {
break;
}
}
return result;
}
std::string read_all(Serial_FD fd) {
int size = get_available_bytes(fd);
if (size == 0) return "";
auto ret = read_block_all(fd, 1024 * 4);
return ret;
int size = get_available_bytes(fd);
if (size == 0)
return "";
auto ret = read_block_all(fd, 1024 * 4);
return ret;
}
bool noblock_error() {
#ifdef _WIN32
DWORD code = GetLastError();
return code == ERROR_IO_PENDING || code == ERROR_NO_SYSTEM_RESOURCES;
DWORD code = GetLastError();
return code == ERROR_IO_PENDING || code == ERROR_NO_SYSTEM_RESOURCES;
#elif defined(__linux__)
return errno == EAGAIN || errno == EWOULDBLOCK;
return errno == EAGAIN || errno == EWOULDBLOCK;
#else
return false;
return false;
#endif
}
int64_t write_all(Serial_FD fd, const std::string& data, int64_t chunkSize,
int64_t milliseconds, int64_t retry_count) {
int64_t total_written = 0;
int64_t data_size = static_cast<int64_t>(data.size());
int64_t write_all(Serial_FD fd, const std::string &data, int64_t chunkSize,
int64_t milliseconds, int64_t retry_count) {
int64_t total_written = 0;
int64_t data_size = static_cast<int64_t>(data.size());
while (total_written < data_size) {
int64_t this_chunk = std::min(chunkSize, data_size - total_written);
int64_t cur_written = 0;
int64_t retry_left = retry_count;
while (total_written < data_size) {
int64_t this_chunk = std::min(chunkSize, data_size - total_written);
int64_t cur_written = 0;
int64_t retry_left = retry_count;
while (cur_written < this_chunk) {
int64_t to_write = this_chunk - cur_written;
int64_t written = serial::write(fd, data.data() + total_written + cur_written, to_write);
if (written < 0) {
// 写入错误,返回 -1
LOG_ERROR(VAR_STR_2(fd, written))
return -1;
while (cur_written < this_chunk) {
int64_t to_write = this_chunk - cur_written;
int64_t written = serial::write(
fd, data.data() + total_written + cur_written, to_write);
if (written < 0) {
// 写入错误,返回 -1
LOG_ERROR(VAR_STR_2(fd, written))
return -1;
}
if (written > 0) {
cur_written += written;
retry_left = retry_count; // 成功写入一次后,重置 retry
} else if (written == -1) {
if (noblock_error()) {
// 非阻塞暂时无法写入
if (retry_count != -1) {
if (--retry_left <= 0) {
LOG_ERROR("Retry limit reached");
return total_written;
}
if (written > 0) {
cur_written += written;
retry_left = retry_count; // 成功写入一次后,重置 retry
} else if (written == -1) {
if (noblock_error()) {
// 非阻塞暂时无法写入
if (retry_count != -1) {
if (--retry_left <= 0) {
LOG_ERROR("Retry limit reached");
return total_written;
}
}
} else {
LOG_ERROR("write failed");
return -1;
}
} else if (written == 0) {
// 不应该发生,write 返回 0 通常表示未写任何数据
LOG_ERROR("write returned 0 unexpectedly");
return -1;
}
if (cur_written == this_chunk) break;
if (milliseconds > 0) {
std::this_thread::sleep_for(std::chrono::milliseconds(milliseconds));
}
}
} else {
LOG_ERROR("write failed");
return -1;
}
} else if (written == 0) {
// 不应该发生,write 返回 0 通常表示未写任何数据
LOG_ERROR("write returned 0 unexpectedly");
return -1;
}
if (cur_written == this_chunk)
break;
if (milliseconds > 0) {
total_written += cur_written;
std::this_thread::sleep_for(std::chrono::milliseconds(milliseconds));
}
}
return total_written;
total_written += cur_written;
}
return total_written;
}
}
} // namespace Psc::serial
+126 -120
View File
@@ -1,18 +1,18 @@
#pragma once
#include <cstdint>
#include <string>
#include <cstring>
#include <functional>
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
#include <functional>
// #define USE_TERMIOS2
//#define USE_TERMIOS
// #define USE_TERMIOS
// 这个不好使
//#define USE_SERIAL_STRUCT
#if !defined(USE_TERMIOS2) && !defined(USE_TERMIOS) && !defined(USE_SERIAL_STRUCT)
// #define USE_SERIAL_STRUCT
#if !defined(USE_TERMIOS2) && !defined(USE_TERMIOS) && \
!defined(USE_SERIAL_STRUCT)
#define USE_TERMIOS
#endif
#ifdef _WIN32
@@ -21,139 +21,145 @@ using Serial_Settings = DCB;
using Serial_FD = HANDLE;
using Baud_Rate_Type = int;
#else
#include <sys/ioctl.h>
#include <fcntl.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <unistd.h>
#if defined(USE_TERMIOS)
#include <termios.h>
#include <linux/serial.h>
using Serial_Settings = termios;
#include <linux/serial.h>
#include <termios.h>
using Serial_Settings = termios;
#elif defined(USE_TERMIOS2)
//#include <asm-generic/termios.h"
#include <asm/termbits.h>
#include <asm/ioctls.h>
using Serial_Settings = termios2;
// #include <asm-generic/termios.h"
#include <asm/ioctls.h>
#include <asm/termbits.h>
using Serial_Settings = termios2;
#elif defined(USE_SERIAL_STRUCT)
#include <linux/serial.h>
#include <asm-generic/termbits.h>
using Serial_Settings = serial_struct;
#include <asm-generic/termbits.h>
#include <linux/serial.h>
using Serial_Settings = serial_struct;
#endif
using Baud_Rate_Type = unsigned int;
using Serial_FD = int;
using Baud_Rate_Type = unsigned int;
using Serial_FD = int;
#ifndef INVALID_HANDLE_VALUE
#define INVALID_HANDLE_VALUE -1
#define INVALID_HANDLE_VALUE -1
#endif
#endif
#include "../system/export.h"
class BaseLogger;
namespace Psc::serial {
extern BaseLogger* serial_logger;
void set_buffer_byte_size(Serial_FD fd, int byte_size);
int get_buffer_byte_size(Serial_FD fd);
void set_binary_mode(Serial_Settings& serial_info);
Serial_FD open(const std::string& port_name);
void close(Serial_FD fd);
void set_block(Serial_FD fd, bool block);
Serial_Settings get_serial_info(Serial_FD fd);
void reset(Serial_Settings& serial_info);
void set_serial_info(Serial_FD fd, Serial_Settings serial_info);
int get_available_bytes(Serial_FD fd);
int get_written_bytes(Serial_FD fd);
// windows下是阻塞的 怎么设置都是阻塞的
int64_t read_data(Serial_FD fd, char* data, int64_t maxSize);
// 非阻塞的,windows下先获取可读的字符在读取
std::string read_all(Serial_FD fd);
std::string read_block_all(Serial_FD fd, int64_t chunkSize);
int64_t write(Serial_FD fd, const char* data, int64_t size);
extern BaseLogger *serial_logger;
void set_buffer_byte_size(Serial_FD fd, int byte_size);
int get_buffer_byte_size(Serial_FD fd);
void set_binary_mode(Serial_Settings &serial_info);
Serial_FD open(const std::string &port_name);
void close(Serial_FD fd);
void set_block(Serial_FD fd, bool block);
Serial_Settings get_serial_info(Serial_FD fd);
void reset(Serial_Settings &serial_info);
void set_serial_info(Serial_FD fd, Serial_Settings serial_info);
int get_available_bytes(Serial_FD fd);
int get_written_bytes(Serial_FD fd);
// windows下是阻塞的 怎么设置都是阻塞的
int64_t read_data(Serial_FD fd, char *data, int64_t maxSize);
// 非阻塞的,windows下先获取可读的字符在读取
std::string read_all(Serial_FD fd);
std::string read_block_all(Serial_FD fd, int64_t chunkSize);
int64_t write(Serial_FD fd, const char *data, int64_t size);
// milliseconds == 0 代表非阻塞 最快直接返回
int64_t write_all(Serial_FD fd, const std::string& data, int64_t chunkSize, int64_t milliseconds, int64_t retry_count);
// milliseconds == 0 代表非阻塞 最快直接返回
int64_t write_all(Serial_FD fd, const std::string &data, int64_t chunkSize,
int64_t milliseconds, int64_t retry_count);
inline int64_t write_all_noblock(Serial_FD fd, const std::string& data, int64_t chunkSize) {
return write_all(fd, data, chunkSize, 0, 0);
}
inline int64_t write_all_block(Serial_FD fd, const std::string& data, int64_t chunkSize) {
return write_all(fd, data, chunkSize, 1, -1);
}
void set_baud_rate(Serial_Settings& serial_info, Serial_FD fd, Baud_Rate_Type baud);
Baud_Rate_Type get_baud_rate(Serial_Settings& serial_info);
std::string get_serial_info_str(std::string serial_name);
inline int64_t write_all_noblock(Serial_FD fd, const std::string &data,
int64_t chunkSize) {
return write_all(fd, data, chunkSize, 0, 0);
}
inline int64_t write_all_block(Serial_FD fd, const std::string &data,
int64_t chunkSize) {
return write_all(fd, data, chunkSize, 1, -1);
}
void set_baud_rate(Serial_Settings &serial_info, Serial_FD fd,
Baud_Rate_Type baud);
Baud_Rate_Type get_baud_rate(Serial_Settings &serial_info);
std::string get_serial_info_str(std::string serial_name);
enum class DataBits {
Data5 = 5,
Data6 = 6,
Data7 = 7,
Data8 = 8,
UnknownDataBits = -1
};
enum class DataBits {
Data5 = 5,
Data6 = 6,
Data7 = 7,
Data8 = 8,
UnknownDataBits = -1
};
void set_data_bits(Serial_Settings& serial_info, DataBits data_bits);
DataBits get_data_bits(Serial_Settings& serial_info);
void set_data_bits(Serial_Settings &serial_info, DataBits data_bits);
DataBits get_data_bits(Serial_Settings &serial_info);
enum class StopBits {
OneStop = 1,
OneAndHalfStop = 3,
TwoStop = 2,
UnknownStopBits = -1
};
enum class StopBits {
OneStop = 1,
OneAndHalfStop = 3,
TwoStop = 2,
UnknownStopBits = -1
};
void set_stop_bits(Serial_Settings& serial_info, StopBits stop_bits);
StopBits get_stop_bits(Serial_Settings& serial_info);
void set_stop_bits(Serial_Settings &serial_info, StopBits stop_bits);
StopBits get_stop_bits(Serial_Settings &serial_info);
enum class Parity {
NoParity = 0,
EvenParity = 2,
OddParity = 3,
SpaceParity = 4,
MarkParity = 5,
UnknownParity = -1
};
enum class Parity {
NoParity = 0,
EvenParity = 2,
OddParity = 3,
SpaceParity = 4,
MarkParity = 5,
UnknownParity = -1
};
void set_parity(Serial_Settings& serial_info, Parity parity);
Parity get_parity(Serial_Settings& serial_info);
void set_parity(Serial_Settings &serial_info, Parity parity);
Parity get_parity(Serial_Settings &serial_info);
enum class FlowControl {
NoFlowControl,
HardwareControl,
SoftwareControl,
UnknownFlowControl = -1
};
enum class FlowControl {
NoFlowControl,
HardwareControl,
SoftwareControl,
UnknownFlowControl = -1
};
void set_flow_control(Serial_Settings& serial_info, FlowControl flow_control);
FlowControl get_flow_control(Serial_Settings& serial_info);
class Serial {
public:
bool open();
void close();
int64_t write(const std::string& data);
std::string read(int64_t size = -1);
int get_available_bytes();
protected:
Baud_Rate_Type baud_rate = -1;
DataBits dataBits = DataBits::UnknownDataBits;
StopBits stopBits = StopBits::UnknownStopBits;
Parity parity = Parity::UnknownParity;
FlowControl flow_control = FlowControl::UnknownFlowControl;
Serial_FD fd = INVALID_HANDLE_VALUE;
Serial_Settings serial_info{};
std::string serial_name;
int buffer_byte_size = -1;
public:
std::string to_string();
void set_serial_name(const std::string& serial_name);
std::string get_serial_name();
void set_baud_rate(Baud_Rate_Type baud_rate);
Baud_Rate_Type get_baud_rate();
void set_data_bits(DataBits data_bits);
DataBits get_data_bits();
void set_stop_bits(StopBits stop_bits);
StopBits get_stop_bits();
void set_parity(Parity parity);
Parity get_parity();
void set_flow_control(FlowControl flow_control);
FlowControl get_flow_control();
void set_buffer_byte_size(int byte_size);
int get_buffer_byte_size();
};
void set_flow_control(Serial_Settings &serial_info, FlowControl flow_control);
FlowControl get_flow_control(Serial_Settings &serial_info);
class Serial {
public:
bool open();
void close();
int64_t write(const std::string &data);
std::string read(int64_t size = -1);
int get_available_bytes();
protected:
Baud_Rate_Type baud_rate = -1;
DataBits dataBits = DataBits::UnknownDataBits;
StopBits stopBits = StopBits::UnknownStopBits;
Parity parity = Parity::UnknownParity;
FlowControl flow_control = FlowControl::UnknownFlowControl;
Serial_FD fd = INVALID_HANDLE_VALUE;
Serial_Settings serial_info{};
std::string serial_name;
int buffer_byte_size = -1;
public:
std::string to_string();
void set_serial_name(const std::string &serial_name);
std::string get_serial_name();
void set_baud_rate(Baud_Rate_Type baud_rate);
Baud_Rate_Type get_baud_rate();
void set_data_bits(DataBits data_bits);
DataBits get_data_bits();
void set_stop_bits(StopBits stop_bits);
StopBits get_stop_bits();
void set_parity(Parity parity);
Parity get_parity();
void set_flow_control(FlowControl flow_control);
FlowControl get_flow_control();
void set_buffer_byte_size(int byte_size);
int get_buffer_byte_size();
};
}
+128 -119
View File
@@ -15,152 +15,161 @@ namespace Psc::serial {
class Serial_Coro : public Serial {
public:
bool open()
{
if (port_ && port_->is_open()) {
return true;
}
port_ = std::make_unique<asio::serial_port>(io_context_);
asio::error_code ec;
port_->open(normalize_port_name(serial_name), ec);
if (ec) {
return false;
}
apply_options(ec);
if (ec) {
close();
return false;
}
serial::set_block(port_->native_handle(), false);
return true;
bool open() {
if (port_ && port_->is_open()) {
return true;
}
void close()
{
if (!port_) {
return;
}
asio::error_code ec;
port_->cancel(ec);
port_->close(ec);
port_.reset();
io_context_.restart();
port_ = std::make_unique<asio::serial_port>(io_context_);
asio::error_code ec;
port_->open(normalize_port_name(serial_name), ec);
if (ec) {
return false;
}
[[nodiscard]] concurrencpp::result<void> tick_coro()
{
io_context_.poll();
co_return;
apply_options(ec);
if (ec) {
close();
return false;
}
[[nodiscard]] concurrencpp::result<std::string> read_coro(std::size_t max_size = 16 * 1024)
{
co_await tick_coro();
if (!port_ || !port_->is_open()) {
co_return "";
}
serial::set_block(port_->native_handle(), false);
auto available = serial::get_available_bytes(port_->native_handle());
if (available <= 0) {
co_return "";
}
return true;
}
auto data = serial::read_all(port_->native_handle());
if (data.size() > max_size) {
data.resize(max_size);
}
co_return data;
void close() {
if (!port_) {
return;
}
[[nodiscard]] concurrencpp::result<std::size_t> write_coro(std::string data)
{
co_await tick_coro();
if (!port_ || !port_->is_open() || data.empty()) {
co_return 0;
}
asio::error_code ec;
port_->cancel(ec);
port_->close(ec);
port_.reset();
io_context_.restart();
}
asio::error_code ec;
auto size = asio::write(*port_, asio::buffer(data), ec);
if (ec) {
co_return 0;
}
[[nodiscard]] concurrencpp::result<void> tick_coro() {
io_context_.poll();
co_return;
}
co_return size;
[[nodiscard]] concurrencpp::result<std::string>
read_coro(std::size_t max_size = 16 * 1024) {
co_await tick_coro();
if (!port_ || !port_->is_open()) {
co_return "";
}
std::string read(int64_t size = -1)
{
auto max_size = size > 0 ? static_cast<std::size_t>(size) : static_cast<std::size_t>(16 * 1024);
return (read_coro(max_size)).get();
auto available = serial::get_available_bytes(port_->native_handle());
if (available <= 0) {
co_return "";
}
int64_t write(const std::string& data)
{
return static_cast<int64_t>(write_coro(data).get());
auto data = serial::read_all(port_->native_handle());
if (data.size() > max_size) {
data.resize(max_size);
}
co_return data;
}
[[nodiscard]] concurrencpp::result<std::size_t> write_coro(std::string data) {
co_await tick_coro();
if (!port_ || !port_->is_open() || data.empty()) {
co_return 0;
}
int get_available_bytes()
{
if (!port_ || !port_->is_open()) {
return 0;
}
return serial::get_available_bytes(port_->native_handle());
asio::error_code ec;
auto size = asio::write(*port_, asio::buffer(data), ec);
if (ec) {
co_return 0;
}
co_return size;
}
std::string read(int64_t size = -1) {
auto max_size = size > 0 ? static_cast<std::size_t>(size)
: static_cast<std::size_t>(16 * 1024);
return (read_coro(max_size)).get();
}
int64_t write(const std::string &data) {
return static_cast<int64_t>(write_coro(data).get());
}
int get_available_bytes() {
if (!port_ || !port_->is_open()) {
return 0;
}
return serial::get_available_bytes(port_->native_handle());
}
private:
static std::string normalize_port_name(std::string port_name)
{
static std::string normalize_port_name(std::string port_name) {
#ifdef _WIN32
if (port_name.rfind("\\\\.\\", 0) != 0) {
port_name = "\\\\.\\" + port_name;
}
if (port_name.rfind("\\\\.\\", 0) != 0) {
port_name = "\\\\.\\" + port_name;
}
#endif
return port_name;
return port_name;
}
void apply_options(asio::error_code &ec) {
if (baud_rate != static_cast<Baud_Rate_Type>(-1)) {
port_->set_option(asio::serial_port_base::baud_rate(
static_cast<unsigned int>(baud_rate)),
ec);
if (ec)
return;
}
void apply_options(asio::error_code& ec)
{
if (baud_rate != static_cast<Baud_Rate_Type>(-1)) {
port_->set_option(asio::serial_port_base::baud_rate(static_cast<unsigned int>(baud_rate)), ec);
if (ec) return;
}
if (dataBits != DataBits::UnknownDataBits) {
port_->set_option(asio::serial_port_base::character_size(static_cast<unsigned int>(dataBits)), ec);
if (ec) return;
}
if (parity != Parity::UnknownParity) {
asio::serial_port_base::parity::type value = asio::serial_port_base::parity::none;
if (parity == Parity::EvenParity) value = asio::serial_port_base::parity::even;
if (parity == Parity::OddParity) value = asio::serial_port_base::parity::odd;
port_->set_option(asio::serial_port_base::parity(value), ec);
if (ec) return;
}
if (stopBits != StopBits::UnknownStopBits) {
asio::serial_port_base::stop_bits::type value = asio::serial_port_base::stop_bits::one;
if (stopBits == StopBits::OneAndHalfStop) value = asio::serial_port_base::stop_bits::onepointfive;
if (stopBits == StopBits::TwoStop) value = asio::serial_port_base::stop_bits::two;
port_->set_option(asio::serial_port_base::stop_bits(value), ec);
if (ec) return;
}
if (flow_control != FlowControl::UnknownFlowControl) {
asio::serial_port_base::flow_control::type value = asio::serial_port_base::flow_control::none;
if (flow_control == FlowControl::HardwareControl) value = asio::serial_port_base::flow_control::hardware;
if (flow_control == FlowControl::SoftwareControl) value = asio::serial_port_base::flow_control::software;
port_->set_option(asio::serial_port_base::flow_control(value), ec);
}
if (dataBits != DataBits::UnknownDataBits) {
port_->set_option(asio::serial_port_base::character_size(
static_cast<unsigned int>(dataBits)),
ec);
if (ec)
return;
}
asio::io_context io_context_;
std::unique_ptr<asio::serial_port> port_;
if (parity != Parity::UnknownParity) {
asio::serial_port_base::parity::type value =
asio::serial_port_base::parity::none;
if (parity == Parity::EvenParity)
value = asio::serial_port_base::parity::even;
if (parity == Parity::OddParity)
value = asio::serial_port_base::parity::odd;
port_->set_option(asio::serial_port_base::parity(value), ec);
if (ec)
return;
}
if (stopBits != StopBits::UnknownStopBits) {
asio::serial_port_base::stop_bits::type value =
asio::serial_port_base::stop_bits::one;
if (stopBits == StopBits::OneAndHalfStop)
value = asio::serial_port_base::stop_bits::onepointfive;
if (stopBits == StopBits::TwoStop)
value = asio::serial_port_base::stop_bits::two;
port_->set_option(asio::serial_port_base::stop_bits(value), ec);
if (ec)
return;
}
if (flow_control != FlowControl::UnknownFlowControl) {
asio::serial_port_base::flow_control::type value =
asio::serial_port_base::flow_control::none;
if (flow_control == FlowControl::HardwareControl)
value = asio::serial_port_base::flow_control::hardware;
if (flow_control == FlowControl::SoftwareControl)
value = asio::serial_port_base::flow_control::software;
port_->set_option(asio::serial_port_base::flow_control(value), ec);
}
}
asio::io_context io_context_;
std::unique_ptr<asio::serial_port> port_;
};
} // namespace Psc::serial
+4 -7
View File
@@ -3,11 +3,8 @@
#include "../../Core/spdlog/export.h"
#include "Serial.h"
void serial_log(Log_Type &log_type, const std::string &MSG);
void serial_log(Log_Type& log_type, const std::string& MSG);
#define LOG_ERROR(MSG) static Log_Type log_type({}, {{"POS", LOG_POS}});\
serial_log(log_type, MSG);
#define LOG_ERROR(MSG) \
static Log_Type log_type({}, {{"POS", LOG_POS}}); \
serial_log(log_type, MSG);
+326 -323
View File
@@ -3,196 +3,191 @@
#include "Serial_p.h"
namespace Psc::serial {
void reset(Serial_Settings &serial_info) {
// 清空整个结构体
ZeroMemory(&serial_info, sizeof(DCB));
serial_info.DCBlength = sizeof(DCB);
void reset(Serial_Settings& serial_info) {
// 清空整个结构体
ZeroMemory(&serial_info, sizeof(DCB));
serial_info.DCBlength = sizeof(DCB);
// 设置默认参数(你可以根据需要修改)
serial_info.BaudRate = CBR_9600; // 默认波特率
serial_info.ByteSize = 8; // 8位数据位
serial_info.Parity = NOPARITY; // 无校验
serial_info.StopBits = ONESTOPBIT; // 1位停止位
serial_info.fBinary = TRUE; // 必须设为 TRUE
serial_info.fDtrControl = DTR_CONTROL_ENABLE;
serial_info.fRtsControl = RTS_CONTROL_ENABLE;
// 设置默认参数(你可以根据需要修改)
serial_info.BaudRate = CBR_9600; // 默认波特率
serial_info.ByteSize = 8; // 8位数据位
serial_info.Parity = NOPARITY; // 无校验
serial_info.StopBits = ONESTOPBIT; // 1位停止位
serial_info.fBinary = TRUE; // 必须设为 TRUE
serial_info.fDtrControl = DTR_CONTROL_ENABLE;
serial_info.fRtsControl = RTS_CONTROL_ENABLE;
}
void set_buffer_byte_size(HANDLE fd, int byte_size) {
if (fd == INVALID_HANDLE_VALUE) {
LOG_ERROR(VAR_STR_2(fd, byte_size) + "Invalid serial handle!")
}
// 设置输入缓冲区和输出缓冲区的大小
if (!SetupComm(fd, byte_size, byte_size)) {
LOG_ERROR(VAR_STR_2(fd, byte_size) + "Failed to set buffer size!")
}
// 清空缓冲区,防止遗留数据干扰
if (!PurgeComm(fd, PURGE_RXCLEAR | PURGE_TXCLEAR)) {
LOG_ERROR(VAR_STR_2(fd, byte_size) + "Failed to purge buffers!")
}
if (fd == INVALID_HANDLE_VALUE) {
LOG_ERROR(VAR_STR_2(fd, byte_size) + "Invalid serial handle!")
}
// 设置输入缓冲区和输出缓冲区的大小
if (!SetupComm(fd, byte_size, byte_size)) {
LOG_ERROR(VAR_STR_2(fd, byte_size) + "Failed to set buffer size!")
}
// 清空缓冲区,防止遗留数据干扰
if (!PurgeComm(fd, PURGE_RXCLEAR | PURGE_TXCLEAR)) {
LOG_ERROR(VAR_STR_2(fd, byte_size) + "Failed to purge buffers!")
}
}
int get_buffer_byte_size(HANDLE fd) {
COMMPROP commProp = {0};
if (GetCommProperties(fd, &commProp)) {
return commProp.dwCurrentRxQueue; // 或者返回 commProp.dwCurrentTxQueue
} else {
LOG_ERROR(VAR_STR_1(fd) + "Failed to get serial port properties.")
}
return 0;
COMMPROP commProp = {0};
if (GetCommProperties(fd, &commProp)) {
return commProp.dwCurrentRxQueue; // 或者返回 commProp.dwCurrentTxQueue
} else {
LOG_ERROR(VAR_STR_1(fd) + "Failed to get serial port properties.")
}
return 0;
}
void set_binary_mode(Serial_Settings& serial_info) {
//windows下默认就是
void set_binary_mode(Serial_Settings &serial_info) {
// windows下默认就是
}
HANDLE open(const std::string& port_name) {
HANDLE hSerial = CreateFile(("\\\\.\\" + port_name).c_str(),
GENERIC_READ | GENERIC_WRITE,
0, // No sharing
NULL, // Default security attributes
OPEN_EXISTING, // Open the existing port
0, // 0 : No overlapped I/O FILE_FLAG_OVERLAPPED是异步
NULL); // No template file
if (hSerial == INVALID_HANDLE_VALUE) {
LOG_ERROR(VAR_STR_1(port_name))
Psc::fail_fast();
return INVALID_HANDLE_VALUE;
}
HANDLE open(const std::string &port_name) {
HANDLE hSerial =
CreateFile(("\\\\.\\" + port_name).c_str(), GENERIC_READ | GENERIC_WRITE,
0, // No sharing
NULL, // Default security attributes
OPEN_EXISTING, // Open the existing port
0, // 0 : No overlapped I/O FILE_FLAG_OVERLAPPED是异步
NULL); // No template file
if (hSerial == INVALID_HANDLE_VALUE) {
LOG_ERROR(VAR_STR_1(port_name))
Psc::fail_fast();
return INVALID_HANDLE_VALUE;
}
return hSerial;
return hSerial;
}
//typedef struct _COMMTIMEOUTS {
// DWORD ReadIntervalTimeout; // 读间隔超时
// DWORD ReadTotalTimeoutMultiplier; // 读时间系数
// DWORD ReadTotalTimeoutConstant; // 读时间常量
// DWORD WriteTotalTimeoutMultiplier; // 写时间系数
// DWORD WriteTotalTimeoutConstant; // 写时间常量
//} COMMTIMEOUTS,*LPCOMMTIMEOUTS;
// 有两种超时:间隔超时和总超时。间隔超时是指在接收时两个字符之间的最大时延,总超时是指读写操作总共花费的最大时间。
// 写操作只支持总超时,而读操作两种超时均支持。
// 用COMMTIMEOUTS结构可以规定读/写操作的超时,该结构的定义为: COMMTIMEOUTS结构的成员都以毫秒为单位。总超时的计算公式是:
// 总超时=时间系数×要求读/写的字符数 + 时间常量// 
// 例如,如果要读入10个字符,那么读操作的总超时的计算公式为:
// 读总超时=ReadTotalTimeoutMultiplier×10 + ReadTotalTimeoutConstant
// 如果所有写超时参数均为0,那么就不使用写超时。如果ReadIntervalTimeout为0,那么就不使用读间隔超时,如果 ReadTotalTimeoutMultiplierReadTotalTimeoutConstant都为0
// 则不使用读总超时。
// 如果读间隔超时被设置成MAXDWORD并且两个读总超时为0,那么在读一次输入缓冲区中的内容后读操作就立即完成,而不管是否读入了要求的字符。
// 在用重叠方式读写串行口时,虽然ReadFile和WriteFile在完成操作以前就可能返回,但超时仍然是起作用的。在这种情况下,超时规定的是操作的完成时间,而不是ReadFile和WriteFile的返回时间
// typedef struct _COMMTIMEOUTS {
// DWORD ReadIntervalTimeout; // 读间隔超时
// DWORD ReadTotalTimeoutMultiplier; // 读时间系数
// DWORD ReadTotalTimeoutConstant; // 读时间常量
// DWORD WriteTotalTimeoutMultiplier; // 写时间系数
// DWORD WriteTotalTimeoutConstant; // 写时间常量
// } COMMTIMEOUTS,*LPCOMMTIMEOUTS;
// 有两种超时:间隔超时和总超时。间隔超时是指在接收时两个字符之间的最大时延,总超时是指读写操作总共花费的最大时间。
// 写操作只支持总超时,而读操作两种超时均支持。
// 用COMMTIMEOUTS结构可以规定读/写操作的超时,该结构的定义为:
// COMMTIMEOUTS结构的成员都以毫秒为单位。总超时的计算公式是:
// 总超时=时间系数×要求读/写的字符数 + 时间常量// 
// 例如,如果要读入10个字符,那么读操作的总超时的计算公式为:
// 读总超时=ReadTotalTimeoutMultiplier×10 + ReadTotalTimeoutConstant
// 如果所有写超时参数均为0,那么就不使用写超时。如果ReadIntervalTimeout为0,那么就不使用读间隔超时,如果
// ReadTotalTimeoutMultiplier和ReadTotalTimeoutConstant都为0
// 则不使用读总超时
// 如果读间隔超时被设置成MAXDWORD并且两个读总超时为0,那么在读一次输入缓冲区中的内容后读操作就立即完成,而不管是否读入了要求的字符。
// 在用重叠方式读写串行口时,虽然ReadFile和WriteFile在完成操作以前就可能返回,但超时仍然是起作用的。在这种情况下,超时规定的是操作的完成时间,而不是ReadFile和WriteFile的返回时间。
void set_block(HANDLE fd, bool block) {
// 获取当前串口的超时设置
COMMTIMEOUTS timeouts = {0};
if (!GetCommTimeouts(fd, &timeouts)) {
LOG_ERROR(VAR_STR_2(fd, block))
return;
}
// 根据 block 参数设置不同的超时行为
if (block) {
// 阻塞模式:没有超时
timeouts.ReadIntervalTimeout = 0;
timeouts.ReadTotalTimeoutConstant = 0;
timeouts.ReadTotalTimeoutMultiplier = 0;
timeouts.WriteTotalTimeoutConstant = 0;
timeouts.WriteTotalTimeoutMultiplier = 0;
} else {
// 非阻塞模式:设置适当的超时(例如 50 毫秒)
// timeouts.ReadIntervalTimeout = 50;
// timeouts.ReadTotalTimeoutConstant = 50;
// timeouts.ReadTotalTimeoutMultiplier = 10;
timeouts.WriteTotalTimeoutConstant = 50;
timeouts.WriteTotalTimeoutMultiplier = 10;
timeouts.ReadIntervalTimeout = MAXDWORD;
timeouts.ReadTotalTimeoutConstant = 0;
timeouts.ReadTotalTimeoutMultiplier = 0;
}
// 设置新的超时参数
if (!SetCommTimeouts(fd, &timeouts)) {
LOG_ERROR("")
}
// 获取当前串口的超时设置
COMMTIMEOUTS timeouts = {0};
if (!GetCommTimeouts(fd, &timeouts)) {
LOG_ERROR(VAR_STR_2(fd, block))
return;
}
// 根据 block 参数设置不同的超时行为
if (block) {
// 阻塞模式:没有超时
timeouts.ReadIntervalTimeout = 0;
timeouts.ReadTotalTimeoutConstant = 0;
timeouts.ReadTotalTimeoutMultiplier = 0;
timeouts.WriteTotalTimeoutConstant = 0;
timeouts.WriteTotalTimeoutMultiplier = 0;
} else {
// 非阻塞模式:设置适当的超时(例如 50 毫秒)
// timeouts.ReadIntervalTimeout = 50;
// timeouts.ReadTotalTimeoutConstant = 50;
// timeouts.ReadTotalTimeoutMultiplier = 10;
timeouts.WriteTotalTimeoutConstant = 50;
timeouts.WriteTotalTimeoutMultiplier = 10;
timeouts.ReadIntervalTimeout = MAXDWORD;
timeouts.ReadTotalTimeoutConstant = 0;
timeouts.ReadTotalTimeoutMultiplier = 0;
}
// 设置新的超时参数
if (!SetCommTimeouts(fd, &timeouts)) {
LOG_ERROR("")
}
}
void close(Serial_FD fd) {
if (fd != INVALID_HANDLE_VALUE) {
if (CloseHandle(fd)) {
if (serial_logger) serial_logger->debug("", {}, VAR_STR_1(fd) + " Serial port closed successfully.");
} else {
LOG_ERROR(VAR_STR_1(fd) + " Failed to close the serial port.")
}
if (fd != INVALID_HANDLE_VALUE) {
if (CloseHandle(fd)) {
if (serial_logger)
serial_logger->debug(
"", {}, VAR_STR_1(fd) + " Serial port closed successfully.");
} else {
LOG_ERROR(VAR_STR_1(fd))
LOG_ERROR(VAR_STR_1(fd) + " Failed to close the serial port.")
}
} else {
LOG_ERROR(VAR_STR_1(fd))
}
}
DCB get_serial_info(HANDLE fd) {
DCB dcbSerialParams = {0}; // 初始化 DCB 结构
// 获取串口的当前状态
if (!GetCommState(fd, &dcbSerialParams)) {
LOG_ERROR(VAR_STR_1(fd))
// 如果获取失败,可以返回一个默认的 DCB 结构(全为零)
return dcbSerialParams;
}
// 成功获取配置后返回 DCB 结构
DCB dcbSerialParams = {0}; // 初始化 DCB 结构
// 获取串口的当前状态
if (!GetCommState(fd, &dcbSerialParams)) {
LOG_ERROR(VAR_STR_1(fd))
// 如果获取失败,可以返回一个默认的 DCB 结构(全为零)
return dcbSerialParams;
}
// 成功获取配置后返回 DCB 结构
return dcbSerialParams;
}
void set_serial_info(HANDLE fd, DCB serial_info) {
// 设置串口配置
if (!SetCommState(fd, &serial_info)) {
// 如果设置失败,输出错误信息
LOG_ERROR(VAR_STR_1(fd))
}
// 设置串口配置
if (!SetCommState(fd, &serial_info)) {
// 如果设置失败,输出错误信息
LOG_ERROR(VAR_STR_1(fd))
}
}
int get_written_bytes(Serial_FD fd) {
COMSTAT comStat;
DWORD dwErrors;
COMSTAT comStat;
DWORD dwErrors;
// 获取串口通信状态
if (!ClearCommError(fd, &dwErrors, &comStat)) {
fprintf(stderr, "ClearCommError failed: %ld\n", GetLastError());
return -1;
}
// 返回发送缓冲区中的字节数
return comStat.cbOutQue;
// 获取串口通信状态
if (!ClearCommError(fd, &dwErrors, &comStat)) {
fprintf(stderr, "ClearCommError failed: %ld\n", GetLastError());
return -1;
}
// 返回发送缓冲区中的字节数
return comStat.cbOutQue;
}
int get_available_bytes(HANDLE fd) {
COMSTAT comStat;
DWORD dwErrors;
// 使用 ClearCommError 获取串口状态和接收队列中的字节数
if (!ClearCommError(fd, &dwErrors, &comStat)) {
LOG_ERROR(VAR_STR_1(fd))
return -1; // 出现错误时返回 -1
}
// 返回接收队列中的字节数
return comStat.cbInQue;
COMSTAT comStat;
DWORD dwErrors;
// 使用 ClearCommError 获取串口状态和接收队列中的字节数
if (!ClearCommError(fd, &dwErrors, &comStat)) {
LOG_ERROR(VAR_STR_1(fd))
return -1; // 出现错误时返回 -1
}
// 返回接收队列中的字节数
return comStat.cbInQue;
}
int64_t read_data(HANDLE fd, char* data, int64_t maxSize) {
DWORD bytesRead = 0;
if (!ReadFile(fd, data, maxSize, &bytesRead, NULL)) {
return -1;
}
return bytesRead;
int64_t read_data(HANDLE fd, char *data, int64_t maxSize) {
DWORD bytesRead = 0;
if (!ReadFile(fd, data, maxSize, &bytesRead, NULL)) {
return -1;
}
return bytesRead;
}
// int64_t read_data(Serial_FD fd, char* data, int64_t maxSize) {
// OVERLAPPED overlapped = {};
// DWORD bytesRead = 0;
// if (ReadFile(fd, data, maxSize, &bytesRead, &overlapped) || GetLastError() == ERROR_IO_PENDING) {
// if (ReadFile(fd, data, maxSize, &bytesRead, &overlapped) ||
// GetLastError() == ERROR_IO_PENDING) {
// if (GetOverlappedResult(fd, &overlapped, &bytesRead, TRUE)) {
// return bytesRead;
// }
@@ -200,141 +195,144 @@ int64_t read_data(HANDLE fd, char* data, int64_t maxSize) {
// return 0; // 如果没有数据可以读取,直接返回
// }
int64_t write(HANDLE fd, const char *data, int64_t maxSize,
bool nonBlocking = false) {
DWORD bytesWritten = 0;
OVERLAPPED overlapped = {0};
int64_t write(HANDLE fd, const char* data, int64_t maxSize, bool nonBlocking = false) {
DWORD bytesWritten = 0;
OVERLAPPED overlapped = {0};
if (nonBlocking) {
overlapped.hEvent = CreateEvent(nullptr, TRUE, FALSE, nullptr);
if (!overlapped.hEvent) {
std::cerr << "创建事件失败" << std::endl;
return -1;
}
if (nonBlocking) {
overlapped.hEvent = CreateEvent(nullptr, TRUE, FALSE, nullptr);
if (!overlapped.hEvent) {
std::cerr << "创建事件失败" << std::endl;
return -1;
}
}
BOOL success = WriteFile(
fd,
data,
static_cast<DWORD>(maxSize),
&bytesWritten,
nonBlocking ? &overlapped : nullptr
);
BOOL success = WriteFile(fd, data, static_cast<DWORD>(maxSize), &bytesWritten,
nonBlocking ? &overlapped : nullptr);
if (!success) {
DWORD error = GetLastError();
if (error == ERROR_IO_PENDING) {
if (nonBlocking) {
CloseHandle(overlapped.hEvent);
return 0; // 非阻塞模式下返回0表示操作挂起
}
return -1;
} else if (error == ERROR_TIMEOUT) {
CloseHandle(overlapped.hEvent);
return 0;
} else {
CloseHandle(overlapped.hEvent);
std::cerr << "写入错误, 错误代码: " << error << std::endl;
return -1;
}
}
if (nonBlocking) {
if (!success) {
DWORD error = GetLastError();
if (error == ERROR_IO_PENDING) {
if (nonBlocking) {
CloseHandle(overlapped.hEvent);
return 0; // 非阻塞模式下返回0表示操作挂起
}
return -1;
} else if (error == ERROR_TIMEOUT) {
CloseHandle(overlapped.hEvent);
return 0;
} else {
CloseHandle(overlapped.hEvent);
std::cerr << "写入错误, 错误代码: " << error << std::endl;
return -1;
}
}
return bytesWritten;
if (nonBlocking) {
CloseHandle(overlapped.hEvent);
}
return bytesWritten;
}
int64_t write(HANDLE fd, const char* data, int64_t size) {
DWORD written;
BOOL success = WriteFile(
fd,
data,
static_cast<DWORD>(size),
&written,
nullptr
);
if (!success)
{
LOG_ERROR("");
return -1;
}
if (written != size)
{
LOG_ERROR("");
}
return written;
int64_t write(HANDLE fd, const char *data, int64_t size) {
DWORD written;
BOOL success =
WriteFile(fd, data, static_cast<DWORD>(size), &written, nullptr);
if (!success) {
LOG_ERROR("");
return -1;
}
if (written != size) {
LOG_ERROR("");
}
return written;
}
void set_baud_rate(DCB& serial_info, Serial_FD fd, int baud) {
// 设置串口波特率
serial_info.BaudRate = baud;
void set_baud_rate(DCB &serial_info, Serial_FD fd, int baud) {
// 设置串口波特率
serial_info.BaudRate = baud;
}
int get_baud_rate(DCB& serial_info) {
return serial_info.BaudRate;
int get_baud_rate(DCB &serial_info) { return serial_info.BaudRate; }
void set_data_bits(DCB &serial_info, DataBits data_bits) {
serial_info.ByteSize = static_cast<BYTE>(data_bits);
}
void set_data_bits(DCB& serial_info, DataBits data_bits) {
serial_info.ByteSize = static_cast<BYTE>(data_bits);
DataBits get_data_bits(DCB &serial_info) {
return static_cast<DataBits>(serial_info.ByteSize);
}
DataBits get_data_bits(DCB& serial_info) {
return static_cast<DataBits>(serial_info.ByteSize);
void set_stop_bits(DCB &serial_info, StopBits stop_bits) {
switch (stop_bits) {
case StopBits::OneStop:
serial_info.StopBits = ONESTOPBIT;
break;
case StopBits::OneAndHalfStop:
serial_info.StopBits = ONE5STOPBITS;
break;
case StopBits::TwoStop:
serial_info.StopBits = TWOSTOPBITS;
break;
default:
std::cerr << "Invalid stop bits value." << std::endl;
return;
}
}
void set_stop_bits(DCB& serial_info, StopBits stop_bits) {
switch (stop_bits) {
case StopBits::OneStop: serial_info.StopBits = ONESTOPBIT;
break;
case StopBits::OneAndHalfStop: serial_info.StopBits = ONE5STOPBITS;
break;
case StopBits::TwoStop: serial_info.StopBits = TWOSTOPBITS;
break;
default: std::cerr << "Invalid stop bits value." << std::endl;
return;
}
StopBits get_stop_bits(DCB &serial_info) {
switch (serial_info.StopBits) {
case ONESTOPBIT:
return StopBits::OneStop;
case ONE5STOPBITS:
return StopBits::OneAndHalfStop;
case TWOSTOPBITS:
return StopBits::TwoStop;
default:
return StopBits::UnknownStopBits;
}
}
StopBits get_stop_bits(DCB& serial_info) {
switch (serial_info.StopBits) {
case ONESTOPBIT: return StopBits::OneStop;
case ONE5STOPBITS: return StopBits::OneAndHalfStop;
case TWOSTOPBITS: return StopBits::TwoStop;
default: return StopBits::UnknownStopBits;
}
void set_parity(DCB &serial_info, Parity parity) {
switch (parity) {
case Parity::NoParity:
serial_info.Parity = NOPARITY;
break;
case Parity::EvenParity:
serial_info.Parity = EVENPARITY;
break;
case Parity::OddParity:
serial_info.Parity = ODDPARITY;
break;
case Parity::SpaceParity:
serial_info.Parity = SPACEPARITY;
break;
case Parity::MarkParity:
serial_info.Parity = MARKPARITY;
break;
default:
std::cerr << "Invalid parity value." << std::endl;
return;
}
}
void set_parity(DCB& serial_info, Parity parity) {
switch (parity) {
case Parity::NoParity: serial_info.Parity = NOPARITY;
break;
case Parity::EvenParity: serial_info.Parity = EVENPARITY;
break;
case Parity::OddParity: serial_info.Parity = ODDPARITY;
break;
case Parity::SpaceParity: serial_info.Parity = SPACEPARITY;
break;
case Parity::MarkParity: serial_info.Parity = MARKPARITY;
break;
default: std::cerr << "Invalid parity value." << std::endl;
return;
}
}
Parity get_parity(DCB& serial_info) {
switch (serial_info.Parity) {
case NOPARITY: return Parity::NoParity;
case EVENPARITY: return Parity::EvenParity;
case ODDPARITY: return Parity::OddParity;
case SPACEPARITY: return Parity::SpaceParity;
case MARKPARITY: return Parity::MarkParity;
default: return Parity::UnknownParity;
}
Parity get_parity(DCB &serial_info) {
switch (serial_info.Parity) {
case NOPARITY:
return Parity::NoParity;
case EVENPARITY:
return Parity::EvenParity;
case ODDPARITY:
return Parity::OddParity;
case SPACEPARITY:
return Parity::SpaceParity;
case MARKPARITY:
return Parity::MarkParity;
default:
return Parity::UnknownParity;
}
}
// 设置流控制
@@ -344,63 +342,64 @@ Parity get_parity(DCB& serial_info) {
// 初始化阶段 用于准备就绪信号
// DSR Data Set Ready)接收端
// DTR Data Terminal Ready)发送端
// fInX = TRUE:启用接收端的软件流控,接收端在接收到 XOFF 时暂停接收数据,在接收到 XON 时恢复接收。
// fOutX = TRUE:启用发送端的软件流控,发送端会根据接收端发送的 XON/XOFF 指令控制数据发送
void set_flow_control(DCB& serial_info, FlowControl flow_control) {
switch (flow_control) {
case FlowControl::NoFlowControl:
// 关闭所有流控制
serial_info.fOutxCtsFlow = FALSE;
serial_info.fOutxDsrFlow = FALSE;
serial_info.fInX = FALSE;
serial_info.fOutX = FALSE;
serial_info.fDtrControl = DTR_CONTROL_DISABLE;
serial_info.fRtsControl = RTS_CONTROL_DISABLE;
break;
case FlowControl::HardwareControl:
// 启用硬件流控制
serial_info.fOutxCtsFlow = TRUE;
serial_info.fOutxDsrFlow = TRUE;
serial_info.fInX = FALSE;
serial_info.fOutX = FALSE;
serial_info.fDtrControl = DTR_CONTROL_ENABLE;
serial_info.fRtsControl = RTS_CONTROL_ENABLE;
break;
case FlowControl::SoftwareControl:
// 启用软件流控制
serial_info.fOutxCtsFlow = FALSE;
serial_info.fOutxDsrFlow = FALSE;
serial_info.fInX = TRUE;
serial_info.fOutX = TRUE;
serial_info.fDtrControl = DTR_CONTROL_ENABLE;
serial_info.fRtsControl = RTS_CONTROL_ENABLE;
break;
default: std::cerr << "Unknown flow control type." << std::endl;
return;
}
// fInX = TRUE:启用接收端的软件流控,接收端在接收到 XOFF
// 时暂停接收数据,在接收到 XON 时恢复接收。 fOutX =
// TRUE:启用发送端的软件流控,发送端会根据接收端发送的 XON/XOFF
// 指令控制数据发送
void set_flow_control(DCB &serial_info, FlowControl flow_control) {
switch (flow_control) {
case FlowControl::NoFlowControl:
// 关闭所有流控制
serial_info.fOutxCtsFlow = FALSE;
serial_info.fOutxDsrFlow = FALSE;
serial_info.fInX = FALSE;
serial_info.fOutX = FALSE;
serial_info.fDtrControl = DTR_CONTROL_DISABLE;
serial_info.fRtsControl = RTS_CONTROL_DISABLE;
break;
case FlowControl::HardwareControl:
// 启用硬件流控制
serial_info.fOutxCtsFlow = TRUE;
serial_info.fOutxDsrFlow = TRUE;
serial_info.fInX = FALSE;
serial_info.fOutX = FALSE;
serial_info.fDtrControl = DTR_CONTROL_ENABLE;
serial_info.fRtsControl = RTS_CONTROL_ENABLE;
break;
case FlowControl::SoftwareControl:
// 启用软件流控制
serial_info.fOutxCtsFlow = FALSE;
serial_info.fOutxDsrFlow = FALSE;
serial_info.fInX = TRUE;
serial_info.fOutX = TRUE;
serial_info.fDtrControl = DTR_CONTROL_ENABLE;
serial_info.fRtsControl = RTS_CONTROL_ENABLE;
break;
default:
std::cerr << "Unknown flow control type." << std::endl;
return;
}
}
// 获取流控制
FlowControl get_flow_control(DCB& serial_info) {
if (serial_info.fInX && serial_info.fOutX) {
return FlowControl::SoftwareControl;
} else if (serial_info.fOutxCtsFlow && serial_info.fOutxDsrFlow) {
return FlowControl::HardwareControl;
} else if (!serial_info.fOutxCtsFlow && !serial_info.fOutxDsrFlow && !serial_info.fInX && !serial_info.fOutX) {
return FlowControl::NoFlowControl;
} else {
return FlowControl::UnknownFlowControl;
}
FlowControl get_flow_control(DCB &serial_info) {
if (serial_info.fInX && serial_info.fOutX) {
return FlowControl::SoftwareControl;
} else if (serial_info.fOutxCtsFlow && serial_info.fOutxDsrFlow) {
return FlowControl::HardwareControl;
} else if (!serial_info.fOutxCtsFlow && !serial_info.fOutxDsrFlow &&
!serial_info.fInX && !serial_info.fOutX) {
return FlowControl::NoFlowControl;
} else {
return FlowControl::UnknownFlowControl;
}
}
}
} // namespace Psc::serial
#endif
// int64_t read_data(HANDLE fd, char* data, int64_t maxSize, bool nonBlocking = false) {
// int64_t read_data(HANDLE fd, char* data, int64_t maxSize, bool nonBlocking =
// false) {
// DWORD bytesRead = 0;
// OVERLAPPED overlapped = {0};
//
@@ -425,19 +424,21 @@ FlowControl get_flow_control(DCB& serial_info) {
// if (error == ERROR_IO_PENDING) {
// if (nonBlocking) {
// // 等待操作完成
// if (WaitForSingleObject(overlapped.hEvent, INFINITE) == WAIT_OBJECT_0) {
// if (GetOverlappedResult(fd, &overlapped, &bytesRead, FALSE)) {
// if (WaitForSingleObject(overlapped.hEvent, INFINITE) ==
// WAIT_OBJECT_0) {
// if (GetOverlappedResult(fd, &overlapped, &bytesRead,
// FALSE)) {
// CloseHandle(overlapped.hEvent);
// return bytesRead;
// } else {
// std::cerr << "获取异步操作结果失败,错误代码: " << GetLastError() << std::endl;
// std::cerr << "获取异步操作结果失败,错误代码: " <<
// GetLastError() << std::endl;
// CloseHandle(overlapped.hEvent);
// return -1;
// }
// } else {
// std::cerr << "等待事件失败,错误代码: " << GetLastError() << std::endl;
// CloseHandle(overlapped.hEvent);
// return -1;
// std::cerr << "等待事件失败,错误代码: " << GetLastError()
// << std::endl; CloseHandle(overlapped.hEvent); return -1;
// }
// }
// return -1;
@@ -461,14 +462,15 @@ FlowControl get_flow_control(DCB& serial_info) {
// DWORD bytesAvailable = 0;
// // 先探测是否有数据
// if (!PeekNamedPipe(fd, NULL, 0, NULL, &bytesAvailable, NULL)) {
// std::cerr << "PeekNamedPipe 失败,错误代码: " << GetLastError() << std::endl;
// return -1;
// std::cerr << "PeekNamedPipe 失败,错误代码: " << GetLastError() <<
// std::endl; return -1;
// }
// if (bytesAvailable > 0) {
// DWORD bytesRead = 0;
// if (!ReadFile(fd, data, static_cast<DWORD>(maxSize), &bytesRead, NULL)) {
// std::cerr << "ReadFile 失败,错误代码: " << GetLastError() << std::endl;
// return -1;
// if (!ReadFile(fd, data, static_cast<DWORD>(maxSize), &bytesRead,
// NULL)) {
// std::cerr << "ReadFile 失败,错误代码: " << GetLastError() <<
// std::endl; return -1;
// }
// return bytesRead;
// } else {
@@ -481,7 +483,8 @@ FlowControl get_flow_control(DCB& serial_info) {
// //return read_data(fd, data, maxSize, true); // 返回读取的字节数
// OVERLAPPED overlapped = {};
// DWORD bytesRead = 0;
// if (ReadFile(fd, data, maxSize, &bytesRead, &overlapped) || GetLastError() == ERROR_IO_PENDING) {
// if (ReadFile(fd, data, maxSize, &bytesRead, &overlapped) ||
// GetLastError() == ERROR_IO_PENDING) {
// std::cout << "bytesRead:" << bytesRead;
// if (GetOverlappedResult(fd, &overlapped, &bytesRead, FALSE)) {
// return bytesRead;
@@ -502,8 +505,8 @@ FlowControl get_flow_control(DCB& serial_info) {
// }
//
// // 发起异步读取操作
// BOOL result = ReadFile(fd, data, static_cast<DWORD>(maxSize), &bytesRead, &overlapped);
// if (!result) {
// BOOL result = ReadFile(fd, data, static_cast<DWORD>(maxSize), &bytesRead,
// &overlapped); if (!result) {
// DWORD err = GetLastError();
// if (err != ERROR_IO_PENDING) {
// LOG_ERROR("ReadFile failed");