UART的發送FIFO問題

UART的發送FIFO問題

先設計一個FIFO的數據隊列UART0SendBuf,然後在UART發送函數中如下操作。如你所看到的,UART0Putch發1個數據往隊列裏寫1個數據,判斷LSR的THRE位是否爲1,即THR如果空則發送1個最先進入隊列的數據到THR寄存器,該寄存器再寫入硬件FIFO。在發送THRE中斷中判斷數據隊列爲空,非空則繼續寫數據到THR。

/******************************************************************************
** 函數名稱: UART0Putch
** 功能描述: 發送一個字節數據
** 輸 入: Data:發送的數據數據
** 輸 出:無
** 全局變量: 無
** 調用模塊: 無
******************************************************************************/
API void UART0Putch(IN uint8 Data)
{
    uint8 temp;
   
    QueueWrite((void *)UART0SendBuf, Data);         // 數據入隊
    OS_ENTER_CRITICAL();
    if ((U0LSR & 0x00000020) != 0)
    {                                               // UART0發送保持寄存器空
        QueueRead(&temp, UART0SendBuf);             // 發送最初入隊的數據
        U0THR = temp;
        U0IER = U0IER | 0x02;                       // 允許發送中斷
    }
    OS_EXIT_CRITICAL();
}

/******************************************************************************
** 函數名稱: UART0Write
** 功能描述: 發送多個字節數據
** 輸 入: Data:發送數據存儲位置
**        NByte:發送數據個數
** 輸 出:無
** 全局變量: 無
** 調用模塊: UART0Putch
******************************************************************************/
API void UART0Write(IN uint8 *Data, IN uint16 NByte)
{
    OS_ENTER_CRITICAL();
    while (NByte-- > 0)
    {
        UART0Putch(*Data++);
    }
    OS_EXIT_CRITICAL();
}

/******************************************************************************
** 函數名稱: UART0_Exception
** 功能描述: UART0中斷服務程序
** 輸 入: 無
**
** 輸 出: 無
**        
** 全局變量: 無
** 調用模塊: QueueRead,OSSemPost
******************************************************************************/
 void UART0_Exception(void)
{
    uint8 IIR, temp, i;
   
    OS_ENTER_CRITICAL();
    IIR = U0IIR;
    if((IIR & 0X01) == 0)
    {
     switch (IIR & 0x0e)
     {
      case 0x02:                                  // THRE中斷   
          for (i = 0; i < UART0_FIFO_LENGTH; i++) // 向發送FIFO填充數據
             {
              if (QueueRead(&temp, UART0SendBuf) == QUEUE_OK)
                 {
                  U0THR = temp;
                 }
                 else
                 {
                     U0IER = U0IER & (~0x02);    // 隊列空,則禁止發送中斷
                 }
             }
             break;
         default :
             break;
     }
 }
    VICVectAddr = 0;            // 通知中斷控制器中斷結束
    OS_EXIT_CRITICAL();
}

//----------------------------------------------------------------------------------

  上面的程序是每往數據隊列裏寫1個數據就從隊列裏取1個數據寫到THR寄存器,看上去也是先進先出,但我認爲這樣的情況下THR寄存器發生堵塞的可能性很小,這樣也就失去了設計FIFO數據隊列的意義,並且效率低下。 如過改成在UART0Write裏把DATA數據都寫進UART0SendBuf隊列裏,然後調用1次UART0Putch來啓動往THR寄存器寫數據,這樣是否會大大提高效率,真正使FIFO隊列起作用,甚至使串口發送類似DMA的功能。改動後的函數如下:

/******************************************************************************
** 函數名稱: UART0Putch
** 功能描述: 發送一個字節數據
** 輸 入: Data:發送的數據數據
** 輸 出:無
** 全局變量: 無
** 調用模塊: 無
******************************************************************************/
API void UART0Putch(void)
{
    uint8 temp;
    OS_ENTER_CRITICAL();
    if ((U0LSR & 0x00000020) != 0)
    {                                               // UART0發送保持寄存器空
        QueueRead(&temp, UART0SendBuf);             // 發送最初入隊的數據
        U0THR = temp;
        U0IER = U0IER | 0x02;                       // 允許發送中斷
    }
    OS_EXIT_CRITICAL();
}

/******************************************************************************
** 函數名稱: UART0Write
** 功能描述: 發送多個字節數據
** 輸 入: Data:發送數據存儲位置
**        NByte:發送數據個數
** 輸 出:無
** 全局變量: 無
** 調用模塊: UART0Putch
******************************************************************************/
API void UART0Write(IN uint8 *Data, IN uint16 NByte)
{
    OS_ENTER_CRITICAL();
    while (NByte-- > 0)
    {
        QueueWrite((void *)UART0SendBuf, *Data++);         // 數據入隊    
    }

    UART0Putch();
    OS_EXIT_CRITICAL();
}

 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章