zoukankan      html  css  js  c++  java
  • 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
    ");
                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
    ");
                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
    ");
                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}
  • 相关阅读:
    学习进度条博客(软件工程)第一周
    随机产生30个两位数的四则运算(包括真分数的计算)
    构建之法阅读笔记01
    感想
    《构建之法》阅读笔记04
    团队冲刺第二天
    第八周学习进度条
    团队冲刺第一天
    第七周学习进度条
    课堂测试03
  • 原文地址:https://www.cnblogs.com/cqwo/p/15439109.html
Copyright © 2011-2022 走看看