STM32 HAL库函数——UART_Start_Receive_IT()详解

文章目录

  • 函数源代码
  • 函数用法详解
  • 函数逐行解释
  • 给出了注释也看不懂?

函数源代码

/**
  * @brief  Start Receive operation in interrupt mode.
  * @note   This function could be called by all HAL UART API providing reception in Interrupt mode.
  * @note   When calling this function, parameters validity is considered as already checked,
  *         i.e. Rx State, buffer address, ...
  *         UART Handle is assumed as Locked.
  * @param  huart UART handle.
  * @param  pData Pointer to data buffer (u8 or u16 data elements).
  * @param  Size  Amount of data elements (u8 or u16) to be received.
  * @retval HAL status
  */
HAL_StatusTypeDef UART_Start_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)
{
  huart->pRxBuffPtr  = pData;
  huart->RxXferSize  = Size;
  huart->RxXferCount = Size;
  huart->RxISR       = NULL;

  /* Computation of UART mask to apply to RDR register */
  UART_MASK_COMPUTATION(huart);

  huart->ErrorCode = HAL_UART_ERROR_NONE;
  huart->RxState = HAL_UART_STATE_BUSY_RX;

  /* Enable the UART Error Interrupt: (Frame error, noise error, overrun error) */
  ATOMIC_SET_BIT(huart->Instance->CR3, USART_CR3_EIE);

  /* Configure Rx interrupt processing */
  if ((huart->FifoMode == UART_FIFOMODE_ENABLE) && (Size >= huart->NbRxDataToProcess))
  {
    /* Set the Rx ISR function pointer according to the data word length */
    if ((huart->Init.WordLength == UART_WORDLENGTH_9B) && (huart->Init.Parity == UART_PARITY_NONE))
    {
      huart->RxISR = UART_RxISR_16BIT_FIFOEN;
    }
    else
    {
      huart->RxISR = UART_RxISR_8BIT_FIFOEN;
    }

    /* Enable the UART Parity Error interrupt and RX FIFO Threshold interrupt */
    if (huart->Init.Parity != UART_PARITY_NONE)
    {
      ATOMIC_SET_BIT(huart->Instance->CR1, USART_CR1_PEIE);
    }
    ATOMIC_SET_BIT(huart->Instance->CR3, USART_CR3_RXFTIE);
  }
  else
  {
    /* Set the Rx ISR function pointer according to the data word length */
    if ((huart->Init.WordLength == UART_WORDLENGTH_9B) && (huart->Init.Parity == UART_PARITY_NONE))
    {
      huart->RxISR = UART_RxISR_16BIT;
    }
    else
    {
      huart->RxISR = UART_RxISR_8BIT;
    }

    /* Enable the UART Parity Error interrupt and Data Register Not Empty interrupt */
    if (huart->Init.Parity != UART_PARITY_NONE)
    {
      ATOMIC_SET_BIT(huart->Instance->CR1, USART_CR1_PEIE | USART_CR1_RXNEIE_RXFNEIE);
    }
    else
    {
      ATOMIC_SET_BIT(huart->Instance->CR1, USART_CR1_RXNEIE_RXFNEIE);
    }
  }
  return HAL_OK;
}

函数用法详解

UART_Start_Receive_IT函数是一个自定义的函数,用于在中断模式下启动接收操作。下面是该函数的详细解释:

HAL_StatusTypeDef UART_Start_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)
  • huart:UART句柄,指向要使用的UART外设。
  • pData:指向数据缓冲区的指针,用于存储接收到的数据。
  • Size:要接收的数据元素(u8或u16)的数量。

返回值类型为HAL_StatusTypeDef,表示函数执行的状态。可能的返回值有:

  • HAL_OK:函数执行成功。

