STM32F103、HAL、シリアル ポートがアイドル割り込みを使用する場合、返されるデータは不完全であり、損失の状況の解決策

 

STM32F103でアイドル割り込みを使用するとデータロストが頻繁に発生しますが、これは接続環境の遅延により誤ってフラグビットがトリガーされてしまうためと思われます。

解決策は、DMA やアイドル割り込みを使用せずに、HAL ライブラリの代わりに LL ライブラリを直接使用することです。最も原始的な方法は、割り込みトリガーを直接受け取ることです。

タイマ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