STM32F103,HAL,串口使用空闲中断时返回的数据不全,有丢失的情况的解决办法

在STM32F103中使用空闲中断的时候,经常会出现丢数据的情况,我猜测是因为连接环境中有延时,造成标志位误触发的情况。

解决思路,直接使用LL库代替HAL库,不用DMA也不用空闲中断,用最原始的办法就是直接接收中断触发的方式做。

使用定时器1,用于接收延时处理,达到不定长字符串接收的目的。

1,CUBEMX配置

不用DMA

中断勾选

定时器配置

2 部分工程代码

需要定义的变量

#define DEBUG 1

#define ERROR_LOG(x) if(DEBUG)printf("error_%d:%s.\r\n",__LINE__,x);	

#ifndef NULL
  #define  NULL ((void*)0)
#endif  

//用于包缓冲或者组包的Buf	
#define BUFFER_SIZE   256

int8_t 	S1recvEnd=0;
int8_t  S1TimeOut=0;
int16_t S1recvLen=0;


int8_t 	S2recvEnd=0;
int8_t  S2TimeOut=0;
int16_t S2recvLen=0;

int8_t 	S3recvEnd=0;
int8_t  S3TimeOut=0;
int16_t S3recvLen=0;


uint8_t mS1SendBuf[BUFFER_SIZE];
uint8_t mS1RecvBuf[BUFFER_SIZE];

uint8_t mS2SendBuf[BUFFER_SIZE];
uint8_t mS2RecvBuf[BUFFER_SIZE];

uint8_t mS3SendBuf[BUFFER_SIZE];
uint8_t mS3RecvBuf[BUFFER_SIZE];


void TestUsartRecvTask(void const * argument)
{
	//串口初始化  
    LL_USART_EnableIT_RXNE(USART1);
	LL_USART_EnableIT_PE(USART1);
	
	LL_USART_EnableIT_RXNE(USART2);
	LL_USART_EnableIT_PE(USART2);
	
	LL_USART_EnableIT_RXNE(USART3);
	LL_USART_EnableIT_PE(USART3);
	//定时器开中断
	HAL_TIM_Base_Start_IT(&htim1);
	
	//I2C_Init();
	while(1)
	{
		if(S1recvEnd)
		{
			S1recvEnd = 0;
			USART_SendData(USART1,mS1RecvBuf,S1recvLen);
			
			HAL_GPIO_WritePin(RS485_DE3_GPIO_Port,RS485_DE3_Pin,GPIO_PIN_SET);
			USART_SendData(USART3,mS1RecvBuf,S1recvLen);
			HAL_GPIO_WritePin(RS485_DE3_GPIO_Port,RS485_DE3_Pin,GPIO_PIN_RESET);
			
			HAL_GPIO_WritePin(RS485_DE2_GPIO_Port,RS485_DE2_Pin,GPIO_PIN_SET);
			USART_SendData(USART2,mS1RecvBuf,S1recvLen);
			HAL_GPIO_WritePin(RS485_DE2_GPIO_Port,RS485_DE2_Pin,GPIO_PIN_RESET);
			//HAL_UART_Transmit(&huart1,mS1RecvBuf,S1recvLen,0xFFFFFFFF);			
			//HAL_UART_Receive_DMA(&huart1,mS1RecvBuf,BUFFER_SIZE);	
			S1recvLen = 0;
		}
		if(S2recvEnd)
		{
			S2recvEnd = 0;
			USART_SendData(USART1,mS2RecvBuf,S2recvLen);
			//HAL_UART_Transmit(&huart1,mS2RecvBuf,S2recvLen,0xFFFFFFFF);			
			//HAL_UART_Receive_DMA(&huart2,mS2RecvBuf,BUFFER_SIZE);
			S2recvLen =0;
		}
		if(S3recvEnd)
		{
			S3recvEnd = 0;
			USART_SendData(USART1,mS3RecvBuf,S3recvLen);
			//HAL_UART_Transmit(&huart1,mS3RecvBuf,S3recvLen,0xFFFFFFFF);		
			//HAL_UART_Receive_DMA(&huart3,mS3RecvBuf,BUFFER_SIZE);	
			S3recvLen = 0;
		}
		ReadSensor();
		//HAL_Delay(1000);
	}
	//HAL_Delay(10);
}
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
	if(htim==&htim1)
	{
		static uint32_t timeLed=1000;
		static GPIO_PinState msate = GPIO_PIN_RESET;
		if(msate)msate = GPIO_PIN_RESET;
		else msate = GPIO_PIN_SET;
		if(timeLed--==0)
		{
			timeLed = 1000;
			HAL_GPIO_WritePin(LED_GPIO_Port,LED_Pin,msate);
		}
		
		if(S1TimeOut)S1TimeOut--;
		else if(S1recvLen>1)
		{
			S1recvEnd =1;
		}
		
		if(S2TimeOut)S2TimeOut--;
		else if(S2recvLen>1)
		{
			S2recvEnd =1;
		}
		if(S3TimeOut)S3TimeOut--;
		else if(S3recvLen>1)
		{
			S3recvEnd =1;
		}
		

		//HAL_UART_Transmit(&huart1,"heesl",5,20);		
		//printf("m\r\n");
	}
}


