UART通信之面向对象编程(OOP)

14 篇文章 1 订阅
4 篇文章 0 订阅

上一篇介绍了UART的简单通信实现,不太了解通信过程的可以先参考上一篇文章《最简单的一个UART通信实例》。上一篇的《最简单的一个UART通信实例》是面向过程编程,本编将介绍UART通信的面向对象编程。

1、抽象接口定义

#ifndef MYUART_HARDINTERFACE_H
#define MYUART_HARDINTERFACE_H

#include <fcntl.h>
#include <utils/threads.h>
#define INVALID_IO_TYPE -1

class HardInterface
{
private:
    /* data */
public:
    
    enum MCUIOTYPE { INVALIDIOTYPE = -1, EUARTIO, I2CIO };
    HardInterface(/* args */) : miotype(MCUIOTYPE::INVALIDIOTYPE), fd(INVALIDIOTYPE)
    {
        fd = init_dev();
    }
    virtual ~HardInterface(){}

    virtual int init_dev()
    {
        return INVALID_IO_TYPE;
    }
    virtual int txdata(unsigned char* txbuf, unsigned int txcount) = 0;//纯虚函数
    virtual int rxdata(unsigned char* rxbuf, unsigned int rxcount) = 0;//纯虚函数
    MCUIOTYPE miotype;
    int fd;    
};

#endif

2、HardInterface.h头文件里面主要定义了虚函数init_dev跟纯虚函数txdata、rxdata。接下来在UartInterface.h头文件里面定义类UartInterface实现HardInterface抽象类,这样类UartInterface就可以进行实例化了。

#ifndef MYUART_UARTINTERFACE_H
#define MYUART_UARTINTERFACE_H
#include <termios.h>
#include "HardInterface.h"

#define  MCUUARTPORT  "/dev/ttyLP3"
#define  BAUDRATEINDEXMAX 9
#define  BAUDRATEINDEX    8
#define  GET_BAUDRATEINDEX(index) ( (BAUDRATEINDEXMAX - 1) & index) 
#define TIMEOUT_SEC(buflen, baudrate)    ((buflen)*20/(baudrate) + 2)
#define TIMEOUT_USEC    0
//波特率数组
static const int speed_arr[] = { B300, B1200, B2400, B4800, B9600, B19200,
                                   B38400, B57600, B115200 };
//根据枚举钟不同的值设置不同的串口属性
enum UARTPROPERTI{ SERIAL_STOPBITS_ONE, SERIAL_STOPBITS_TWO, SERIAL_DATABITS_SEVEN, \
    SERIAL_DATABITS_EIGHT, SERIAL_HARDWARE_UNCTRL, SERIAL_HARDWARE_XONXOFF, \
    SERIAL_HARDWARE_CTRL, SERIAL_PARITY_NONE, SERIAL_PARITY_ODD, SERIAL_PARITY_EVEN, \
    SERIAL_PARITY_MARK, SERIAL_PARITY_SPACE };

static const int name_arr[] = { 300, 1200, 2400, 4800, 9600, 19200, 38400,
                               57600, 115200 };

class UartInterface : public HardInterface
{
private:
    bool uart_error;/* data */
public:
    UartInterface(/* args */)
    {
        init_dev();
    }
    ~UartInterface(){
        uart_close(this->fd);
    }
    int init_dev();//设备初始化
    int txdata(unsigned char* txbuf, unsigned int txcount);//向串口发送数据
    int rxdata(unsigned char* rxbuf, unsigned int rxcount);//接收来自串口端的数据
    int uart_sest_baudrate(int handle, int baudrateindex);//设置波特率
    //设置串口属性
    int uart_set_properties(int handle, unsigned char databits, unsigned char stopbits, \
        unsigned char parity, unsigned char flow_control);
    //关闭对应的文件描述符
    int uart_close(int handle);
};


#endif

3、接下来需要实现每个函数里面的具体内容,如下:

#include <errno.h>
#include <linux/fb.h>
#include <unistd.h>
#include "UartInterface.h"

//初始化设备
int UartInterface::init_dev()
{
    int ret = 0;
    this->uart_error = false;
    printf("UartInterface--> init dev start--\n");
    this->fd = open(MCUUARTPORT, O_RDWR | O_NDELAY | O_NOCTTY | O_NONBLOCK);
    if (-1 == this->fd)
    {
        printf("UartInterface--> open serial port %s fail %d--\n", MCUUARTPORT, this->fd);
        this->uart_error = true;
        return this->fd;
    }

    fcntl(fd, F_SETFL, 0);//设置文件状态标志值为0,阻塞模式
    //设置波特率
    ret = uart_sest_baudrate(this->fd, GET_BAUDRATEINDEX(BAUDRATEINDEX));
    if (ret == -1)
    {
         printf("UartInterface--> uart_sest_baudrate %s fail %d\n", MCUUARTPORT, ret);
         this->uart_error = true;
         return ret;
    }
    //串口属性配置
    ret = uart_set_properties(this->fd, SERIAL_DATABITS_EIGHT, SERIAL_STOPBITS_ONE, \
    SERIAL_PARITY_NONE, SERIAL_HARDWARE_UNCTRL);
    if (ret == -1)
    {
         printf("UartInterface--> uart_set_properties %s fail %d\n", MCUUARTPORT, ret);
         this->uart_error = true;
         return ret;
    }
    printf("UartInterface--> init dev end--\n");
    return 0;
}

//向串口发送数据
int UartInterface::txdata(unsigned char* txbuf, unsigned int txcount)
{
    unsigned char* write_data = txbuf;
    unsigned int total_len = 0;
    int len =0;
    unsigned int size = txcount;
    if ( this->fd <= 0)
    {
        printf("UartInterface-->txdata fd = %d litter zero\n", this->fd);
        return this->fd;
    }
    for (total_len = 0; total_len < size;)
    {
        len = write(this->fd, &write_data[total_len], size - total_len);
        if (len > 0)
        {
            total_len += len;
        }
        else if (len < 0)
        {
            if (total_len == 0)
            {
                tcflush(this->fd, TCOFLUSH);//清除正写入的数据,且不会发送至终端。
                return -1;
            }
            return total_len;
        }else
        {
            printf("UartInterface-->txdata len = %d \n", len);
            break;
        }
               
    }//for
    return 0;
}

//从串口读取数据
int UartInterface::rxdata(unsigned char* rxbuf, unsigned int rxcount)
{
    if (this->fd <= 0)
    {
        printf("UartInterface-->rxdata fd = %d \n", this->fd);
        return -1;
    }
    int len = read(this->fd, rxbuf, rxcount);
    if (len < 0)
    {
        printf("UartInterface-->rxdata len = %d \n", len);
        return -1;
    }
    return len;
    
}

//设置波特率
int UartInterface::uart_sest_baudrate(int handle, int baudrateindex)
{
    struct termios options;
    memset(&options, 0x00, sizeof(options));
    if (baudrateindex >= BAUDRATEINDEXMAX)
    {
        printf("UartInterface--> ot support BAUDRATEINDEXMAX %d", BAUDRATEINDEXMAX);
        return -1;
    }
    
    if (tcgetattr(handle, &options) != 0)
     {
        printf("UartInterface--> tcgetattr error\n");
        return -1;
    }
    tcflush(this->fd, TCIOFLUSH);//刷新输入输出缓冲区
    cfsetispeed(&options, speed_arr[baudrateindex]);//设置输入速度
    cfsetospeed(&options, speed_arr[baudrateindex]);//设置输出速度

    if (tcsetattr(handle, TCSANOW, &options)  != 0)//设置串口属性,TCSANOW:不等数据传输完毕就立即改变属性
    {
        printf("UartInterface--> tcsetattr \n");
        return -1;
    }
    
    tcflush(this->fd, TCIOFLUSH);//刷新输入输出缓冲区
    return 0;
    
}

