• 用ASIO读写串行口


    ASIO不仅支持网络通信,还能支持串口通信。要让两个设备使用串口通信,关键是要设置好正确的参数,这些参数是:波特率、奇偶校验 位、停止位、字符大小和流量控制。两个串口设备只有设置了相同的参数才能互相交谈。

    ASIO提供了boost::asio::serial_port类,它有一个set_option(const SettableSerialPortOption& option)方法就是用于设置上面列举的这些参数的,其中的option可以是:

    • serial_port::baud_rate 波特率,构造参数为unsigned int
    • serial_port::parity 奇偶校验,构造参数为serial_port::parity::type,enum类型,可以是none, odd, even。
    • serial_port::flow_control 流量控制,构造参数为serial_port::flow_control::type,enum类型,可以是none software hardware
    • serial_port::stop_bits 停止位,构造参数为serial_port::stop_bits::type,enum类型,可以是one onepointfive two
    • serial_port::character_size 字符大小,构造参数为unsigned int

     

    演示代码

    #include <iostream>
    #include <boost/asio.hpp>
    #include <boost/bind.hpp>

    using namespace std;
    using namespace boost::asio;

    int main(int argc, char* argv[])
    {
            io_service iosev;
            // 串口COM1, Linux下为“/dev/ttyS0”
            serial_port sp(iosev, "COM1");
            // 设置参数
            sp.set_option(serial_port::baud_rate(19200));
            sp.set_option(serial_port::flow_control(serial_port::flow_control::none));
            sp.set_option(serial_port::parity(serial_port::parity::none));
            sp.set_option(serial_port::stop_bits(serial_port::stop_bits::one));
            sp.set_option(serial_port::character_size(8));
            // 向串口写数据
            write(sp, buffer("Hello world"12));

            // 向串口读数据
            char buf[100];
            read(sp, buffer(buf));

            iosev.run();
            return 0;


    上面这段代码有个问题,read(sp, buffer(buf))非得读满100个字符才会返回,串口通信有时我们确实能知道对方发过来的字符长度,有时候是不能的。

    如果知道对方发过来的数据里有分隔符的话(比如空格作为分隔),可以使用read_until来读,比如:

    boost::asio::streambuf buf;
    // 一直读到遇到空格为止
    read_until(sp, buf, ' ');
    copy(istream_iterator<char>(istream(&buf)>>noskipws),
            istream_iterator<char>(),
            ostream_iterator<char>(cout));
     

    另外一个方法是使用前面说过的异步读写+超时的方式,代码如下: 

    #include <iostream>
    #include <boost/asio.hpp>
    #include <boost/bind.hpp>

    using namespace std;
    using namespace boost::asio;
    void handle_read(char *buf,boost::system::error_code ec,
    std::size_t bytes_transferred)
    {
            cout.write(buf, bytes_transferred);
    }

    int main(int argc, char* argv[])
    {
            io_service iosev;
            serial_port sp(iosev, "COM1");
            sp.set_option(serial_port::baud_rate(19200));
            sp.set_option(serial_port::flow_control());
            sp.set_option(serial_port::parity());
            sp.set_option(serial_port::stop_bits());
            sp.set_option(serial_port::character_size(8));

            write(sp, buffer("Hello world"12));

            // 异步读
            char buf[100];
            async_read(sp, buffer(buf), boost::bind(handle_read, buf, _1, _2));
            // 100ms后超时
            deadline_timer timer(iosev);
            timer.expires_from_now(boost::posix_time::millisec(100));
            // 超时后调用sp的cancel()方法放弃读取更多字符
            timer.async_wait(boost::bind(&serial_port::cancel, boost::ref(sp)));

            iosev.run();
            return 0;


  • 相关阅读:
    Vue自定义Table
    Cesium GeometryIntstance 选中改变颜色 和 绘制带箭头的直线
    echart 饼图
    C# 读取json 文件 解析处理并另存
    滚动条到底 监听
    二分总结
    LeetCode 438. 找到字符串中所有字母异位词
    LeetCode 400. 第 N 位数字
    WPF深入浅出代码案例
    设计模式生成器模式
  • 原文地址:https://www.cnblogs.com/toosuo/p/2281008.html
Copyright © 2020-2023  润新知