先設計一個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();
}