重新设置代码格式
This commit is contained in:
+205
-228
@@ -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
@@ -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
@@ -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
|
||||
|
||||
@@ -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
@@ -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,那么就不使用读间隔超时,如果 ReadTotalTimeoutMultiplier和ReadTotalTimeoutConstant都为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");
|
||||
|
||||
Reference in New Issue
Block a user