以下是使用Boost.Asio实现同步串口通信的示例代码:
#include <iostream>
#include <boost/asio.hpp>
using namespace boost::asio;
using namespace boost::system;
class SyncSerialPort
{
public:
SyncSerialPort(const std::string& port, unsigned int baud_rate)
: io_(), port_(io_)
{
// 打开串口
port_.open(port);
// 配置串口参数
port_.set_option(serial_port::baud_rate(baud_rate));
port_.set_option(serial_port::flow_control(serial_port::flow_control::none));
port_.set_option(serial_port::parity(serial_port::parity::none));
port_.set_option(serial_port::stop_bits(serial_port::stop_bits::one));
port_.set_option(serial_port::character_size(8));
}
// 同步写入数据
void write(const std::string& data)
{
try {
size_t bytes_written = write(port_, buffer(data));
std::cout << "Sent " << bytes_written << " bytes" << std::endl;
}
catch (const boost::system::system_error& e) {
std::cerr << "Write error: " << e.what() << std::endl;
}
}
// 同步读取数据(带超时)
std::string read(size_t timeout_sec = 5)
{
try {
// 设置超时
deadline_timer timer(io_);
timer.expires_from_now(boost::posix_time::seconds(timeout_sec));
std::string result;
char buf[128];
while (true) {
size_t bytes_read = port_.read_some(buffer(buf));
result.append(buf, bytes_read);
// 检查是否满足停止条件(例如收到特定结束符)
if (result.find('\n') != std::string::npos) {
break;
}
// 检查超时
if (timer.expires_at() <= deadline_timer::traits_type::now()) {
port_.cancel(); // 取消IO操作
throw boost::system::system_error(
error::operation_aborted, "Read timeout");
}
}
return result;
}
catch (const boost::system::system_error& e) {
std::cerr << "Read error: " << e.what() << std::endl;
return "";
}
}
private:
io_context io_;
serial_port port_;
};
int main()
{
try {
// 创建串口对象(Windows使用"COM3"格式)
SyncSerialPort serial("/dev/ttyUSB0", 115200);
// 发送数据
serial.write("AT\\r\\n");
// 接收数据(带5秒超时)
std::string response = serial.read();
std::cout << "Received: " << response << std::endl;
}
catch (const std::exception& e) {
std::cerr << "Error: " << e.what() << std::endl;
}
return 0;
}
代码特点说明:
-
同步操作核心方法:
write()
:使用boost::asio::write()
进行阻塞式写入read()
:使用read_some()
进行分块读取,支持超时控制
-
超时控制机制:
deadline_timer timer(io_); timer.expires_from_now(boost::posix_time::seconds(timeout_sec));
使用deadline_timer实现超时控制,防止永久阻塞
-
数据接收策略:
while (true) { size_t bytes_read = port_.read_some(buffer(buf)); // ...处理数据... }
持续读取直到满足停止条件(如检测到换行符)
-
错误处理:
- 使用try-catch块捕获system_error
- 自动处理串口断开等异常情况
编译命令(Linux):
g++ -std=c++11 -o sync_serial sync_serial.cpp -lboost_system -lpthread
同步 vs 异步的选择建议:
特性 | 同步通信 | 异步通信 |
---|---|---|
代码复杂度 | 简单 | 较复杂(需要回调管理) |
性能 | 适合低频操作 | 适合高并发场景 |
线程占用 | 阻塞当前线程 | 非阻塞,配合io_context使用 |
适用场景 | 简单命令/响应模式 | 需要同时处理多个I/O操作 |
超时控制 | 需要手动实现 | 可集成到异步操作链中 |
扩展建议:
-
协议解析:
// 在read方法中添加协议解析逻辑 if (response.find("OK") != std::string::npos) { // 处理成功响应 }
-
二进制数据传输:
// 使用vector<uint8_t>代替string std::vector<uint8_t> binary_data = {0x01, 0x02, 0x03}; write(port_, buffer(binary_data));
-
流量控制:
// 启用硬件流控 port_.set_option(serial_port::flow_control( serial_port::flow_control::hardware));
-
错误重试机制:
bool send_with_retry(const std::string& data, int max_retries = 3) { for (int i = 0; i < max_retries; ++i) { try { write(data); return true; } catch (...) { // 等待后重试 sleep(1); } } return false; }
此同步实现方案适合以下场景:
- 需要简单快速的串口测试工具
- 单线程环境下操作串口
- 对实时性要求不高的配置类操作
- 硬件调试时的交互式操作