HAL库串口HAL_LOCK的问题造成的串口半双工的解决

 一、原因分析

        由于HAL库串口中断机制的问题,一进入中断就会自动的把中断使能标志位关掉所以要在进入中断后调用HAL_UART_Receive_IT()开启下次接收;

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	if(huart->Instance==USART2)
	{
	    if(mUART2.TEMP == '$' && mUART2.FLG == 0)
		{
			mUART2.FLG = 1;
			Uart2_Len = 0;
		}
		if(mUART2.FLG)
		{
			mUART2.BUF[Uart2_Len] = mUART2.TEMP;
			++Uart2_Len;
		}
		if(Uart2_Len >7 && mUART2.BUF[Uart2_Len - 1] == 0x0a)
		{
			mUART2.LEN = Uart2_Len;
			Uart2_Len = 0;
			mUART2.FLG = 0;
			mUART2.RX_FLG = 1;
		}
	    HAL_UART_Receive_IT(&huart2,&mUART2.TEMP,RECLEN);
	}
}

       中断断掉的原因:HAL_UART_Receive_IT()函数没有执行成功导致的开启下次接收失败。执行失败原因是在主循环调用HAL_UART_Transmit_IT()或HAL_UART_Transmit()函数发送时,串口给锁住这时候进接收中断,由于串口给锁住所以调用HAL_LOCK时直接返回HAL_BUSY,导致接收中断开启失败,数据不在接收。可以看一下HAL_UART_Transmit_IT()底层的动作。

HAL库串口HAL_LOCK的问题造成的串口半双工的解决_第1张图片

HAL库串口HAL_LOCK的问题造成的串口半双工的解决_第2张图片

 二、处理方法

       使用HAL_UART_Transmit_IT()函数发送前关掉接收中断执行完后再开启接收中断即可避免,这里建议调用HAL_UART_Transmit_IT()函数,因为该函数是使用中断发送,函数里并没有执行发送内容只是开启发送中断配置要发送内容等,不会占用太多时序,所以短暂的关闭接收中断是允许的。每个发送函数加上判返回值如:while(HAL_UART_Transmit_IT() != HAL_OK),避免多次调用发送函数时上一次发送还没执行完成,huart->gState处于HAL_BUSY状态不是处于HAL_UART_STATE_READY状态造成的此次发送失败。

void Uart_Tx(UART_HandleTypeDef* huart, uint8_t* buf, uint16_t len)
{
    /***********等待上一次发送完成************/
	while (huart->gState == HAL_UART_STATE_BUSY_TX);
	
    /**********关闭总中断*************/
    if (huart->Instance == USART1)
	{
		HAL_NVIC_DisableIRQ(USART1_IRQn);
	}
	else if (huart->Instance == USART4 || huart->Instance == USART5)
	{
		HAL_NVIC_DisableIRQ(USART4_5_IRQn);
	}
	
    /**********开启发送(采用中断形式)*************/
	while (HAL_UART_Transmit_IT(huart, buf, len) != HAL_OK);
	
    /**********开启总中断*************/
	if (huart->Instance == USART1)
	{
		HAL_NVIC_EnableIRQ(USART1_IRQn);
	}
	else if (huart->Instance == USART4 || huart->Instance == USART5)
	{
		HAL_NVIC_EnableIRQ(USART4_5_IRQn);
	}
}


这样就可以解决串口锁的问题,并且不用去改动HAL库的底层函数。

你可能感兴趣的:(STM32)