作为一个嵌入式程序员,串口的读写已经见怪不怪了。嵌入式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的为终端实现的。