void USART_SendData(USART_TypeDef *uart,uint8_t *tmpData,int16_t len)
{
	int16_t iLen=0;
	
	for(iLen=0;iLen<len;iLen++)
	{
		LL_USART_TransmitData8(uart,tmpData[iLen]);//将数据准备好
		while(!LL_USART_IsActiveFlag_TC(uart));	//发送完数据再返回
	}
}
void USART1_IRQHandler(void)
{
  /* USER CODE BEGIN USART1_IRQn 0 */
	if(LL_USART_IsActiveFlag_RXNE(USART1))
	{
		S1TimeOut =UART_TIMEOUT;
		mS1RecvBuf[S1recvLen] = LL_USART_ReceiveData8(USART1);
		//LL_USART_TransmitData8(USART1,mS1RecvBuf[S1recvLen]);
		S1recvLen++;
		if(S1recvLen >=BUFFER_SIZE)S1recvLen=0;
		//LL_USART_TransmitData8(USART1,tmp);
	}
  /* USER CODE END USART1_IRQn 0 */
  /* USER CODE BEGIN USART1_IRQn 1 */
  /* USER CODE END USART1_IRQn 1 */
}

/**
* @brief This function handles USART2 global interrupt.
*/
void USART2_IRQHandler(void)
{
  /* USER CODE BEGIN USART2_IRQn 0 */
	if(LL_USART_IsActiveFlag_RXNE(USART2))
	{
		S2TimeOut =UART_TIMEOUT;
		if(S2recvLen >=BUFFER_SIZE)S2recvLen=0;
		mS2RecvBuf[S2recvLen++] = LL_USART_ReceiveData8(USART2);
		//LL_USART_TransmitData8(USART1,tmp);
	}
  /* USER CODE END USART2_IRQn 0 */
  /* USER CODE BEGIN USART2_IRQn 1 */

  /* USER CODE END USART2_IRQn 1 */
}

/**
* @brief This function handles USART3 global interrupt.
*/
void USART3_IRQHandler(void)
{
  /* USER CODE BEGIN USART3_IRQn 0 */
	if(LL_USART_IsActiveFlag_RXNE(USART3))
	{
		S3TimeOut =UART_TIMEOUT;
		if(S3recvLen >=BUFFER_SIZE)S3recvLen=0;
		mS3RecvBuf[S3recvLen++] = LL_USART_ReceiveData8(USART3);
		//LL_USART_TransmitData8(USART1,tmp);
	}
  /* USER CODE END USART3_IRQn 0 */
  /* USER CODE BEGIN USART3_IRQn 1 */

  /* USER CODE END USART3_IRQn 1 */
}

大致思路就是: 产生中断--》缓存-》定时器检查》超时接收完成。

完整工程

猜你喜欢

转载自blog.csdn.net/wfjdemmye/article/details/88564719