由于自己需要,封装了一个串口的方案,单例模式
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}
原文链接: https://www.cnblogs.com/cqwo/p/15439109.html
欢迎关注
微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍
原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/214476
非原创文章文中已经注明原地址,如有侵权,联系删除
关注公众号【高性能架构探索】,第一时间获取最新文章
转载文章受原作者版权保护。转载请注明原作者出处!