概述
一.UART中断概述
如figure 302所示,在stm32中UART有多个中断,下面来逐一说明这些中断及其应用。
一.发送中断
1.1TXE:发送数据寄存器为空状态标志位
当TDR寄存器的内容已转移到移位寄存器中时,此位由硬件置1。 如果USART_CR1寄存器中的TXEIE位= 1,则会产生一个中断。 通过写USART_DR寄存器将其清除。
0:数据未传输到移位寄存器
1:数据传输到移位寄存器)
注:在单缓冲区传输期间使用此位。TXE位总是通过写数据寄存器来清除。TXE位由硬件置1,它指示:
•数据已从TDR移至移位寄存器,并且数据传输已开始。
•TDR寄存器为空。
•可以将下一个数据写入USART_DR寄存器,而不会覆盖前一个数据。
如果TXEIE位置1,此标志将产生中断。
1.2.TC 传输完成状态标志位
传输完成中断,如果包含数据的帧的传输完成并且TXE被置位,则该位置1。 如果USART_CR1寄存器中的TCIE = 1,则产生一个中断。 通过软件序列(从USART_SR寄存器读取,然后写入USART_DR寄存器)将其清除。 TC位也可以通过向其写入“ 0”来清除。 建议仅对多缓冲区通信使用此清除序列。
0:传输未完成。
1:传输完成。
1.3.CTS
<待整理>
1.4.中断发送
通过STM32CubeIDE创建工程后,设置好UART及其它相关的配置后,在UART的中断发送过程中,HAL库的相互调用关系如下:HAL_UART_Transmit_IT ---》 HAL_UART_IRQHandler ---》 UART_Transmit_IT ---》 UART_EndTransmit_IT。
HAL_UART_Transmit_IT :
此函数会将要发送的数据赋值给UART结构体。然后使能UART_IT_TXE中断,进入中断处理函数。
HAL_StatusTypeDef HAL_UART_Transmit_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)
{
/*
*此函数会将要发送的数据赋值给UART结构体。然后使能UART_IT_TXE中断,进入中断处理函数;从发送时序图Fig 282可以看到
*在使能UART_IT_TXE中断后会马上触发一次UART_IT_TXE中断中断。TXE flag在初始状态就是保持在高电平。
*
**/
/* Check that a Tx process is not already ongoing */
if (huart->gState == HAL_UART_STATE_READY)
{
if ((pData == NULL) || (Size == 0U))
{
return HAL_ERROR;
}
/* Process Locked */
__HAL_LOCK(huart);
huart->pTxBuffPtr = pData;
huart->TxXferSize = Size;
huart->TxXferCount = Size;
huart->ErrorCode = HAL_UART_ERROR_NONE;
huart->gState = HAL_UART_STATE_BUSY_TX;
/* Process Unlocked */
__HAL_UNLOCK(huart);
/* Enable the UART Transmit data register empty Interrupt */
__HAL_UART_ENABLE_IT(huart, UART_IT_TXE);
return HAL_OK;
}
else
{
return HAL_BUSY;
}
}
HAL_UART_IRQHandler :
进入UART中断入口函数后,会调用中断处理函数HAL_UART_IRQHandler,在中断处理函数HAL_UART_IRQHandler中会根据中断标志位(TC TXE)不同调用不同的函数UART_Transmit_IT 和UART_EndTransmit_IT。其中UART_Transmit_IT在huart->gState == HAL_UART_STATE_BUSY_TX控制下循环将要发送的数据一帧一帧的写入串口的发送数据寄存器,并关闭TXE中断,使能TC中断。UART_EndTransmit_IT会关闭TC中断并调用用户自己的中断处理函数HAL_UART_TxCpltCallback。
void HAL_UART_IRQHandler(UART_HandleTypeDef *huart)
{
uint32_t isrflags = READ_REG(huart->Instance->SR);
uint32_t cr1its = READ_REG(huart->Instance->CR1);
uint32_t cr3its = READ_REG(huart->Instance->CR3);
uint32_t errorflags = 0x00U;
uint32_t dmarequest = 0x00U;
/* If no error occurs */
errorflags = (isrflags & (uint32_t)(USART_SR_PE | USART_SR_FE | USART_SR_ORE | USART_SR_NE));
if (errorflags == RESET)
{
/* UART in mode Receiver -------------------------------------------------*/
if (((isrflags & USART_SR_RXNE) != RESET) && ((cr1its & USART_CR1_RXNEIE) != RESET))
{
UART_Receive_IT(huart);
return;
}
}
/* If some errors occur */
if ((errorflags != RESET) && (((cr3its & USART_CR3_EIE) != RESET) || ((cr1its & (USART_CR1_RXNEIE | USART_CR1_PEIE)) != RESET)))
{
//error flag
//此处代码暂时不关注已删除
} /* End if some error occurs */
/* UART in mode Transmitter ------------------------------------------------*/
if (((isrflags & USART_SR_TXE) != RESET) && ((cr1its & USART_CR1_TXEIE) != RESET))
{
//中断发送,每次发生TXE中断,就调用一次UART_Transmit_IT。
UART_Transmit_IT(huart);
return;
}
/* UART in mode Transmitter end --------------------------------------------*/
if (((isrflags & USART_SR_TC) != RESET) && ((cr1its & USART_CR1_TCIE) != RESET))
{
//如果是发送TC中断,则调用UART_EndTransmit_IT。
UART_EndTransmit_IT(huart);
return;
}
UART_Transmit_IT :
huart->gState == HAL_UART_STATE_BUSY_TX软件定义的传输完成标志变量,如果特定的帧数据发送完成,会触发TC中断再次调用HAL_UART_IRQHandler,并在HAL_UART_IRQHandler中调用TC中断处理函数UART_EndTransmit_IT中复位HAL_UART_STATE_BUSY_TX。
static HAL_StatusTypeDef UART_Transmit_IT(UART_HandleTypeDef *huart)
{
uint16_t *tmp;
/* Check that a Tx process is ongoing */
if (huart->gState == HAL_UART_STATE_BUSY_TX)
{
if ((huart->Init.WordLength == UART_WORDLENGTH_9B) && (huart->Init.Parity == UART_PARITY_NONE))
{
//如果数据位是9位,则需要发送一个16位数
tmp = (uint16_t *) huart->pTxBuffPtr;
huart->Instance->DR = (uint16_t)(*tmp & (uint16_t)0x01FF);
huart->pTxBuffPtr += 2U;
}
else
{
//如果数据位是8位,则只需要发送一个8位数
huart->Instance->DR = (uint8_t)(*huart->pTxBuffPtr++ & (uint8_t)0x00FF);
}
if (--huart->TxXferCount == 0U)
{
/* Disable the UART Transmit Complete Interrupt */
__HAL_UART_DISABLE_IT(huart, UART_IT_TXE);
/* Enable the UART Transmit Complete Interrupt */
__HAL_UART_ENABLE_IT(huart, UART_IT_TC);
}
return HAL_OK;
}
else
{
return HAL_BUSY;
}
}
UART_EndTransmit_IT :
执行到这里标志串口发送完成,在UART_EndTransmit_IT中关闭TC中断,复位HAL_UART_STATE_BUSY_TX,然后调用发送完成的用户中断处理程序HAL_UART_TxCpltCallback。
static HAL_StatusTypeDef UART_EndTransmit_IT(UART_HandleTypeDef *huart)
{
/* Disable the UART Transmit Complete Interrupt */
__HAL_UART_DISABLE_IT(huart, UART_IT_TC);
/* Tx process is ended, restore huart->gState to Ready */
huart->gState = HAL_UART_STATE_READY;
#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
/*Call registered Tx complete callback*/
huart->TxCpltCallback(huart);
#else
/*Call legacy weak Tx complete callback*/
HAL_UART_TxCpltCallback(huart);
#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
return HAL_OK;
}
二.接收中断
https://blog.csdn.net/Hola_ya/article/details/81560204?utm_medium=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.control&dist_request_id=5e1deb95-ae63-46d4-8bf3-744ae8dc909d&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.control
https://blog.csdn.net/qq_29413829/article/details/63262321?utm_medium=distribute.pc_relevant_download.none-task-blog-baidujs-1.nonecase&depth_1-utm_source=distribute.pc_relevant_download.none-task-blog-baidujs-1.nonecase
2.1 IDLE:IDLE line detected
当检测到空闲线时,该位置1。 如果USART_CR1寄存器中的IDLEIE = 1,则产生一个中断。 它由软件序列清除(先读取USART_SR寄存器,再读取USART_DR寄存器)。
0:未检测到空闲线
1:检测到空闲线
注意:在RXNE位本身被置位之前(即出现新的空闲线),IDLE位将不会再次置位。
2.2 ORE:Overrun error(溢出错误)
当RXNE = 1时,当移位寄存器中当前接收的字准备好被传送到RDR寄存器中时,该位由硬件置1。 如果USART_CR1寄存器中的RXNEIE = 1,则产生一个中断。 它由软件序列清除(先读取USART_SR寄存器,再读取USART_DR寄存器)。
0:无溢出错误
1:检测到超限错误
注:置位时,RDR寄存器的内容不会丢失,但移位寄存器将被覆盖。 如果EIE位置1,则在进行多缓冲区通信时,在ORE标志上会产生一个中断。
2.3 RXNE : Read data register not empty
当RDR移位寄存器的内容已传输到USART_DR寄存器时,此位由硬件置1。 如果USART_CR1寄存器中的RXNEIE = 1,则产生一个中断。通过读取USART_DR寄存器将其清除。 也可以通过向其写入零来清除RXNE标志。 建议仅对多缓冲区通信使用此清除序列。
0:未收到数据
1:已准备好读取已接收的数据。
2.4 PE :Parity error
当在接收器模式下发生奇偶校验错误时,此位由硬件设置。 它由软件序列清除(先读取状态寄存器,然后读取USART_DR数据寄存器)。 在清除PE位之前,软件必须等待RXNE标志置1。
如果USART_CR1寄存器中的PEIE = 1,则会产生一个中断。
0:无奇偶校验错误
1:奇偶校验错误
2.5 LBD : LIN break detection flag
当检测到LIN中断时,由硬件将该位置1。 通过软件清除(将其写入0)。 如果USART_CR2寄存器中的LBDIE = 1,则会产生一个中断。
0:未检测到LIN Break
1:检测到LIN中断
注意:如果LBDIE = 1,则当LBD = 1时会产生一个中断。
2.6 NE/ORE/FE :
NE: Noise error flag
当在接收到的帧上检测到噪声时,该位由硬件设置。 它由软件序列清除(先读取USART_SR寄存器,再读取USART_DR寄存器)。
0:未检测到噪音
1:检测到噪音
注意:如果EIE位置1,则在多缓冲区通信的情况下,NE标志上会生成与本身产生中断中断的RXNE位同时出现的该位,不会产生中断。
ORE: Overrun error
当RXNE = 1时,当移位寄存器中当前接收的字准备好被传送到RDR寄存器中时,该位由硬件置1。 如果USART_CR1寄存器中的RXNEIE = 1,则产生一个中断。 它由软件序列清除(先读取USART_SR寄存器,再读取USART_DR寄存器)。
0:无溢出错误
1:检测到超限错误
注:置位时,RDR寄存器的内容不会丢失,但移位寄存器将被覆盖。 如果EIE位置1,则在进行多缓冲区通信时,在ORE标志上会产生一个中断。
FE: Framing error
当检测到去同步,过多的噪声或中断字符时,该位将由硬件置位。 它由软件序列清除(先读取USART_SR寄存器,再读取USART_DR寄存器)。
0:未检测到构图错误
1:检测到帧错误或中断字符
注:该位不会产生中断,因为它与本身会产生中断的RXNE位同时出现。 如果当前正在传输的字同时引起帧错误和溢出错误,则将传输该字,并且仅将ORE位置1。 如果EIE位置1,则在多缓冲区通信的情况下,FE标志上会产生一个中断。
EIE: Error interrupt enable
如果发生多缓冲器通信(DMAR = 1时),则在发生帧错误,溢出错误或噪声错误(USART_SR寄存器中的FE = 1或ORE = 1或NE = 1)时,需要错误中断允许位来使能中断生成。 USART_CR3寄存器)。
0:禁止中断
1:每当USART_CR3寄存器中的DMAR = 1和USART_SR寄存器中的FE = 1或ORE = 1或NE = 1时,都会产生一个中断。
DMAR :DMA enable receiver
该位由软件置位/复位
1:启用DMA模式进行接收
0:禁用DMA模式进行接收
该位不适用于UART5。
HAL_UART_Receive_IT : Enable the UART Parity Error ,Frame error, noise error, overrun error,UART Data Register not empty Interrupt.
HAL_StatusTypeDef HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)
{
/* Check that a Rx process is not already ongoing */
if (huart->RxState == HAL_UART_STATE_READY)
{
if ((pData == NULL) || (Size == 0U))
{
return HAL_ERROR;
}
/* Process Locked */
__HAL_LOCK(huart);
huart->pRxBuffPtr = pData;
huart->RxXferSize = Size;
huart->RxXferCount = Size;
huart->ErrorCode = HAL_UART_ERROR_NONE;
huart->RxState = HAL_UART_STATE_BUSY_RX;
/* Process Unlocked */
__HAL_UNLOCK(huart);
/* Enable the UART Parity Error Interrupt */
__HAL_UART_ENABLE_IT(huart, UART_IT_PE);
/* Enable the UART Error Interrupt: (Frame error, noise error, overrun error) */
__HAL_UART_ENABLE_IT(huart, UART_IT_ERR);
/* Enable the UART Data Register not empty Interrupt */
__HAL_UART_ENABLE_IT(huart, UART_IT_RXNE);
return HAL_OK;
}
else
{
return HAL_BUSY;
}
}
HAL_UART_IRQHandler :
void HAL_UART_IRQHandler(UART_HandleTypeDef *huart)
{
uint32_t isrflags = READ_REG(huart->Instance->SR);
uint32_t cr1its = READ_REG(huart->Instance->CR1);
uint32_t cr3its = READ_REG(huart->Instance->CR3);
uint32_t errorflags = 0x00U;
uint32_t dmarequest = 0x00U;
/* If no error occurs */
errorflags = (isrflags & (uint32_t)(USART_SR_PE | USART_SR_FE | USART_SR_ORE | USART_SR_NE));
if (errorflags == RESET)
{
/* UART in mode Receiver -------------------------------------------------*/
if (((isrflags & USART_SR_RXNE) != RESET) && ((cr1its & USART_CR1_RXNEIE) != RESET))
{
UART_Receive_IT(huart);
return;
}
}
/* If some errors occur */
/* UART in mode Transmitter ------------------------------------------------*/
/* UART in mode Transmitter end --------------------------------------------*/
}
UART_Receive_IT :
static HAL_StatusTypeDef UART_Receive_IT(UART_HandleTypeDef *huart)
{
uint8_t *pdata8bits;
uint16_t *pdata16bits;
/* Check that a Rx process is ongoing */
if (huart->RxState == HAL_UART_STATE_BUSY_RX)
{
if ((huart->Init.WordLength == UART_WORDLENGTH_9B) && (huart->Init.Parity == UART_PARITY_NONE))
{
pdata8bits = NULL;
pdata16bits = (uint16_t *) huart->pRxBuffPtr;
*pdata16bits = (uint16_t)(huart->Instance->DR & (uint16_t)0x01FF);
huart->pRxBuffPtr += 2U;
}
else
{
pdata8bits = (uint8_t *) huart->pRxBuffPtr;
pdata16bits = NULL;
if ((huart->Init.WordLength == UART_WORDLENGTH_9B) || ((huart->Init.WordLength == UART_WORDLENGTH_8B) && (huart->Init.Parity == UART_PARITY_NONE)))
{
*pdata8bits = (uint8_t)(huart->Instance->DR & (uint8_t)0x00FF);
}
else
{
*pdata8bits = (uint8_t)(huart->Instance->DR & (uint8_t)0x007F);
}
huart->pRxBuffPtr += 1U;
}
if (--huart->RxXferCount == 0U)
{
/* Disable the UART Data Register not empty Interrupt */
__HAL_UART_DISABLE_IT(huart, UART_IT_RXNE);
/* Disable the UART Parity Error Interrupt */
__HAL_UART_DISABLE_IT(huart, UART_IT_PE);
/* Disable the UART Error Interrupt: (Frame error, noise error, overrun error) */
__HAL_UART_DISABLE_IT(huart, UART_IT_ERR);
/* Rx process is completed, restore huart->RxState to Ready */
huart->RxState = HAL_UART_STATE_READY;
#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
/*Call registered Rx complete callback*/
huart->RxCpltCallback(huart);
#else
/*Call legacy weak Rx complete callback*/
HAL_UART_RxCpltCallback(huart);
#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
return HAL_OK;
}
return HAL_OK;
}
else
{
return HAL_BUSY;
}
}
最后
以上就是细心项链为你收集整理的STM32CubeIDE UART01-中断收发一.UART中断概述的全部内容,希望文章能够帮你解决STM32CubeIDE UART01-中断收发一.UART中断概述所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复