/**
* @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外设在中断模式下的接收操作。下面是函数的具体步骤和操作:
pData
。Size
。Size
。使用该函数时,需要先创建一个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外设的接收操作,并配置相关的中断和参数。下面是函数的整体流程:
这个函数的代码结构可能看起来有些复杂,因为它需要根据不同的条件进行设置。具体而言,它根据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模式启用且接收数据量大于等于要处理的数据数量时,函数会选择适当的中断服务函数,并使能相关的中断,以便在接收缓冲区中有足够的数据时触发中断来处理数据。
相反,如果接收到的数据量小于要处理的数据数量,意味着接收缓冲区中的数据还不足以进行一次较大规模的数据处理。在这种情况下,函数会选择另一组中断服务函数,并使能相应的中断,以便在接收到每个数据时触发中断进行数据处理。
这样设计的目的是根据接收到的数据量的多少,选择合适的中断服务函数和中断触发时机,以提高系统的效率和性能。