c++ linux串口封装方案
由于自己需要,封装了一个串口的方案,单例模式
1.头文件 uart.h
#ifndef ___UART_H___ #define ___UART_H___ #include <stdio.h> /*标准输入输出定义*/ #include <stdlib.h> /*标准函数库定义*/ #include <iostream> #include <termios.h> #include <errno.h> #include <time.h> #include <pthread.h> #include <string.h> #include <dirent.h> #include <unistd.h> #include <fcntl.h> #include <unistd.h> #include <fcntl.h> #define DEFAULT_UART_COM "/dev/ttyS3" //环境探测器 #define DEFAULT_VMIN 5 #define DEFAULT_VTIME 6 class SerialPort { private: SerialPort(); //构造方法 public: // 串口打开关闭与读写 int openUart(const char* path); //设置串口波特率 int setSpeed(int fd, int speed); //设置串口的数据位、停止位、校验位。 int setParity(int fd, int databits, int stopbits, char parity); //串口写入数据 int writeUart(int fd, const void* data, size_t size); //读取串口数据 int readUart(int fd, void* data, size_t size); //关闭串口 int closeUart(int fd); private: static SerialPort* m_instance_ptr; //单例变量 public: static pthread_mutex_t mutex; static SerialPort* getInstance(); //单例实例化函数 }; #endif // !___UART_H___
2.uarh.cpp 文件
#include "uart.h" //默认构造方法 SerialPort::SerialPort() { } /****************************************************************************** * Name : SerialPort::close * Author : cqnews * Version : V1.0.0 * Data : 2021.10.22 * Describe : 串口打开关闭与读写 * @path : 串口名称 * @speed : 串口波特率 * @ospeed : 等待时间,单位百毫秒(读) * *****************************************************************************/ int SerialPort::openUart(const char* path) { if (path == NULL) { return -1; } int fd = -1; fd = open(path, O_RDWR | O_NOCTTY); if (fd < 0) //串口打开失败 { perror(path); return -2; } struct termios opt; tcgetattr(fd, &opt); tcflush(fd, TCIOFLUSH);//设置前flush cfsetispeed(&opt, B9600); //设置的输入波特率 cfsetospeed(&opt, B9600); //设置的输出波特率 //raw mode opt.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG); opt.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON); opt.c_oflag &= ~(OPOST); opt.c_cflag &= ~(CSIZE | PARENB); opt.c_cflag |= CS8; //opt.c_cc[VMIN] = DEFAULT_VMIN; //最小字节数 //opt.c_cc[VTIME] = DEFAULT_VTIME; //等待时间,单位百毫秒 (读) if (tcsetattr(fd, TCSANOW, &opt) != 0) //配置发生错误 { return -3; } tcflush(fd, TCIOFLUSH); //设置后flush return fd; } int speed_arr[] = { B38400, B19200, B9600, B4800, B2400, B1200, B300, B38400, B19200, B9600, B4800, B2400, B1200, B300, }; int name_arr[] = { 38400, 19200, 9600, 4800, 2400, 1200, 300, 38400, 19200, 9600, 4800, 2400, 1200, 300, }; /****************************************************************************** * Name : SerialPort::setSpeed 串口波特率 * Author : cqnews * Version : V1.0.0 * Date : 2021.10.22 * Describe : 设置串口模特率,可以是下面的一个值 * 921600, 460800, 230400, 115200, 57600, 38400, 19200, 9600, 4800, 2400, 1200, 300 * 返回值: 成功 0 ; 失败 错误码 ******************************************************************************/ int SerialPort::setSpeed(int fd, int speed) { if (speed < 300 || speed > 921600) { return -1; //参数异常 } int i; int length = sizeof(speed_arr) / sizeof(int); for (i = 0; i < length; i++) { if (speed == name_arr[i]) { tcflush(fd, TCIOFLUSH); termios opt; tcgetattr(fd, &opt); cfsetispeed(&opt, speed_arr[i]); cfsetospeed(&opt, speed_arr[i]); if (tcsetattr(fd, TCSANOW, &opt) != 0) //配置发生错误 { return -2; //配置异常 } tcflush(fd, TCIOFLUSH); //设置后flush return 0; } } return -2; } /****************************************************************************** * Name : SerialPort::setParity 串口波特率 * Author : cqnews * Version : V1.0.0 * Date : 2021.10.22 * Describe : 设置串口的数据位、停止位、校验位。 * databit : 数据位 * stopbit : 停止位 * paritybit : 校验位* * 返回值: 成功 0 ; 失败 错误码 ******************************************************************************/ int SerialPort::setParity(int fd, int databit, int stopbit, char paritybit) { termios opt; tcgetattr(fd, &opt); tcflush(fd, TCIOFLUSH);//设置前flush switch (databit) //数据位 { case 7: opt.c_cflag |= CS7; break; case 8: opt.c_cflag |= CS8; break; default: fprintf(stderr, "Unsupported data size\n"); return -1; } switch (stopbit) //停止位 { case 1: opt.c_cflag &= ~CSTOPB; break; //1 位停止位 case 2: opt.c_cflag |= CSTOPB; break; //2 位停止位,否则为 1 位 default: fprintf(stderr, "Unsupported stop bit\n"); return -2; } switch (paritybit) //校验位 { case 'n': case 'N': opt.c_cflag &= ~PARENB; // 不校验 opt.c_iflag &= ~INPCK; //关闭输入奇偶校验 opt.c_iflag &= ~(ICRNL | IGNCR); opt.c_lflag &= ~(ICANON); //不规范输入 break; case 'o': //奇校验 case 'O': opt.c_cflag |= PARENB; //进行奇偶校验 opt.c_cflag |= PARODD; //奇校验,否则为偶校验 opt.c_iflag |= INPCK; //打开输入奇偶校验 break; case 'e': //偶校验 case 'E': opt.c_cflag |= PARENB; // 进行奇偶校验 opt.c_cflag &= ~PARODD; //偶校验 opt.c_iflag |= INPCK; //打开输入奇偶校验 break; case 'S': case 's': /*as no parity*/ opt.c_cflag &= ~PARENB; //不进行奇偶校验 opt.c_cflag &= ~CSTOPB; //1 位停止位 break; default: fprintf(stderr, "Unsupported parity bit\n"); return -3; } if (tcsetattr(fd, TCSANOW, &opt) != 0) //配置发生错误 { return -4; } tcflush(fd, TCIOFLUSH); //设置后flush return 0; } /****************************************************************************** * Name : SerialPort::close * Author : cqnews * Version : V1.0.0 * Date : 2021.10.22 * Describe : 串口写入数据 ******************************************************************************/ int SerialPort::writeUart(int fd, const void* buff, size_t size) { if (buff == NULL || size <= 0) { return -1; } return write(fd, buff, size); } /****************************************************************************** * Name : SerialPort::close * Author : cqnews * Version : V1.0.0 * Date : 2021.10.22 * Describe : 读取串口数据 ******************************************************************************/ int SerialPort::readUart(int fd, void* buff, size_t size) { if (buff == NULL || size <= 0) { return -1; } return read(fd, buff, size); } /****************************************************************************** * Name : SerialPort::close * Author : cqnews * Version : V1.0.0 * Date : 2021.10.22 * Describe : 关闭串口 ******************************************************************************/ int SerialPort::closeUart(int fd) { close(fd); return 0; } /****************************************************************************** * Name : Logger::Logger * Author : cqnews * Version : V1.0.0 * Date : 2021.07.28 * Describe : 串口单例函数 ******************************************************************************/ SerialPort* SerialPort::getInstance() { if (m_instance_ptr == NULL) { pthread_mutex_lock(&mutex); if (m_instance_ptr == NULL) { m_instance_ptr = new SerialPort(); } pthread_mutex_unlock(&mutex); } return m_instance_ptr; } pthread_mutex_t SerialPort::mutex; SerialPort* SerialPort::m_instance_ptr = NULL;
3.测试方法
LINK = @echo linking $@ && arm-linux-gnueabihf-g++ GCC = @echo compiling $@ && arm-linux-gnueabihf-g++ GC = @echo compiling $@ && arm-linux-gnueabihf-gcc AR = @echo generating static library $@ && ar crv FLAGS = -g -DDEBUG -W -Wall -fPIC -std=c++11 GCCFLAGS = DEFINES = HEADER = -I./ -I/usr/arm32/include LIBS = -L./ -L/usr/arm32/lib LINKFLAGS = LIBS += -pthread -lm SOURCE_FILES :=\ main.cpp\ app/uart/uart.cpp\ PROJECTNAME = UartDemo.out TARGET = main all: $(SOURCE_FILES) $(LINK) $(FLAGS) $(LINKFLAGS) -o ${PROJECTNAME} $^ $(LIBS) ${HEADER} clean: rm -rf *.o ${PROJECTNAME}