函数的作用是启动UART外设在中断模式下的接收操作。下面是函数的具体步骤和操作:

  1. 将接收数据缓冲区指针设置为传入的pData
  2. 将接收数据总大小设置为传入的Size
  3. 将接收数据剩余大小设置为传入的Size
  4. 将接收中断服务函数指针设置为NULL。
  5. 计算UART外设的掩码,用于RDR寄存器。
  6. 将错误码设置为无错误。
  7. 将接收状态设置为忙碌。
  8. 使能UART外设的错误中断(帧错误、噪声错误、溢出错误)。
  9. 检查是否启用了FIFO模式,并且接收数据的数量大于等于要处理的数据数量。
    • 如果满足条件,根据数据字长和奇偶校验设置接收中断服务函数指针,并使能奇偶校验错误中断和接收FIFO阈值中断。
    • 如果不满足条件,根据数据字长和奇偶校验设置接收中断服务函数指针,并使能奇偶校验错误中断和接收数据寄存器非空中断。
  10. 返回函数执行成功的状态。

使用该函数时,需要先创建一个UART句柄,并进行初始化配置(包括波特率、字长、奇偶校验等)。然后创建一个数据缓冲区,用于存储接收到的数据。最后调用UART_Start_Receive_IT函数,传入UART句柄、数据缓冲区指针和要接收的数据数量作为参数。函数会启动UART的接收操作,并在接收到数据时触发中断,通过中断服务函数进行数据处理。

函数逐行解释

HAL_StatusTypeDef UART_Start_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)
  • huart:UART句柄,指向要使用的UART外设。
  • pData:指向数据缓冲区的指针,用于存储接收到的数据。
  • Size:要接收的数据元素(u8或u16)的数量。

返回值类型为HAL_StatusTypeDef,表示函数执行的状态。可能的返回值有:

  • HAL_OK:函数执行成功。

下面是对每一行代码的详细注释:

huart->pRxBuffPtr  = pData;

将UART句柄中的接收数据缓冲区指针设置为传入的pData。

huart->RxXferSize  = Size;

将UART句柄中的接收数据总大小设置为传入的Size。

huart->RxXferCount = Size;

将UART句柄中的接收数据剩余大小设置为传入的Size。

huart->RxISR       = NULL;

将UART句柄中的接收中断服务函数指针设置为NULL。

UART_MASK_COMPUTATION(huart);

计算UART句柄中用于RDR寄存器的掩码。

huart->ErrorCode = HAL_UART_ERROR_NONE;

将UART句柄中的错误码设置为无错误。

huart->RxState = HAL_UART_STATE_BUSY_RX;

将UART句柄中的接收状态设置为忙碌。

ATOMIC_SET_BIT(huart->Instance->CR3, USART_CR3_EIE);

使能UART外设的错误中断(帧错误、噪声错误、溢出错误)。

if ((huart->FifoMode == UART_FIFOMODE_ENABLE) && (Size >= huart->NbRxDataToProcess))

检查UART句柄中的FIFO模式是否使能,并且接收数据的数量是否大于等于要处理的数据数量。

if ((huart->Init.WordLength == UART_WORDLENGTH_9B) && (huart->Init.Parity == UART_PARITY_NONE))

检查UART句柄中的数据字长是否为9位,并且奇偶校验是否为无。

huart->RxISR = UART_RxISR_16BIT_FIFOEN;

将UART句柄中的接收中断服务函数指针设置为处理16位数据的FIFO使能模式。

ATOMIC_SET_BIT(huart->Instance->CR1, USART_CR1_PEIE);

使能UART外设的奇偶校验错误中断。

ATOMIC_SET_BIT(huart->Instance->CR3, USART_CR3_RXFTIE);

使能UART外设的接收FIFO阈值中断。

else

如果不满足上述条件,则执行以下代码块。

if ((huart->Init.WordLength == UART_WORDLENGTH_9B) && (huart->Init.Parity == UART_PARITY_NONE))

检查UART句柄中的数据字长是否为9位,并且奇偶校验是否为无。

huart->RxISR = UART_RxISR_16BIT;

将UART句柄中的接收中断服务函数指针设置为处理16位数据的普通模式。

ATOMIC_SET_BIT(huart->Instance->CR1, USART_CR1_PEIE | USART_CR1_RXNEIE_RXFNEIE);

使能UART外设的奇偶校验错误中断和接收数据寄存器非空中断。

else

如果不满足上述条件,则执行以下代码块。

