spi*_*epf 3 boost serial-port arduino boost-asio
我正在尝试使用boost在台式机和arduino之间进行串行通信。在arduino空间中,我可以在尝试执行读取操作之前询问串行端口是否有可用字节。
我在查找boost :: asio :: serial_port的等效项时遇到了麻烦。
尽管Boost.Asio不为此提供直接支持,但仍然可以通过将串行端口native_handle()与系统特定的调用配合使用来实现此目的。请查阅系统文档以确定如何查询准备读取的可用字节,但是通常ioctl(..., FIONREAD, ...)在Linux和ClearCommError()Windows上使用。
这是一个完整的最小示例,该示例使用系统特定的调用来获取可用的字节数。示例程序将继续查询串行端口,直到有20个以上的可用字节为止,此时它将读取除5个字节以外的所有字节:
#include <iostream>
#include <vector>
#include <boost/asio.hpp>
#include <boost/thread.hpp>
/// @brief Returns the number of bytes available for reading from a serial
/// port without blocking.
std::size_t get_bytes_available(
boost::asio::serial_port& serial_port,
boost::system::error_code& error)
{
error = boost::system::error_code();
int value = 0;
#if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
COMSTAT status;
if (0 != ::ClearCommError(serial_port.lowest_layer().native_handle(),
NULL, &status))
{
value = status.cbInQue;
}
// On error, set the error code.
else
{
error = boost::system::error_code(::GetLastError(),
boost::asio::error::get_system_category());
}
#else // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
if (0 == ::ioctl(serial_port.lowest_layer().native_handle(),
FIONREAD, &value))
{
error = boost::system::error_code(errno,
boost::asio::error::get_system_category());
}
#endif // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
return error ? static_cast<std::size_t>(0)
: static_cast<size_t>(value);
}
/// @brief Returns the number of bytes available for reading from a serial
/// port without blocking. Throws on error.
std::size_t get_bytes_available(boost::asio::serial_port& serial_port)
{
boost::system::error_code error;
std::size_t bytes_available = get_bytes_available(serial_port, error);
if (error)
{
boost::throw_exception((boost::system::system_error(error)));
}
return bytes_available;
}
int main(int argc, char* argv[])
{
if (argc < 2)
{
std::cerr << "Usage: " << argv[0] << " <device_name>" << std::endl;
return 1;
}
// Create all I/O objects.
boost::asio::io_service io_service;
boost::asio::serial_port serial_port(io_service, argv[1]);
// Continue quering the serial port until at least 20 bytes are available
// to be read.
std::size_t bytes_available = 0;
while (bytes_available < 20)
{
bytes_available = get_bytes_available(serial_port);
std::cout << "available: " << bytes_available << std::endl;
boost::this_thread::sleep_for(::boost::chrono::seconds(3));
}
// Read all but 5 available bytes.
std::vector<char> buffer(bytes_available - 5);
std::size_t bytes_transferred =
read(serial_port, boost::asio::buffer(buffer));
bytes_available = get_bytes_available(serial_port);
// Print results.
std::cout << "Read " << bytes_transferred << " bytes\n";
std::cout.write(&buffer[0], bytes_transferred);
std::cout << "\navailable: " << bytes_available << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
使用以下命令创建虚拟串行端口socat:
$ socat -d -d PTY: PTY
2015/02/01 21:12:31 socat[3056] N PTY is /dev/pts/2
2015/02/01 21:12:31 socat[3056] N PTY is /dev/pts/3
2015/02/01 21:12:31 socat[3056] N starting data transfer loop
with FDs [3,3] and [5,5]
Run Code Online (Sandbox Code Playgroud)
在一个终端中启动程序后,我/dev/pts/3在另一终端中写入:
$ echo -n "This is" > /dev/pts/3
$ echo -n " an example" > /dev/pts/3
$ echo -n " with asio." > /dev/pts/3
Run Code Online (Sandbox Code Playgroud)
以及程序的结果输出:
$ ./a.out /dev/pts/2
available: 0
available: 7
available: 18
available: 29
Read 24 bytes
This is an example with
available: 5
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1630 次 |
| 最近记录: |