ICode9

精准搜索请尝试: 精确搜索
首页 > 系统相关> 文章详细

c++ linux串口封装方案

2021-10-22 15:32:29  阅读:208  来源: 互联网

标签:opt int 串口 c++ SerialPort fd linux include


由于自己需要,封装了一个串口的方案,单例模式

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}

 

标签:opt,int,串口,c++,SerialPort,fd,linux,include
来源: https://www.cnblogs.com/cqwo/p/15439109.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有