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}
  • 相关阅读:
    hdu 5224 Tom and paper 水题
    2015 UESTC 搜索专题N题 韩爷的梦 hash
    2015 UESTC 搜索专题M题 Palindromic String 马拉车算法
    2015 UESTC 搜索专题K题 秋实大哥の恋爱物语 kmp
    2015 UESTC 搜索专题J题 全都是秋实大哥 kmp
    2015 UESTC 搜索专题F题 Eight Puzzle 爆搜
    2015 UESTC 搜索专题E题 吴队长征婚 爆搜
    2015 UESTC 搜索专题D题 基爷的中位数 二分
    2015 UESTC 搜索专题C题 基爷与加法等式 爆搜DFS
    2015 UESTC 搜索专题B题 邱老师降临小行星 记忆化搜索
  • 原文地址:https://www.cnblogs.com/cqwo/p/15439109.html
Copyright © 2011-2022 走看看