【轉】發送串口中斷


我將其改為真正的中斷發送。
步驟一:初始化GPIO
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;         //LED1-PC10
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure);
 
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;          //USART1 TX
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;    //復用推挽輸出
GPIO_Init(GPIOA, &GPIO_InitStructure);          //A端口
 
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;             //USART1 RX
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;   //復用開漏輸入
GPIO_Init(GPIOA, &GPIO_InitStructure);               //A端口
12345678910111213
步驟二:開時鍾
/* Enable USART1, GPIOA, GPIOD and AFIO clocks */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOC
                         | RCC_APB2Periph_AFIO, ENABLE);
123
在此說明,不用設置RCC_APB2Periph_AFIO也是可以的,也就是在此沒有使用復用功能。這兩個步驟與查詢方式是一樣的。
步驟三:初始化USART1
USART_InitStructure.USART_BaudRate = 9600;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_2;
USART_InitStructure.USART_Parity = USART_Parity_No;      //設置奇校驗時,通信出現錯誤
USART_InitStructure.USART_HardwareFlowControl=USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
 /* Configure the USART1 */
USART_Init(USART1, &USART_InitStructure);
 /* Enable the USART Transmoit interrupt: this interrupt is generated when the
USART1 transmit data register is empty */
USART_ITConfig(USART1, USART_IT_TXE, ENABLE);
 /* Enable the USART Receive interrupt: this interrupt is generated when the
  USART1 receive data register is not empty */
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
 /* Enable USART1 */
USART_Cmd(USART1, ENABLE);
12345678910111213141516
在這里要使能USART1的外設中斷,如USART_ITConfig(USART1, USART_IT_TXE, ENABLE);這就是使能發送中斷,但發送寄存器空時能產生中斷。
步驟四:編寫中斷函數
#define TxBufferSize1   (countof(TxBuffer1) - 1)
#define RxBufferSize1   (countof(TxBuffer1) - 1)
#define countof(a)   (sizeof(a) / sizeof(*(a)))      //表示數組a中元素的個數
 
uint8_t TxBuffer1[] = "USART Interrupt Example: This is USART1 DEMO";
uint8_t RxBuffer1[RxBufferSize1],rec_f;
__IO uint8_t TxCounter1 = 0x00;
__IO uint8_t RxCounter1 = 0x00;
uint8_t NbrOfDataToTransfer1 = TxBufferSize1;
uint8_t NbrOfDataToRead1 = RxBufferSize1;
 
 
/*串口中斷服務程序*/
void USART1_IRQHandler(void)
{
  unsigned int i;
  /*接收中斷*/
  if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
  {  
    /* Read one byte from the receive data register */
    RxBuffer1[RxCounter1++] = USART_ReceiveData(USART1);
    if(RxCounter1 == NbrOfDataToRead1)  //接收數據達到需要長度,則將數據復制到發送數組中,並置標志
    {                    
      /* Disable the USART1 Receive interrupt */
      //USART_ITConfig(USART1, USART_IT_RXNE, DISABLE);
        for(i=0; i< RxCounter1; i++) TxBuffer1[i]  = RxBuffer1[i];
        rec_f=1;
        RxCounter1=0;
        TxCounter1=0;
        USART_ITConfig(USART1, USART_IT_TXE, ENABLE);  //打開發送中斷,這句是關鍵
    }
  }
  /*發送中斷*/
  if(USART_GetITStatus(USART1, USART_IT_TXE) != RESET)
  { 
 
    USART_SendData(USART1, TxBuffer1[TxCounter1++]);
 
    if(TxCounter1 == NbrOfDataToTransfer1)//發送數據完成
    {  
      USART_ITConfig(USART1, USART_IT_TXE, DISABLE); //關閉發送中斷
    }  
  }  
}
1234567891011121314151617181920212223242526272829303132333435363738394041424344
至此程序就結束了。
我們就會有個疑問,main()只包括前三個步驟的初始化和一個死循環,那么中斷又是如何觸發的呢,main()的結構如下:
int main(void)
{
 /* System Clocks Configuration */
 RCC_Configuration();
 /* NVIC configuration */
 NVIC_Configuration();
 /* Configure the GPIO ports */
 GPIO_Configuration();
 USART_Configuration();
 
 while (1)
 {
 }
}
1234567891011121314
原來是這樣的:狀態寄存器USART_SR的復位值為0x00C0H, 也就是第七位TXE和第六位TC復位值為1,而TXE=1,表明發送數據寄存器為空, TC=1表明發送已完成。而在USART的設置中有
 USART_ITConfig(USART1, USART_IT_TXE, ENABLE);
 USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
12
這兩句使能中斷,也就是說當TXE=1就會進入中斷,所以程序初始化后就能進入中斷,執行
if(USART_GetITStatus(USART1, USART_IT_TXE) != RESET)
 { 
    /* Write one byte to the transmit data register */
      USART_SendData(USART1, TxBuffer[TxCounter++]);
    if(TxCounter == NbrOfDataToTransfer)
    {
      /* Disable the USART1 Transmit interrupt */
      USART_ITConfig(USART1, USART_IT_TXE, DISABLE);
    }
 }
12345678910
因此建議的是在初始化時不好啟用TXE中斷,只在要發送數據(尤其是字符串、數組這樣的系列數據)時才啟用TXE。在發送完成后立即將其關閉,以免引起不必要的麻煩。
對於發送,需要注意TXE和TC的差別——這里簡單描述一下,假設串口數據寄存器是DR、串口移位寄存器是SR以及TXD引腳TXDpin,其關系是DR->SR->TXDpin。當DR中的數據轉移到SR中時TXE置1,如果有數據寫入DR時就能將TXE置0;如果SR中的數據全部通過TXDpin移出並且沒有數據進入DR,則TC置1。並且需要注意TXE只能通過寫DR來置0,不能直接將其清零,而TC可以直接將其寫1清零。
對於發送單個字符可以考慮不用中斷,直接以查詢方式完成。
對於發送字符串/數組類的數據,唯一要考慮的是只在最后一個字符發送后關閉發送中斷,這里可以分為兩種情況:對於發送可顯示的字符串,其用0x00作為結尾的,因此在ISR中就用0x00作為關閉發送中斷(TXE或者TC)的條件;第二種情況就是發送二進制數據,那就是0x00~0xFF中間的任意數據,就不能用0x00來判斷結束了,這時必須知道數據的具體長度。
來自 http://huangchuanlong.blog.163.com/blog/static/14709020201281921233833/
---------------------
作者:劉Zzr
來源:CSDN
原文:https://blog.csdn.net/weixin_43202477/article/details/84848295
版權聲明:本文為博主原創文章,轉載請附上博文鏈接!


注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2021 ITdaan.com