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

作为一个嵌入式程序员,串口的读写已经见怪不怪了。嵌入式Linux的串口也应用广泛。百度一搜也有许多讲解这方面的知识,今天我只展示我Linux下用C++实现的一个串口类可以实现类似于单片机中断的机制。使用起来很方便

我只展示接口:

/* 
 * 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));
            }
        }
    }
}

由于代码量较多,这里就不全部列出了。在类的实现中用到了回调函数和函数指针的知识,不懂的读者可以参考https://blog.csdn.net/BLUCEJIE/article/details/103538410。
串口类以及串口管理类的实现源码请在我博客的资源文件中下载http://download.csdn.net/download/BLUCEJIE/12063038
在上面的类实现中还实现了虚拟串口的功能,这样的虚拟串口是用Linux的为终端实现的。

发布了23 篇原创文章 · 获赞 27 · 访问量 1154

猜你喜欢

转载自blog.csdn.net/BLUCEJIE/article/details/103753635
今日推荐