给大家分享一种usart接收不定长数据,并且防止数据溢出卡死等情况;
在这里需要引用到两个中断,接收数据非空中断(RXNE)&接收总线空闲中断(IDLE),废话不多说,直接上代码。
中断服务函数中数据处理:
u8 RxBuffer[30]; //接收缓冲区,长度自己定义
/**
* @brief This function handles USART1 global interrupt.
*/
void USART1_IRQHandler(void)
{
/* USER CODE BEGIN USART1_IRQn 0 */
static uint8_t USART_REC_LEN=0; //usart接收数据长度
uint8_t clr; //清除usart数据寄存器用
/* USER CODE END USART1_IRQn 0 */
HAL_UART_IRQHandler(&huart1);
/* USER CODE BEGIN USART1_IRQn 1 */
if(RESET != __HAL_UART_GET_FLAG(&huart1, UART_FLAG_RXNE))//当接收数据非空标志位置一,开始将数据放于缓冲区中
{
RxBuffer[ USART_REC_LEN++ ] = USART1->DR; //读数据
if( USART_REC_LEN >= 48) //防止缓冲区数据溢出使用
{
USART_REC_LEN = 0; //将缓冲区地址清零
}
}
if(RESET != __HAL_UART_GET_FLAG(&huart1, UART_FLAG_IDLE))
{
clr = USART1->SR;
clr = USART1->DR; //清除数据寄存器
USART1_REC_OK = 1; //接收完成标志置1
USART_REC_LEN = 0; //将缓冲区地址清零
}
/* USER CODE END USART1_IRQn 1 */
}
usart初始化完毕后:
__HAL_UART_ENABLE_IT(&huart1, UART_IT_RXNE); //使能usart1接收非空中断
__HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE); //使能usart1接收总线空闲中断
切记一定要打开这两个中断哟~
while循环中数据处理:
if( 1 == USART1_REC_OK ) //如果接收总线空闲中断来了,说明暂时无数据接收
{
USART1_REC_OK= 0; //清除标志位
data_process(RxBuffer); //处理缓冲区数据
memset(RxBuffer, 0, 30); //清空缓冲区
}
实测结果:
使用sscom将0~100多个字节数据按照1ms-nms定时发送,测试时长10min
,程序未出现卡死情况,缓冲区数据完整性正常。