1. 程式人生 > >Linux/Android系統開發 串列埠驅動原始碼,FIFO模式

Linux/Android系統開發 串列埠驅動原始碼,FIFO模式

該驅動適用於採用linux和android系統平臺的C/C++串列埠開發。

FIFO傳送模式:建立資料傳送FIFO佇列,在多工資料傳送情境下,既能保證資料傳送任務能夠得到執行,又可解決資料傳送衝突問題。

select接收資料:有效監聽串列埠接收資料,提高執行效率,減少出錯概率。

原始碼如下:

uart.h

//
// Created by taxiang&xuezi on 2018/4/2.
//

#ifndef NDKAPPECG_UART_H
#define NDKAPPECG_UART_H
#include "typedef.h"

#ifdef  UART_GLOBALS
#define UART_EXT
#else
#define UART_EXT extern
#endif

#define UART_DBG   1

#define UART_TX_EVENT_FIFO    (32)
#define UART_BUF_SIZE         (1024)

enum UART_EVENT_SET{
    UART_EVENT_IDLE = 0,
    //event
    UART_EVENT_VERION,
    UART_EVENT_DATA_START,
    UART_EVENT_DATA_STOP,
    UART_EVENT_DEFAULT,
};

struct S_UART_TX_EVENT_SET{
    s32 fifo[UART_TX_EVENT_FIFO];
    s32 head;
    s32 tail;
};

struct S_UART_RX {
    s32 fd;
    u8  buf[UART_BUF_SIZE];
    s32 len;
};

struct S_UART_TX {
    s32 fd;
    u8  buf[UART_BUF_SIZE];
    s32 len;
};

UART_EXT struct S_UART_RX s_uart3_rx;
UART_EXT struct S_UART_TX s_uart3_tx;
UART_EXT struct S_UART_TX_EVENT_SET s_uart_tx_event;

UART_EXT s32 uart_insert_tx_event(int txevent);
UART_EXT s32 uart_tx_task(struct S_UART_TX *uart_ptr);
UART_EXT s32 uart_rx_task(s32 fd,s32 recv_len,s8 *recv_data);
#endif //NDKAPPECG_UART_H

uart.c/uart.cpp

//
// Created by taxiang&xuezi on 2018/4/2.
//

#define UART_GLOBALS
#include "includes.h"

#ifdef UART_DBG
#define UART_PRINT0(X) printf(X);
#define UART_PRINT1(X,A)  printf (X,A);
#define UART_PRINT2(X,A,B)  printf (X,A,B);
#define UART_PRINT3(X,A,B,C)  printf (X,A,B,C);
#else
#define UART_PRINT0(X)
#define UART_PRINT1(X,A)
#define UART_PRINT2(X,A,B)
#define UART_PRINT3(X,A,B,C)
#endif

/*******************************************************************************
* 函式名稱: s32 uart_insert_tx_event(s32 tx_event)
* 函式功能: 串列埠添加發送事件到fifo
* 輸入引數:
* 輸出引數:
* 返回值  :
*******************************************************************************/
s32 uart_insert_tx_event(s32 tx_event)
{
    s_uart_tx_event.fifo[s_uart_tx_event.head] = tx_event;
    s_uart_tx_event.head++;

    if (s_uart_tx_event.head >= UART_TX_EVENT_FIFO) {
        s_uart_tx_event.head = 0;
    }
    return 0;
}

/*******************************************************************************
* 函式名稱: s32 uart_tx_task(struct S_UART_TX *uart_ptr)
* 函式功能: 串列埠fifo傳送任務
* 輸入引數:
* 輸出引數:
* 返回值  :
*******************************************************************************/
s32 uart_tx_task(struct S_UART_TX *uart_ptr)
{
    if(s_uart_tx_event.head == s_uart_tx_event.tail){
        return 1;
    }

    switch(s_uart_tx_event.fifo[s_uart_tx_event.tail]){
        case UART_EVENT_VERION:
            sprintf((char*)uart_ptr->buf, "Verion0.0.1\n");
            uart_ptr->len = strlen((char*)uart_ptr->buf);
            break;
        case UART_EVENT_DATA_START:
            sprintf((char*)uart_ptr->buf, "data_start");
            uart_ptr->len = strlen((char*)uart_ptr->buf);
            run_log("uart tx:%s",uart_ptr->buf);
            break;
        case UART_EVENT_DATA_STOP:
            sprintf((char*)uart_ptr->buf, "data_stop");
            uart_ptr->len = strlen((char*)uart_ptr->buf);
            run_log("uart tx:%s",uart_ptr->buf);
            break;
        default:
            break;
    }

    s_uart_tx_event.fifo[s_uart_tx_event.tail] = UART_EVENT_IDLE;
    s_uart_tx_event.tail++;
    if(s_uart_tx_event.tail >= UART_TX_EVENT_FIFO) {
        s_uart_tx_event.tail = 0;
    }

    if(uart_ptr->len != 0) {
        int write_len = write(uart_ptr->fd,uart_ptr->buf,uart_ptr->len);
        if(write_len == uart_ptr->len){
            run_log("uart send done");
            return 0;
        }else if(write_len <= 0){
            err_log("uart send failed");
            return -1;
        }
    }

    return 0;
}
/*******************************************************************************
* 函式名稱: s32 uart_rx_task(s32 fd,s32 recv_len,s8 *recv_data)
* 函式功能:
* 輸入引數:
* 輸出引數:
* 返回值  :
***************************************************************s****************/
s32 uart_rx_task(s32 fd,s32 recv_len,s8 *recv_data)
{
    s8 in_buf[recv_len];
    s8 buf[recv_len];

    memset(in_buf,'\0',recv_len);
    memset(buf,'\0',recv_len);

    fd_set read_set;
    struct timeval tv;
    s32 max_fd = 0;
    s32 tmp_len = 0;
    s32 ret_val = 0;
    s32 read_size;

    do{
        FD_ZERO(&read_set);
        if(fd >= 0){
            FD_SET(fd,&read_set);
        }

        max_fd = fd + 1;
        tv.tv_sec = 0;
        tv.tv_usec = 300000;
        do{
            ret_val = select(max_fd,&read_set,0,0,&tv);
        }while((ret_val == -1) && (errno == EINTR));

        if(ret_val == -1){
            run_log("select(2)");
        }else if(ret_val == 0){//timeout
            fd = -1;
        }

        if((fd>=0) && FD_ISSET(fd,&read_set)){
            read_size = read(fd,buf,(recv_len-tmp_len));
            tmp_len += read_size;
            if(read_size == -1){
                fd = -1;
            }

            if(read_size > 0){
                buf[(read_size+1)] = '\0';
                strcat(in_buf,buf);
                memset(buf,0x00,recv_len);
            }else{
                fd = -1;
            }
        }
    }while(fd >= 0);

    memcpy(recv_data,in_buf,tmp_len);

    return tmp_len;
}