STM32CubeIDE UART01-中断收发

一.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中配置USART串口需要进行以下步骤: 1. 打开STM32CubeIDE,并创建一个新的工程。 2. 在工程导航器中,右键单击"Core"文件夹,选择"Add Component",然后选择"USART"组件。这将在工程中添加USART相关的文件和代码。 3. 在"Pinout & Configuration"选项卡中,选择你要使用的USART引脚。 4. 在"Configuration"选项卡中,配置USART的参数,包括波特率、数据位数、停止位等等。可以根据具体需求进行配置。 5. 在代码中,使用HAL库函数来初始化和配置USART,例如使用`HAL_UART_Init()`函数来初始化USART,使用`HAL_UART_MspInit()`函数来配置USART引脚等等。 6. 在代码中,根据需求来实现USART的发送和接收功能。可以使用轮询方式或中断方式来发送和接收数据。如果使用中断方式,需要编写相应的中断回调函数,例如使用`HAL_UART_RxCpltCallback()`函数来处理接收完成中断。 在以上步骤中,引用提供了一些关键词,如"STM32F407VE"、"FreeRTOS"、"DMA"等,可以参考这些关键词在STM32CubeIDE中进行配置。同时,引用和引用提供了一些代码示例,可以参考这些示例来实现USART的配置和功能。 请注意,具体的配置和代码实现可能会因具体的硬件平台和需求而有所不同。建议查阅官方的文档和资料来获取更详细和准确的配置步骤。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [STM32F407VE+FreeRTOS+STM32CubeIDE+串口DMA+Freemodbus移植代码](https://download.csdn.net/download/qq_31272725/83163651)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* [STM32CubeIDE学习笔记——USART(三种收发方式,printf重定向,工程配置)](https://blog.csdn.net/Reasally/article/details/126751127)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值