嵌入式DTU實際用到的數組隊列形式共享內存實現結果

#define __DTU_INNER_FUNC__
#ifdef __DTU_INNER_FUNC__
#define MAX_UART_SIZE       (32*1024)
// 用戶共享內存
kal_mutexid dtu_mutex;
#define MUTEX_BEGIN         kal_take_mutex(dtu_mutex)
#define MUTEX_END           kal_give_mutex(dtu_mutex)


#define MAX_SIZE            (1024*1024-1024*1024/56 -2*MAX_UART_SIZE)                           // 1MB-MAX_L_SIZE

struct arrQueue                             // 聲明隊列的頭和尾節點,數據存儲元素
{
    unsigned char       data[MAX_SIZE+1];   // 定義數組隊列元素,能容納MAX_SIZE字節
    unsigned int        front;              // 含有數據的第一個下標
    unsigned int        rear;               // 含有數據的最後一個元素下標,rear所在的元素不存數據
}queue;

void initQueue()
{
    memset(queue.data, '\0', sizeof(queue.data));
    queue.front = 0;
    queue.rear  = 0;
}


void enQueue(unsigned char *pElement, unsigned int *len)//向queue中存入長度爲len字節數據,len返回長度實際存入的長度
{
    // 如果rear在front前面一位,則表明緩衝區已經滿,無法存入數據
    // 當rear在最後一位,front在最前一位,也是沒有空間
    if ((queue.rear+1)%(MAX_SIZE+1) == queue.front)
    {
        *len = 0;
        return;
    }

    // 如果rear在front前面一位以上,則rear與front之間就是空閒區域,長度爲front-rear-1
    if (queue.rear+1<queue.front)
    {
        // 存入數據位len與剩餘空間較小者
        *len = *len <= (queue.front-queue.rear-1) ? *len : queue.front-queue.rear-1;
        
        memcpy(&queue.data[queue.rear], pElement, *len);
        queue.rear += *len;
    }
    else    // 如果 rear在front後面,或者相等時,並且有空間
    {
        // 剩餘空間大小爲 MAX_SIZE-(rear-front), 可寫入的數據位長度與剩餘空間較小者
        *len = *len <= (MAX_SIZE-(queue.rear-queue.front)) ? *len : MAX_SIZE-(queue.rear-queue.front);
        // 如果front爲0,則rear就在小於等於MAX_SIZE的位置,只需要隊列尾部保存數據
        if (queue.front==0)
        {
            memcpy(&queue.data[queue.rear], pElement, *len);
            queue.rear += *len;
        }
        else // 如果front不爲0,則 隊列尾保存了數據,隊列頭部有可能需要保存數據
        {
            // 如果尾部可以保存數據,則直接保存數據
            if ((MAX_SIZE+1-queue.rear) >= *len)
            {
                memcpy(&queue.data[queue.rear], pElement, *len);
                queue.rear = (queue.rear + *len)%(MAX_SIZE+1);
            }
            else // 如果尾部保存不了數據,頭部還需要保存數據,尾部保存的數據長度爲:MAX_SIZE+1-queue.rear
            {
                memcpy(&queue.data[queue.rear], pElement, MAX_SIZE+1-queue.rear);
                queue.rear = *len-(MAX_SIZE+1-queue.rear);
                memcpy(&queue.data[0], pElement+(*len-queue.rear), queue.rear);
            }
        }
    }
}

void deQueue(unsigned char *pElement, unsigned int *len)//向queue中取出長度爲len字節數據,len返回長度實際取出的長度
{
    // 如果爲空數據
    if ((*len==0) || (queue.rear==queue.front))
    {
        *len = 0;
        return;
    }

    // 如果 rear在front後面,則直接取出數據
    if (queue.rear > queue.front)
    {
        *len = *len <= (queue.rear-queue.front) ? *len : (queue.rear-queue.front);
        memcpy(pElement, &queue.data[queue.front], *len);
        queue.front += *len;
    }
    else    // 如果rear在front前面
    {
        // 隊列中數據長度爲 rear+(MAX_SIZE+1-front)
        *len = *len <= queue.rear+(MAX_SIZE+1-queue.front) ? *len : queue.rear+(MAX_SIZE+1-queue.front);
        
        // 如果尾部可以取出*len的數據則直接取,尾部數據大小爲MAX_SIZE+1-queue.front
        if (*len <= MAX_SIZE+1-queue.front)
        {
            memcpy(pElement, &queue.data[queue.front], *len);
            queue.front = (queue.front + *len) % (MAX_SIZE+1);
        }
        else    // 如果尾部取完,還需要取數據,則取頭部數據
        {
            memcpy(pElement, &queue.data[queue.front], (MAX_SIZE+1-queue.front));
            queue.front = *len-(MAX_SIZE+1-queue.front);
            memcpy(&pElement[*len-queue.front], &queue.data[0], queue.front);
        }
    }
}

unsigned int lenQueue()     // 隊列存了多少數據
{
    return (queue.rear+MAX_SIZE+1-queue.front)%(MAX_SIZE+1);
}


/////////////////////////////////長度數組隊列///////////////////////////////////
#define MAX_L_SIZE      1024*1024/56    //1024*1024/56+1
struct LQueue
{
    unsigned int data[MAX_L_SIZE];
    unsigned int front;
    unsigned int rear;
}lqueue;

void initLQueue()
{
    memset(lqueue.data, '\0', sizeof(lqueue.data));
    lqueue.front = 0;
    lqueue.rear = 0;
}

void enLQueue(unsigned int *len)    // 插入長度len, len不能爲0,插入正確len不改變,插入錯誤len爲0
{
    if ((lqueue.rear+1)%MAX_L_SIZE == lqueue.front)     // 隊列已滿
    {
        *len = 0;
    }
    else
    {
        lqueue.data[lqueue.rear] = *len;
        lqueue.rear = (lqueue.rear+1)%MAX_L_SIZE;
    }

}

void deLQueue(unsigned int *len)    // 返回一個長度len數值,len爲0則隊列爲空
{
    if (lqueue.rear == lqueue.front)    // 隊列爲空
    {
        *len = 0;
    }
    else
    {
        *len = lqueue.data[lqueue.front];
        lqueue.data[lqueue.front] = 0;  // 還原數據爲0
        lqueue.front = (lqueue.front+1)%MAX_L_SIZE;
    }
}

unsigned int lenLQueue()            // 獲取隊列存入多少len數值
{
    return (lqueue.rear+MAX_L_SIZE-lqueue.front)%MAX_L_SIZE;
}
/////////////////////////////////長度隊列///////////////////////////////////
#endif
#undef __DTU_INNER_FUNC__


// 緩衝區對外兩個接口函數
//////////////////////////////////////////////////////////////////////
// 寫入數據到緩衝區,若緩衝區存不下需要放入的數據,則刪除前面存入的數據
unsigned char dtu_buffer_add_data(const unsigned char *pbuf, unsigned int len)
{
    unsigned int len_t = 0;
    int i = 0;
    if ((pbuf==NULL) || (len==0))
    {
        return 0;
    }
    MUTEX_BEGIN;
    while (MAX_SIZE-lenQueue() < len)   // 如果緩衝區滿了,則刪除以前的的數據
    {
        deLQueue(&len_t);
        deQueue((unsigned char*)g_dtu_buffer, &len_t);
        trace_print("add_data deQueue【%d-%s】\r\n", len_t, g_dtu_buffer);
    }
    if (MAX_L_SIZE==lenLQueue()+1)      // 如果長度隊列滿了,則刪除一個長度隊列
    {
        deLQueue(&len_t);
        deQueue((unsigned char*)g_dtu_buffer, &len_t);
        trace_print("add_data deQueue【%d-%s】\r\n", len_t, g_dtu_buffer);
    }

    for (i=len-DTU_DATA_LEN; i>=0; i-=DTU_DATA_LEN) // i爲剩餘存儲一組數據的剩餘長度,如果小於0,表示不足一組數據,等於0表示剛好一組數據
    {
        len_t = DTU_DATA_LEN;
        trace_print("lenQueue=%d,%d,%d\r\n", lenQueue(), len_t, len-i-DTU_DATA_LEN);
        enLQueue(&len_t);
        enQueue((unsigned char*)&pbuf[len-i-DTU_DATA_LEN], &len_t);
    }
    // 存儲不足一組數據的數據
    len_t = len%DTU_DATA_LEN;
    if (len_t)
    {
        enLQueue(&len_t);
        enQueue((unsigned char*)&pbuf[len-len_t], &len_t);
        trace_print("lenQueue=%d,%d\r\n", lenQueue(), len_t);
    }
    MUTEX_END;
    return 1;
}

// 從緩衝區獲取內容
unsigned char dtu_buffer_get_data(unsigned char* pbuf, unsigned int* len)
{
    unsigned char result = 0;
    if (pbuf==NULL)
        return result;
    MUTEX_BEGIN;

    deLQueue((unsigned int*)len);
    deQueue((unsigned char*)pbuf, (unsigned int*)len);
    if (*len)   // 如果有數據,返回1
    {
        result = 1;
    }

    MUTEX_END;
    return result;
}

/////////////////////////////////////////////////////////////////////////
 
 
// 使用時需要先初始化
    ///////////////////////////// 初始化隊列
    initQueue();
    initLQueue();
    ///////////////////////////// 初始化隊列完畢

 

// 然後調用兩個函數進行存取數據,上面數組隊列對外接口只有兩個函數和初始化函數而已

// 存入數據
dtu_buffer_add_data((unsigned char*)uart_buffer2, len);     // 添加數據到發送隊列

// 取出數據
if (KAL_TRUE==dtu_buffer_get_data((unsigned char*)g_send_data_buffer, (unsigned int*)&len)) // 取數據
{
    g_send_data_buffer[len] = '\0';
    u8_heartbeat_times = 0;
}

 

 數據隊列測試原型見http://blog.csdn.net/zeroboundary/article/details/9295979

 
發佈了17 篇原創文章 · 獲贊 55 · 訪問量 27萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章