STM32中发送中断标志位

本文详细介绍了STM32串口中断的配置方法及其实现过程,包括USART寄存器的理解、GPIO初始化、USART初始化等步骤,并给出了具体的代码实例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

数据手册中对此标志位的解释:

Bit 7 TXE : Transmit data register empty
This bit is set by hardware when the content of the TDR register has been transferred into 
the shift register. An interrupt is generated if  the TXEIE bit =1 in the USART_CR1 register. It 
is cleared by a write to the USART_DR register.
0: Data is not transferred to the shift register
1: Data is transferred to the shift register)

仔细看看这段话。TXE在数据寄存器为空的时候就会置一,也就是说你的数据发送完成之后,如果没有数据发送了,这一位就是置一的。既然是置一的,那么就会发生中断。所以要关一下中断,要发送数据的时候可以再开启中断。

所以要使用STM32串口发送中断,基本代码如下:

  1. <font color="rgb(85, 85, 85)"><font face="verdana,"><span style="background-color: white;">void usart_Configuration(void)
  2. {
  3.     USART_InitTypeDef USART_InitStruct;
  4.     GPIO_InitTypeDef GPIO_InitStruct;

  5.     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO,ENABLE);
  6.     RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2 ,ENABLE);
  7.     RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 ,ENABLE);

  8.     GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
  9.     GPIO_InitStruct.GPIO_Pin = GPIO_Pin_2;
  10.     GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
  11.     GPIO_Init(GPIOA, &GPIO_InitStruct);
  12.     GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;
  13.     GPIO_InitStruct.GPIO_Pin = GPIO_Pin_3;    
  14.     GPIO_Init(GPIOA, &GPIO_InitStruct);

  15.     GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
  16.     GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9;
  17.     GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
  18.     GPIO_Init(GPIOA, &GPIO_InitStruct);
  19.     GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;
  20.     GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10;    
  21.     GPIO_Init(GPIOA, &GPIO_InitStruct);

  22.     GPIO_InitStruct.GPIO_Pin =  GPIO_Pin_4;                     //485 dir pin
  23.     GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
  24.     GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP; 
  25.     GPIO_Init(GPIOA ,&GPIO_InitStruct);

  26.     USART_InitStruct.USART_BaudRate = 9600;
  27.     USART_InitStruct.USART_StopBits = USART_StopBits_1;
  28.     USART_InitStruct.USART_WordLength = USART_WordLength_8b;
  29.     USART_InitStruct.USART_Parity = USART_Parity_No;
  30.     USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
  31.     USART_InitStruct.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
  32.     
  33.     USART_Init(USART2, &USART_InitStruct);
  34.     USART_ITConfig(USART2,USART_IT_RXNE,ENABLE);
  35.     USART_ClearFlag(USART2,USART_IT_TC);             
  36.     USART_Cmd(USART2, ENABLE);
  37.     RS485_DIR_0; 

  38.     USART_InitStruct.USART_BaudRate = 115200;
  39.     USART_Init(USART1, &USART_InitStruct);
  40.     USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);
  41.     USART_ClearFlag(USART1,USART_IT_TC);        
  42.     USART_Cmd(USART1, ENABLE);
  43. }</span></font></font>
复制代码

上面配置了USART1和USART2(个人项目需要),并设置了串口1和串口2接收中断(USART_ITConfig(USART1,USART_IT_RXNE,ENABLE)。


    启动串口1数据发送的代码:

  1. <font color="rgb(85, 85, 85)"><font face="verdana,"><span style="background-color: white;">void Uart1_RS232_SendString(unsigned char *buf,unsigned char len)
  2. {
  3.     if(len >= MAX_TX1_BUFSIZE)
  4.         len = MAX_TX1_BUFSIZE;

  5.     memcpy(uart1_tx_buf,buf,len);
  6.     uart1_tx_SendLength = len;

  7.     USART_ITConfig(USART1,USART_IT_TXE,ENABLE);    //这里立即启动了发送中断
  8. }</span></font></font>
复制代码
    串口1的中断函数:
  1. void USART1_IRQHandler(void)
  2. {
  3.     if(USART_GetITStatus(USART1,USART_IT_RXNE) != RESET)           //USART1接收中断
  4.     {    
  5.         uart1_rx_buf[uart1_rx_RecvIndex] = USART1->DR;
  6.         uart1_rx_RecvIndex++;
  7.         if(uart1_rx_RecvIndex > 3)
  8.         {
  9.              uart1_rx_RecvIndex = 4;
  10.              Uart1_RS232_SendString(uart1_rx_buf,4);
  11.         }
  12.         //uart1_rx_RecvOvertimeCnt = 0;
  13.         //uart1_rx_RecvFlag = 1;
  14.     }

  15.     if(USART_GetITStatus(USART1,USART_IT_TXE) != RESET)               //USART1发送中断
  16.     {
  17.         if(uart1_tx_SendIndex < uart1_tx_SendLength)              
  18.         {
  19.             USART1->DR = uart1_tx_buf[uart1_tx_SendIndex]&0x01FF;
  20.             uart1_tx_SendIndex++;
  21.         }
  22.         else
  23.         {
  24.             uart1_tx_SendIndex = 0;            
  25.             USART_ITConfig(USART1, USART_IT_TXE, DISABLE);         //关闭发送中断           
  26.         }
  27.     }
  28. }
复制代码
结合代码和上面数据手册标志位的解释,就很容易看懂了。
### 如何在 STM32 中清除 USART 或 UART 中断标志位 对于 STM32 的 USART 和 UART 设备,在处理中断时,某些状态标志需要手动清除。具体到中断标志位的清除方法取决于具体的标志位。 #### 清除 TXE (传输数据寄存器空) 中断标志位 TXE 是只读标志位,当 TDR 寄存器为空时自动置位,并不需要显式的软件清除操作[^1]。因此无需编写额外代码来清除此标志位。 #### 清除 TC (传输完成) 中断标志位 TC 标志位会在 DR 寄存器中的最后一位被移出后设置。为了清除此标志位,可以调用 HAL 库函数 `HAL_UART_Transmit` 或者直接写入新的数据到发送缓冲区,这会重置该标志位。如果采用轮询方式等待传输结束,则可以通过如下所示的方式实现: ```c for(i=0; i<Num; i++) { USART_SendData(USARTx, Array[i]); while(USART_GetFlagStatus(USARTx, USART_FLAG_TC) == RESET); } ``` 这段代码通过循环检测 TC 标志直到其变为 SET 来确认每次字符已经成功发出并自动清除 TC 标志[^3]。 另外一种更推荐的做法是利用 HAL 库提供的接口来进行更加优雅的操作: ```c // 使用 HAL 库进行单字节发送并等待完成 HAL_StatusTypeDef status; status = HAL_UART_Transmit(&huart1, &data, 1, HAL_MAX_DELAY); if(status != HAL_OK){ // 错误处理逻辑... } // 如果启用了中断模式下的多字节数组发送 uint8_t buffer[] = "Hello"; HAL_UART_Transmit_IT(&huart1, buffer, sizeof(buffer)); ``` 以上例子展示了如何使用 HAL 库简化编程流程的同时也隐含地解决了 TC 标志位管理的问题[^2]。 需要注意的是,不同的 STM32 系列可能有不同的行为细节差异,请查阅对应的数据手册获取最准确的信息。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值