您的位置:

全能串行通信库-serial库

Serial库是一个面向对象的跨平台串行通信库。它提供了一个简单而一致的接口,以处理各种串行协议。这篇文章将从以下多个方面详细阐述serial库的特点和使用方法。

一、初始化串行通信

对于串行通信设备,如何初始化才能使用?在使用serial库之前,需要对串行口设置进行初始化。这些设置包括波特率、数据位、停止位、校验位等,如下所示:

#include "serial/serial.h"

serial::Serial my_serial("/dev/ttyUSB0", 115200, serial::Timeout::simpleTimeout(1000));

void init_serial()
{
    my_serial.setBaudrate(9600);
    my_serial.setBytesize(serial::eightbits);
    my_serial.setParity(serial::parity_none);
    my_serial.setStopbits(serial::stopbits_one);
}

这里创建了一个名为my_serial的串行通信对象,将其绑定到设备/dev/ttyUSB0上,并设置波特率为115200。之后调用my_serial的四个函数,依次设置数据位、校验位和停止位。需要注意的是,在设置完这些参数之后,还需要调用setBaudrate()函数重新设置波特率,以保证波特率设置正确。

二、读写串行数据

串行通信是双向的,用户需要能够读取来自串行设备的数据,同时还需要向其发送数据。为此,serial库提供了以下两个函数:

size_t read(uint8_t *buf, size_t size);
size_t write(const uint8_t *data, size_t length);

read()函数从串行口中读取数据,将其存储在缓冲区中,然后返回实际读取的字节数。用户需要提供缓冲区指针和要读取的字节数。write()函数将数据写入串行口,需要提供发送数据的指针和字节数。下面是一个例子:

void serial_write_data()
{
    std::string write_data("Hello, world!");
    my_serial.write(write_data);
}

void serial_read_data()
{
    std::vector read_data;
    read_data.resize(10);
    size_t bytes_read = my_serial.read(read_data.data(), 10);
}

  

这里的serial_write_data()函数将字符串"Hello, world!"写入串行口,而serial_read_data()函数从串行口中读取了10个字节的数据存储在read_data中。

三、控制串行通信流

有时候,当没有足够的数据时,读取操作会被阻塞。在这种情况下,根据用户需求进行流的控制非常重要。serial库提供了以下控制函数,以控制流的状态:

void flushInput();
void flushOutput();
void flush();
void pause();
void resume();

flushInput()函数清除输入缓冲区,flushOutput()清除输出缓冲区,flush()函数清除输入输出缓冲区。pause()和resume()将控制通信流。调用pause()时,串行口将不再读取或写入数据。调用resume()时,流将恢复,并尝试建立新的连接。下面是一个例子:

void serial_control_flow()
{
    my_serial.pause();    // pause the flow
    my_serial.flushInput(); // clear input buffer
    my_serial.flushOutput();    // clear output buffer
    my_serial.resume();   // resume the flow
}

四、串行端口信息

串行口的一些信息,如其设备名称、波特率等,对于一些应用程序而言是非常重要的。serial库提供了以下函数来获取这些信息:

std::string getPort() const;
uint32_t getBaudrate() const;
uint8_t getBytesize() const;
uint8_t getParity() const;
uint8_t getStopbits() const;
bool isOpen() const;

getPort()函数返回串行通信对象使用的设备名称。getBaudrate()返回当前波特率,getBytesize()返回数据位,getParity()返回校验位类型,getStopbits()返回停止位类型,而isOpen()函数则检查端口是否已打开。下面是一个例子:

void serial_port_info()
{
    std::string port_name = my_serial.getPort();
    uint32_t baudrate = my_serial.getBaudrate();
    uint8_t bytesize = my_serial.getBytesize();
    uint8_t parity = my_serial.getParity();
    uint8_t stopbits = my_serial.getStopbits();
    bool is_open = my_serial.isOpen();
}

五、错误处理

由于串行通信与硬件相关,因此在使用过程中可能会出现错误。serial库提供了以下几种错误处理方式:

enum SerialExceptionType
{
    timeout,
    port_not_open,
    already_open,
    open_failed,
    configuration_failed,
    read_failed,
    write_failed,
    ioctl_failed,
    other_error
};

class SerialException : public std::exception
{
public:
    SerialException() : type_(other_error){}
    SerialException(const SerialExceptionType& type) : type_(type){}
    virtual const char *what() const noexcept override
    {
        return "serial exception";
    }
    virtual const char *type() const noexcept
    {
        switch (type_)
        {
            case timeout:
                return "timed out";
            case port_not_open:
                return "port not open";
            case already_open:
                return "port already open";
            case open_failed:
                return "failed to open port";
            case configuration_failed:
                return "failed to configure port";
            case read_failed:
                return "read failed";
            case write_failed:
                return "write failed";
            case ioctl_failed:
                return "ioctl failed";
            case other_error:
            default:
                return "other error";
        }
    }
    SerialExceptionType type() const noexcept
    {
        return type_;
    }
private:
    SerialExceptionType type_;
};

SerialException作为serial库的异常类,提供了几种错误类型。例如timeout表示读或写操作因超时而失败,port_not_open表示串行端口未被打开,already_open表示已经打开的端口再次被打开,open_failed表示打开端口失败,configuration_failed表示无法对端口进行正确的配置,而read_failed和write_failed表示读或写操作失败。

六、总结

serial库是一个功能强大且易于使用的库,非常适合处理各种串行通信协议。它提供了一些重要的功能,如初始化通信、读写通信、控制通信流、获取串行端口信息和错误处理等。使用serial库能够让用户轻松地进行串行通信。code示例:

#include "serial/serial.h"

serial::Serial my_serial("/dev/ttyUSB0", 115200, serial::Timeout::simpleTimeout(1000));

void init_serial()
{
    my_serial.setBaudrate(9600);
    my_serial.setBytesize(serial::eightbits);
    my_serial.setParity(serial::parity_none);
    my_serial.setStopbits(serial::stopbits_one);
}

void serial_write_data()
{
    std::string write_data("Hello, world!");
    my_serial.write(write_data);
}

void serial_read_data()
{
    std::vector read_data;
    read_data.resize(10);
    size_t bytes_read = my_serial.read(read_data.data(), 10);
}

void serial_control_flow()
{
    my_serial.pause();
    my_serial.flushInput();
    my_serial.flushOutput();
    my_serial.resume();
}

void serial_port_info()
{
    std::string port_name = my_serial.getPort();
    uint32_t baudrate = my_serial.getBaudrate();
    uint8_t bytesize = my_serial.getBytesize();
    uint8_t parity = my_serial.getParity();
    uint8_t stopbits = my_serial.getStopbits();
    bool is_open = my_serial.isOpen();
}