通常在裸机中,我们使用一个定时器来辅助串口实现串口数据不定长接收,也就是当串口接收数据时,定时器一直处于定时值(比如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发送的数据: