在串口通讯中,空闲中断使用起来效率高了很多。首先把RX_LENGTH_MAX的值设成比你协议中最长帧略大一些。串口接收数据只需静静等待空闲中断的到来,来了我们就立即处理数据。
/*
初始化空闲中断和接收中断
*/
#define RX_LENGTH_MAX 20
__HAL_UART_ENABLE_IT(&huart1,UART_IT_IDLE);
HAL_UART_Receive_IT(&huart1,(uint8_t*)RxBuffer,RX_LENGTH_MAX);
/*
自己写的空闲中断回调函数,这个回调函数必须修改接收中断函数中才能触发
*/
void HAL_UART_IdleCpltCallback(UART_HandleTypeDef *huart)
{
huart->pRxBuffPtr = RxBuffer;
huart->RxXferCount = 0;
//上面两句话必须带上
RxFlag=1;
BSP_LED_Toggle(LED2);
}
/*
处理接收数据函数
*/
void DEAL_RECDATA_Loop(void)
{
uint16_t temp;
if(RxFlag==1)
{
RxFlag=0;
if(RxBuffer[0]==FRAME_HEAD)
{
Lenth_Rx=RxBuffer[1]+VDATA_LENTH;
if(RxBuffer[Lenth_Rx-1]==FRAME_END)
{
temp=GetCRC16(&RxBuffer[2],Lenth_Rx-VDATA_LENTH);
if(RxBuffer[Lenth_Rx-3]==(temp>>8) && RxBuffer[Lenth_Rx-2]==(uint8_t)temp)//CRC CHECK
{
if(RxBuffer[2]==FRAME_ADDR)//¼ì²éÊý¾Ý³¤¶È¼°É豸µØÖ·
{
switch(RxBuffer[3])
{
case FUNC1:
DEAL_OPERATE_FUNC1_Code(RxBuffer);
break;
case FUNC2:
DEAL_OPERATE_FUNC2_Code(RxBuffer);
break;
case FUNC3:
DEAL_OPERATE_FUNC3_Code(RxBuffer);
break;
}
}
else
{
ErrFlag=1;
}
}
else
{
ErrFlag=1;
}
}
else
{
ErrFlag=1;
}
}
else
{
ErrFlag=1;
}
// if(ErrFlag==1)
// {
// ErrFlag=0;
// #if log_uart
// printf("½ÓÊÕ´íÎó£¡\n");
// #endif
// }
//缓存清零,各种清零,准备下一次接收
BSP_LED_Off(LED2);
Lenth_Rx=0;
memset(&RxBuffer, 0, Lenth_Rx);
}
}
/*
在stm32f1xx_it.c文件中找到这个串口中断函数,添加如下代码
这样才能触发空闲中断
*/
void USART1_IRQHandler(void)
{
/* USER CODE BEGIN USART1_IRQn 0 */
/* USER CODE END USART1_IRQn 0 */
HAL_UART_IRQHandler(&huart1);
/* USER CODE BEGIN USART1_IRQn 1 */
if(__HAL_UART_GET_FLAG(&huart1,UART_FLAG_IDLE)!=RESET)
{
__HAL_UART_CLEAR_IDLEFLAG(&huart1);
HAL_UART_IdleCpltCallback(&huart1);
}
/* USER CODE END USART1_IRQn 1 */
}
空闲中断就是这么简单,可以接收有限长度内(取决于RX_LENGTH_MAX设置的值)任意长度的数据。