//设置串口属性
int UartInterface::uart_set_properties(int handle, unsigned char databits, unsigned char stopbits, \
    unsigned char parity, unsigned char flow_control)
{
    struct termios options;
    if (this->fd <= 0)
    {
        printf("UartInterface--> fd litter zero \n");
        return -1;
    }
    memset(&options, 0x00, sizeof(options));
    if (tcgetattr(handle, &options) != 0)
    {
        printf("UartInterface--> tcgetattr error \n");
        return -1;
    }
    options.c_cflag |= (CLOCAL | CREAD);
    options.c_cflag &= ~CSIZE;

    switch (stopbits) 
    {
        case SERIAL_STOPBITS_ONE:
            options.c_cflag &= ~CSTOPB;
            break;
        case SERIAL_STOPBITS_TWO:
            options.c_cflag |= CSTOPB;
            break;
        default:
            return -1;
    }

    switch (databits)
    {
        case SERIAL_DATABITS_SEVEN:
            options.c_cflag |= CS7;
            break;
        case SERIAL_DATABITS_EIGHT:
            options.c_cflag |= CS8;
            break;
        default:
            return -1;
    }

    switch (flow_control) 
    {
        case SERIAL_HARDWARE_UNCTRL:
            options.c_cflag &= ~CRTSCTS;
            options.c_iflag &= ~(IXON | IXOFF | IXANY);
            break;
        case SERIAL_HARDWARE_XONXOFF:
            options.c_iflag |= IXON | IXOFF | IXANY;
            break;
        case SERIAL_HARDWARE_CTRL:
            options.c_cflag |= CRTSCTS;
            options.c_iflag &= ~(IXON | IXOFF | IXANY);
            break;
        default:
            return -1;
    }
    options.c_iflag &= IGNCR;

    switch (parity)
    {
        case SERIAL_PARITY_NONE:
            options.c_cflag &= ~PARENB;
            break;
        case SERIAL_PARITY_ODD:
            options.c_cflag |= PARENB;
            options.c_cflag |= PARODD;
            break;
        case SERIAL_PARITY_EVEN:
            options.c_cflag |= PARENB;
            options.c_cflag &= ~PARODD;
            break;
        case SERIAL_PARITY_MARK:
            options.c_cflag &= ~PARENB;
            options.c_cflag |= CSTOPB;
            break;
        case SERIAL_PARITY_SPACE:
            options.c_cflag &= ~PARENB;
            options.c_cflag &= ~CSTOPB;
            break;
        default:
            return -1;
    }

    options.c_oflag &= ~OPOST;
    options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
    options.c_cc[VMIN] = 0;
    options.c_cc[VTIME] = 0;//VTIME和VMIN都取0,即使读取不到任何数据,函数read也会立即返回
    tcflush(this->fd, TCIFLUSH);//刷新输入缓冲区

    if (0 != tcsetattr(handle, TCSANOW, &options)) //设置串口属性
    {
        printf("UartInterface--> tcsetattr error \n");
        return -1;
    }

    return 0; 
}

int UartInterface::uart_close(int handle)
{
    printf("UartInterface--> uart_close \n");
    close(handle);
    return 0;
}

到目前为止UART通信的面向对象编程就完了,接下来是要编写测试接口函数的测试类。

4、测试类

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "UartInterface.h"

//向串口写数据
static void mcu_reboot() {
    printf("mcu_reboot start\n");
    unsigned char write_data[] = { 1, 4, 2, 2, 1, 3, 133, 232, 0 };
    UartInterface *u = new UartInterface();
    int tx = u->txdata(write_data, 9);
    sleep(3);
    printf("mcu_reboot tx = %d\n", tx);
}
//向串口读数据
static void mcu_read_data() {
    printf("mcu_read_data start\n");
    static uint8_t recv_buf[512];
    UartInterface *u = new UartInterface();
    int j = 1;
    while(1){//由于不是每次都能读取到数据,所以要在循环中不断去读取
        int readLen = u->rxdata(recv_buf, 512);	
        if (readLen < 0)
        {
            printf("read failed\n");
            return ;
        }      
        if(readLen == -1 || readLen == 0)
        {
            continue;//读取不到数据,就结束本次循环,进入下一次循环进行重新读取
        }
        printf("readLen = %d\n", readLen);
        for(int i =0; i <readLen; i++)
        {
            printf("%02x ",recv_buf[i]);//打印从串口端读取到的数据			
        }
        j++;
        printf("\n");		
        usleep(10 * 1000);//睡眠10毫秒
        if (j > 10)break;//读取完10条数据就跳出while循环
    }
    printf("mcu_read_data tr\n");
}

int main(int argc, char **argv)
{
    printf("main start ---> \n");
    if (argc > 1)
    {       
        printf("argv[1] = %s\n", argv[1]);
        if (strncmp(argv[1], "w", 1) ==  0)
        {
            printf("main write data\n");
            mcu_reboot();//执行后mcu会重启
        }               
        else if (strncmp(argv[1], "r", 1) == 0)
        {
            printf("main read data\n");
            mcu_read_data();//执行后会打印接收到的数据
        }                      
     
        printf("\n");
    }
    printf("main start ---> \n");
    return 0;
}

5、运行结果如下:

代码参考:https://github.com/gunder1129/android-tool/tree/master/myuartOOP

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值