- Life moves pretty fast. If you don’t stop and look around once in a while, you could miss it.
人生匆匆,若不偶爾停下來看看周圍,便會錯過許多風景。
一、串口數據不定長接收的實現
通常在裸機中,我們使用一個定時器來輔助串口實現串口數據不定長接收,也就是當串口接收數據時,定時器一直處於定時值(比如100ms),接收不斷的把數據放入緩衝區(通常可使用數組),當串口空閒時,定時器開始計時,當計時時間到,讀取緩衝區的數據即可,這樣就實現了數據的不定長接收。
而使用RTOS,可以使用消息隊列來作爲緩衝區,串口每次就收到數據就放入消息隊列中,然後別的對象(諸如線程),就可以讀取消息隊列裏的數據,從而實現串口數據的不定長接收。
二、具體實現
- 這裏使用串口2接收電腦發送的數據,然後將數據放入定義的消息隊列。
- 同時建立一個線程,當消息隊列有數據時,通過串口1發送消息隊列的數據到電腦,已驗證是否實現。
/* 消息隊列控制塊指針 */
static rt_mq_t uart2_mq = RT_NULL;
/* 打印存儲在消息隊列中的uart2發來的數據 */
static void uart2_mq_tid_entry(void *parameter)
{
rt_err_t uwRet = RT_EOK;
rt_uint8_t rx;
while(1)
{
uwRet = rt_mq_recv(uart2_mq,
&rx,
sizeof(rx),
RT_WAITING_FOREVER
);
if(RT_EOK == uwRet)
rt_kprintf("%c",rx);
}
}
static rt_uint8_t RxBuffer; // 串口接收的數據
static rt_thread_t uart2_mq_tid = RT_NULL;
int uart2_mq_rev_init(void)
{
uart2_mq = rt_mq_create("uart2_mq", //消息隊列名字
5, //消息的最大長度, bytes
20, //消息隊列的最大容量(個數)
RT_IPC_FLAG_FIFO //隊列模式 FIFO
);
if(uart2_mq != RT_NULL)
rt_kprintf("消息隊列uart2_mq創建成功\n\n");
/* 創建電機線程*/
uart2_mq_tid = rt_thread_create("uart2_mq_tid", // 線程名字
uart2_mq_tid_entry, // 線程入口函數
RT_NULL, // 線程入口參數
512, // 堆棧大小,
5, // 線程優先級
5); // 時間片長度
/* 如果獲得線程控制塊,啓動這個線程 */
if (uart2_mq_tid != RT_NULL)
rt_thread_startup(uart2_mq_tid);
return 0;
}
INIT_DEVICE_EXPORT(uart2_mq_rev_init); // 自動初始化
// 串口接收回調函數
// 注意初始化串口後,也要HAL_UART_Receive_IT(&huart2,&RxBuffer,1);才能開始接收數據
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if(huart->Instance == USART2)
{
rt_mq_send (uart2_mq, &RxBuffer, sizeof(RxBuffer));
HAL_UART_Receive_IT(&huart2,&RxBuffer,1); // 每次接收完後,必須使用這一句,且在別處容易卡死,
// 否則下次無法接收中斷
}
}
- 串口2發送的數據:
- 串口1接收的數據:
由數據可知,初步實現了數據的不定長接收。