单片机学习小组
直播中

陈杰

7年用户 1384经验值
私信 关注

如何解决STM32串口发送中断试验问题?

如何解决STM32串口发送中断试验问题?

回帖(1)

毛微

2022-2-7 16:08:23
最近在学习STM32串口应用,对照51单片机的应用,在使用串口发送中断时发现了一些问题,经过试验找到了问题所在,以下为试验总结。


/**
  * @brief  USART GPIO 配置,工作参数配置
  * @param  无
  * @retval 无
  */
void USART_Config(void)
{       
        GPIO_InitTypeDef GPIO_InitStructure;
        USART_InitTypeDef USART_InitStructure;


        // 打开串口GPIO的时钟
         DEBUG_USART_GPIO_APBxClkCmd(DEBUG_USART_GPIO_CLK, ENABLE);
         
         // 打开串口外设的时钟
         DEBUG_USART_APBxClkCmd(DEBUG_USART_CLK, ENABLE);
        // 将USART Tx的GPIO配置为推挽复用模式
         GPIO_InitStructure.GPIO_Pin = DEBUG_USART_TX_GPIO_PIN;
         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
         GPIO_Init(DEBUG_USART_TX_GPIO_PORT, &GPIO_InitStructure);
        // 将USART Rx的GPIO配置为浮空输入模式
         GPIO_InitStructure.GPIO_Pin = DEBUG_USART_RX_GPIO_PIN;
         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
         GPIO_Init(DEBUG_USART_RX_GPIO_PORT, &GPIO_InitStructure);
         
         // 配置串口的工作参数
         // 配置波特率
         USART_InitStructure.USART_BaudRate = DEBUG_USART_BAUDRATE;
         // 配置 针数据字长
         USART_InitStructure.USART_WordLength = USART_WordLength_8b;
         // 配置停止位
         USART_InitStructure.USART_StopBits = USART_StopBits_1;
         // 配置校验位
         USART_InitStructure.USART_Parity = USART_Parity_No ;
         // 配置硬件流控制
         USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
         // 配置工作模式,收发一起
         USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
         // 完成串口的初始化配置
         USART_Init(DEBUG_USARTx, &USART_InitStructure);
         
         // 串口中断优先级配置
         NVIC_Configuration();
         
         // 使能串口接收中断
         USART_ITConfig(DEBUG_USARTx, USART_IT_RXNE, ENABLE);
        // // 使能串口发送中断
        // USART_ITConfig(DEBUG_USARTx, USART_IT_TC, ENABLE);
         
         // 使能串口
         USART_Cmd(DEBUG_USARTx, ENABLE);
        }




在初始化时,配置串口发送、接收引脚,配置串口参数,配置串口中断优先级。
1
切记:在初始化时不能使能串口发送中断
原因分析:


#define USART_IT_TC                          ((uint16_t)0x0626)


void USART_ITConfig(USART_TypeDef* USARTx, uint16_t USART_IT, FunctionalState NewState)
{
          uint32_t usartreg = 0x00, itpos = 0x00, itmask = 0x00;
          uint32_t usartxbase = 0x00;
          /* Check the parameters */
         assert_param(IS_USART_ALL_PERIPH(USARTx));
          assert_param(IS_USART_CONFIG_IT(USART_IT));
          assert_param(IS_FUNCTIONAL_STATE(NewState));
          /* The CTS interrupt is not available for UART4 and UART5 */
          if (USART_IT == USART_IT_CTS)
          {
                    assert_param(IS_USART_123_PERIPH(USARTx));
          }     
          usartxbase = (uint32_t)USARTx;
          /* Get the USART register index */
         usartreg = (((uint8_t)USART_IT) >> 0x05);
         /* Get the interrupt position */
          itpos = USART_IT & IT_Mask;
          itmask = (((uint32_t)0x01) << itpos);
          if (usartreg == 0x01) /* The IT is in CR1 register */
          {
            usartxbase += 0x0C;
          }
          else if (usartreg == 0x02) /* The IT is in CR2 register */
          {
            usartxbase += 0x10;
          }
          else /* The IT is in CR3 register */
          {
            usartxbase += 0x14;
          }
          if (NewState != DISABLE)
          {
            *(__IO uint32_t*)usartxbase  |= itmask;
          }
          else
          {
            *(__IO uint32_t*)usartxbase &= ~itmask;
          }
        }




从库函数配置USART_IT_TC串口发送中断可以看出,最终是配置CR1寄存器的TXEIE和TCIE,经过试验,如果初始化时使能TXEIE中断允许,则会导致程序运行时一直在进串口中断。
所以,如果使用串口发送中断,则需要先向DR寄存器填入数据,然后再使能串口发送中断。在串口中断中查询发送完成标志,发现发送完成后,就要关闭串口发送中断。


// 串口中断服务函数
void DEBUG_USART_IRQHandler(void)
{
         uint8_t ucTemp;
         if(USART_GetITStatus(DEBUG_USARTx,USART_IT_RXNE)!=RESET)
         {  
                  ucTemp = USART_ReceiveData(DEBUG_USARTx);
                  // 使能串口发送中断
                  USART_ITConfig(DEBUG_USARTx, USART_IT_TC, ENABLE);
                  USART_SendData(DEBUG_USARTx,ucTemp);
         }
         if(USART_GetFlagStatus(DEBUG_USARTx,USART_FLAG_TC)!=RESET)
         {
                 // 关闭串口发送完成中断
                USART_ITConfig(DEBUG_USARTx, USART_IT_TC, DISABLE);
                USART_ClearFlag(DEBUG_USARTx, USART_IT_TC);
        }
}
举报

更多回帖

发帖
×
20
完善资料,
赚取积分