C++实现Linux下串口的读写

更新时间:2019-12-30 14:23:57 点击次数:1517次
/* 
 * File:   BSerialPort.h
 */

#ifndef BSERIALPORT_H
#define BSERIALPORT_H

class BSerialPort {
public:
    friend class BSerialPortManger;
    
    enum SerialType{
        Actual, Virtual,
    };
    
    BSerialPort();
    BSerialPort(const BSerialPort& orig);
    BSerialPort(char *filename, SerialType type = Actual);
    BSerialPort(const char *filename, SerialType type = Actual);
    
    virtual ~BSerialPort();
    
    /*
     * 参数: 串口设备文件路径
     * 功能:打开串口,默认设置串口设备参数:9600,N,1
     * 返回值:成功 true ; 失败 false
     */
    bool open(char *filename);
    /*
     * 参数: 串口波特率
     * 功能: 设置串口模特率,可以是下面的一个值
     * 921600, 460800, 230400, 115200, 57600, 38400, 19200, 9600, 4800, 2400, 1200, 300
     * 返回值: 成功 true ; 失败 false
     */
    bool set_Speed(int speed);
    /*
     * 参数: databits:数据位数
     *       stopbits:停止位
     *       parity:  校验位
     * 功能: 设置串口的数据位、停止位、校验位。
     * 返回值: 成功 true ; 失败 false
     */
    bool set_Parity(int databits, int stopbits, char parity);
    /*
     * 参数:dest:数据读取缓存数组
     *      bytes:要读取数据的字节数
     * 功能:从串口读取数据存储在dest中
     * 返回值:实际读取数据字节数,出错返回-1。
     */
    int  read(char *dest, int bytes);
    /*
     * 参数:buff:要写入的数据
     *      bytes:要写入数据的字节数
     * 功能:将buff中的数据写入串口
     * 返回值:实际写入数据字节数,出错返回-1。
     */
    int  write(char *buff, int bytes);
    /*关闭串口*/
    void close(void);
    
    bool operator==(BSerialPort &serial);
private:
    /*串口文件描述符*/
    int fd;
    /*如果是虚拟串口,从设备的文件描述符*/
    int sfd;
    void (*function)(BSerialPort *serial);
};
#endif /* BSERIALPORT_H */


/* 
 * File:   BSerialPortManger.h
 */

#ifndef BSERIALPORTMANGER_H
#define BSERIALPORTMANGER_H

#include "BSerialPort.h"
#include <vector>
#include <string>
#include <unistd.h>
#include <sys/time.h>
#include <iostream>

using namespace std;

class BSerialPortManger {
public:
    BSerialPortManger();
    BSerialPortManger(const BSerialPortManger& orig);
    virtual ~BSerialPortManger();
    
    /*向串口管理类中添加一个待监控的串口*/
    void add(BSerialPort *serial, void (*func)(BSerialPort *serial));
    /*从管理类中移除一个串口*/
    void remove(BSerialPort *serial);
    /*每调用一次,检查一次是否有串口数据到达*/
    void read_monitor();
private:
    vector<BSerialPort *> list;
    int fd_max;
    fd_set fd_sets;
    fd_set handle_sets;
};
#endif /* BSERIALPORTMANGER_H */


上面我定义了两个类,一个是串口类一个是串口管理类。BSerialPortManger类是BSerialPort的友元类,这样利用BSerialPortManger就能管理所以注册到该类的串口对象,如果有可读数据就调用对应对象的回调函数。

下面展示BSerialPortManger::add的实现

void BSerialPortManger::add(BSerialPort* serial, void (*func)(BSerialPort *serial)){
    serial->function = func;
    if(serial->fd > 0){
        FD_SET(serial->fd, &this->handle_sets);
        this->list.push_back(serial);
        this->fd_max = 0;
        cout << "list_count:" << this->list.size()<<endl;
        for(int i = 0; i < this->list.size(); i++){
            if(this->list.at(i)->fd > this->fd_max)
                this->fd_max = this->list.at(i)->fd;
        }
    }   
}

监控函数的实现是利用select函数来监控所以注册的串口对象是否有数据要读取,如果有则调用相应的回调函数。

void BSerialPortManger::read_monitor(){
    struct timeval timeout;
    timeout.tv_sec = 0;
    timeout.tv_usec = 100000;
    this->fd_sets = this->handle_sets;
    int rs = select(this->fd_max+1, &this->fd_sets, NULL, NULL, &timeout);
    if(rs > 0){
        for(int i = 0; i < this->list.size(); i++){
            if(FD_ISSET(this->list.at(i)->fd, &this->fd_sets) && this->list.at(i)->function != NULL){
                this->list.at(i)->function(this->list.at(i));
            }
        }
    }
}

本站文章版权归原作者及原出处所有 。内容为作者个人观点, 并不代表本站赞同其观点和对其真实性负责,本站只提供参考并不构成任何投资及应用建议。本站是一个个人学习交流的平台,网站上部分文章为转载,并不用于任何商业目的,我们已经尽可能的对作者和来源进行了通告,但是能力有限或疏忽,造成漏登,请及时联系我们,我们将根据著作权人的要求,立即更正或者删除有关内容。本站拥有对此声明的最终解释权。

回到顶部
嘿,我来帮您!