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}

 

posted @ 2021-10-22 15:23  流逝的轻风  阅读(1219)  评论(0编辑  收藏  举报