1、原理:
1、使能串口接收中断、定时器中断;
2、在串口第一次进入到中断后,使能定时器计时;
3、在串口每次进入中断后,清空定时器;
4、当定时器溢出时,判定数据接收完毕。
说明:以串口波特率设定9600为例,接收1byte数据时,进入中断的时间为1/(9600/8)≈800us,也即定时器会在计数到800us时清零,我这里以接收完数据后的10ms时间内未接收到数据作为判据,定时器在大于10ms时溢出进入中断,即当定时器溢出时,判断接收数据完成。
由于中断中处理项比较少,对于频繁接收外部数据的场景,程序能稳定运行。
由于是接收数据过程中无判断,接收完后可以对接收到的数据的每一字节进行判断纠错。
2、例程(关键代码):
//串口一中断函数
void USART1_IRQHandler(void)
{
if(__HAL_UART_GET_FLAG(&huart1,UART_FLAG_RXNE) != RESET)
{
__HAL_TIM_SET_COUNTER(&htim2, 0);//清零定时器2
if(USART_RX_STA1 == 0)//接收数据长度为0,首次进入中断
{
__HAL_TIM_CLEAR_FLAG(&htim2, TIM_FLAG_UPDATE);//清除定时器2更新标志
HAL_TIM_Base_Start_IT(&htim2);//开始计时
}
HAL_UART_Receive(&huart1, &USART1_RX_DATA[USART_RX_STA1], 1, 10);//接收数据
USART_RX_STA1++;
__HAL_UART_CLEAR_FLAG(&huart1,UART_FLAG_RXNE);//清串口读取标志位
}
}
//定时器中断处理
void TIM2_IRQHandler(void)
{
if(__HAL_TIM_GET_IT_SOURCE(&htim2, TIM_IT_UPDATE) != RESET)//定时器2溢出
{
WorkingState = 1;//接收完成标志
HAL_TIM_Base_Stop_IT(&htim2);//关闭定时器2
}
}