#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