huart->RxISR = UART_RxISR_8BIT;

将UART句柄中的接收中断服务函数指针设置为处理8位数据的普通模式。

ATOMIC_SET_BIT(huart->Instance->CR1, USART_CR1_RXNEIE_RXFNEIE);

使能UART外设的接收数据寄存器非空中断。

return HAL_OK;

返回函数执行成功的状态。

给出了注释也看不懂?

你是不是有以下疑问?看看以下问题有没有你关心的

之前给出的逐行解释,虽然每一行我都知道是什么作用了,但是他们连在一起我看不懂,不知道为什么要那么写;

我理解你的困惑。让我们将每一行代码的作用连接起来,以便更好地理解函数的整体流程。

这个函数的目标是启动UART外设的接收操作,并配置相关的中断和参数。下面是函数的整体流程:

  1. 设置接收数据缓冲区指针、接收数据总大小、接收数据剩余大小和接收中断服务函数指针。
  2. 计算UART外设的掩码。
  3. 初始化错误码和接收状态。
  4. 使能UART外设的错误中断。
  5. 检查FIFO模式是否启用,并根据条件设置接收中断服务函数指针和相关中断使能。
  6. 如果FIFO模式未启用或数据量不足,则根据条件设置接收中断服务函数指针和相关中断使能。
  7. 返回函数执行成功的状态。

这个函数的代码结构可能看起来有些复杂,因为它需要根据不同的条件进行设置。具体而言,它根据FIFO模式、数据字长和奇偶校验等因素选择合适的中断服务函数,并使能相应的中断。这样设计的目的是为了适应不同的UART配置和需求。

为什么要计算UART外设的掩码?

计算UART外设的掩码的目的是为了在接收数据时使用。让我解释一下为什么需要进行掩码计算。

在UART通信中,接收数据时,我们需要读取UART外设的数据寄存器(RDR)来获取接收到的数据。数据寄存器中的数据位可能不止一个,而是一个数据位域(bit field)。为了提取其中的有效数据,我们需要使用一个掩码来屏蔽其他无关的位。

掩码是一个二进制值,其中每个位对应一个数据位域。通过将掩码与数据寄存器中的值进行按位与操作,可以将其他位清零,只保留我们关心的数据位。

UART_Start_Receive_IT函数中,通过调用UART_MASK_COMPUTATION宏来计算UART外设的掩码。这个宏根据UART的数据字长(Word Length)和奇偶校验(Parity)配置生成相应的掩码。掩码的生成方式可能因不同的UART外设而有所不同,因此需要进行计算。

计算掩码的目的是确保在接收数据时,我们只提取出有效的数据位,而忽略其他位,从而得到正确的数据值。

为什么要判断接收数据的数量是否大于等于要处理的数据数量?

if ((huart->FifoMode == UART_FIFOMODE_ENABLE) && (Size >= huart->NbRxDataToProcess))

这个条件判断主要是针对启用了FIFO(First-In-First-Out)模式的情况。FIFO模式允许UART外设在接收数据时使用一个缓冲区,以减少主处理器的负载。当接收到的数据量达到一定数量时,UART外设会触发中断,通知主处理器处理接收到的数据。

在这种情况下,如果接收到的数据量大于等于要处理的数据数量,意味着接收缓冲区中已经积累了足够的数据,可以进行一次较大规模的数据处理。这样可以减少中断的频率,提高系统的效率。

因此,当FIFO模式启用且接收数据量大于等于要处理的数据数量时,函数会选择适当的中断服务函数,并使能相关的中断,以便在接收缓冲区中有足够的数据时触发中断来处理数据。

相反,如果接收到的数据量小于要处理的数据数量,意味着接收缓冲区中的数据还不足以进行一次较大规模的数据处理。在这种情况下,函数会选择另一组中断服务函数,并使能相应的中断,以便在接收到每个数据时触发中断进行数据处理。

这样设计的目的是根据接收到的数据量的多少,选择合适的中断服务函数和中断触发时机,以提高系统的效率和性能。

你可能感兴趣的:(STM32,HAL库函数详解,stm32,linux,嵌入式硬件)