C++ 如何使用boost::asio通过串行连接正确编写Win32应用程序
我正在开发一个Windows应用程序,它必须通过其串行端口与Arduino进行通信(输入和输出)。出于可移植性的原因,我正在使用boost::asio,我希望继续使用它。发生的情况是,第一次运行应用程序时,它工作得很好,但如果第二次运行,则不再有来自Arduino的数据,应用程序将停止读取操作。恢复的唯一方法是从计算机上拔下并重新插入Arduino USB电缆 此行为特定于Windows。同样的代码在Linux上也能完美地工作 编译器是Visual Studio 2017社区版 下面是重现问题的示例代码:C++ 如何使用boost::asio通过串行连接正确编写Win32应用程序,c++,boost,arduino,serial-port,C++,Boost,Arduino,Serial Port,我正在开发一个Windows应用程序,它必须通过其串行端口与Arduino进行通信(输入和输出)。出于可移植性的原因,我正在使用boost::asio,我希望继续使用它。发生的情况是,第一次运行应用程序时,它工作得很好,但如果第二次运行,则不再有来自Arduino的数据,应用程序将停止读取操作。恢复的唯一方法是从计算机上拔下并重新插入Arduino USB电缆 此行为特定于Windows。同样的代码在Linux上也能完美地工作 编译器是Visual Studio 2017社区版 下面是重现问题的
#include <iostream>
#include <string>
#include <boost/asio.hpp>
#include <vector>
int main() {
boost::asio::serial_port port(ioctx, "COM3"); // "/dev/ttyACM0" on Linux
port.set_option(boost::asio::serial_port::baud_rate(9600));
port.set_option(boost::asio::serial_port::character_size(8));
port.set_option(boost::asio::serial_port::stop_bits(boost::asio::serial_port::stop_bits::one));
port.set_option(boost::asio::serial_port::parity(boost::asio::serial_port::parity::none));
port.set_option(boost::asio::serial_port::flow_control(boost::asio::serial_port::flow_control::none));
char c = 'e';
auto const s = boost::asio::write(port, boost::asio::buffer(&c, 1));
std::cout << "sent " << s << " bytes" << std::endl;
boost::asio::streambuf response;
boost::asio::read_until(port, response, "\r\n");
std::istream response_stream(&response);
std::string line;
std::getline(response_stream, line);
std::cout << line << std::endl;
port.close(); // last-ditch effort to get it working
}
有没有办法恢复连接的正确状态?我遗漏了什么吗?USB串行适配器可能有设备驱动程序错误和硬件问题。您必须拔下并插入设备才能使其重新工作,这表明存在设备驱动程序错误
- 寻找更新的驱动程序。它可能是一个多产或FTDI芯片组,确保你从芯片制造商那里得到驱动程序。看到或
- 如果是与流量控制相关的硬件问题,您可以将DTR、DSR和CD引脚连接在一起,并将USB适配器上RS-232接口上的RTS和CTS引脚连接在一起。我见过USB适配器,这是必要的,尽管设置没有流量控制的软件
SetCommState
函数一次设置所有连接参数,并以与GetCommState
函数类似的方式检索它们。这是set_option
函数用来设置参数的方法,但是在一行中多次调用GetCommState
-SetCommState
会大大降低过程的速度(可能是通过多次重置Arduino) #include <Windows.h>
#include <chrono>
void init_arduino(boost::asio::serial_port& port, std::chrono::milliseconds const& sleep = 2000)
{
DCB dcbSerialParams = { 0 };
GetCommState(port.native_handle(), &dcbSerialParams);
// this is the optimal way to set the whole serial port configuration
// just in one shot.
dcbSerialParams.BaudRate = CBR_9600;
dcbSerialParams.ByteSize = 8;
dcbSerialParams.StopBits = ONESTOPBIT;
dcbSerialParams.Parity = NOPARITY;
//Setting the DTR to Control_Enable ensures that the Arduino is properly
//reset upon establishing a connection
dcbSerialParams.fDtrControl = DTR_CONTROL_ENABLE;
SetCommState(port.native_handle(), &dcbSerialParams);
PurgeComm(port.native_handle(), PURGE_RXCLEAR | PURGE_TXCLEAR);
// Wait for Arduino to boot the sketch
Sleep(sleep.count());
}
#包括
#包括
void init_arduino(boost::asio::串行端口和端口,std::chrono::毫秒常量和睡眠=2000)
{
DCB dcbSerialParams={0};
GetCommState(port.native_handle(),&dcbSerialParams);
//这是设置整个串行端口配置的最佳方式
//就这么一枪。
dcbSerialParams.BaudRate=CBR_9600;
dcbSerialParams.ByteSize=8;
dcbSerialParams.StopBits=一个停止位;
dcbSerialParams.奇偶性=无奇偶性;
//将DTR设置为Control_Enable可确保Arduino正常运行
//建立连接后重置
dcbSerialParams.fDtrControl=DTR\u CONTROL\u ENABLE;
SetCommState(port.native_handle(),&dcbSerialParams);
PurgeComm(port.native_handle(),PURGE_RXCLEAR | PURGE_TXCLEAR);
//等待Arduino启动草图
Sleep(Sleep.count());
}
并使用它替换问题示例中的port.set_选项(
行)
我还将流量控制设置为
DTR\u control\u ENABLE
,而不是原来的none
,以便在连接时重置Arduino。谢谢您的发帖,我只是在自己回答问题的过程中。的确,出现了错误,但在这种情况下,它既不是驱动程序,也不是硬件。Arduino正在工作在Linux下以及Windows上使用Arduino IDE串行监视器时,g都非常完美。
#include <Windows.h>
#include <chrono>
void init_arduino(boost::asio::serial_port& port, std::chrono::milliseconds const& sleep = 2000)
{
DCB dcbSerialParams = { 0 };
GetCommState(port.native_handle(), &dcbSerialParams);
// this is the optimal way to set the whole serial port configuration
// just in one shot.
dcbSerialParams.BaudRate = CBR_9600;
dcbSerialParams.ByteSize = 8;
dcbSerialParams.StopBits = ONESTOPBIT;
dcbSerialParams.Parity = NOPARITY;
//Setting the DTR to Control_Enable ensures that the Arduino is properly
//reset upon establishing a connection
dcbSerialParams.fDtrControl = DTR_CONTROL_ENABLE;
SetCommState(port.native_handle(), &dcbSerialParams);
PurgeComm(port.native_handle(), PURGE_RXCLEAR | PURGE_TXCLEAR);
// Wait for Arduino to boot the sketch
Sleep(sleep.count());
}