先设计一个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();
}
本文探讨了UART发送过程中如何有效利用FIFO数据队列提高效率,避免 THR 寄存器堵塞。原有的实现方式是每写入一个数据就从队列取出一个数据发送,而建议的改进方案是在 UART0Write 中批量写入数据到队列,然后通过 UART0Putch 启动发送过程,以实现类似 DMA 的效果,提高串口发送性能。

7392

被折叠的 条评论
为什么被折叠?



