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();
}

 

你可能感兴趣的:(UCOS-II)