最近一直在研究那个UART的例程,感谢斑竹tiankai001的心得,令我受到不少启发,目前的状态是:例程代码基本看懂,但用起来还不能得心应手,lanyu345的代码我粘到uarttest.c中报了一大堆错,是我没有用好?现把例程代码讲一下(估计大家都已知道了哈)。
UART中共有4个文件:cr_startup_lpc13xx.c、uart.c、uart.h、uarttest.c.主要是后三个。
#define SystemFrequency SystemCoreClock //定义产生波特率的时钟
volatile uint32_t UARTStatus; //定义UART状态变量
volatile uint8_t UARTTxEmpty = 1; //标志缓冲区状态的变量,该变量=1时RBR不为空
volatile uint8_t UARTBuffer[BUFSIZE]; //接收和发送的数据共用该数组,下文可知,收到数据后存入该数组,马上又从中读出数据发回串口
volatile uint32_t UARTCount = 0; //上面数组的元素地址
下面着重讲下串口中断的服务函数
void UART_IRQHandler(void)
{
uint8_t IIRValue, LSRValue;
uint8_t Dummy = Dummy;
**********************************************************************************
IIRValue = LPC_UART->IIR;
IIRValue >>= 1; /* skip pending bit in IIR 右移跳过保留位?保留位在4:5啊?*/
IIRValue &= 0x07; /* check bit 1~3, interrupt identification */
if (IIRValue == IIR_RLS) /* Receive Line Status在uart.h中定义IIR_RLS=0x03 */
{
LSRValue = LPC_UART->LSR;
/* Receive Line Status */
if (LSRValue & (LSR_OE | LSR_PE | LSR_FE | LSR_RXFE | LSR_BI)) //根据uart.h中的宏定义,LSR_OE | LSR_PE | LSR_FE | LSR_RXFE | LSR_BI=10011110,查询LSR对应位,表明有错误状态激活。
{
/* There are errors or break interrupt */
/* Read LSR will clear the interrupt 读取LSR,中断被清除*/
UARTStatus = LSRValue;
Dummy = LPC_UART->RBR; /* Dummy read on RX to clear
interrupt, then bail out 读取缓冲区,清楚中断*/
return;
}
/*这部分用来给串口通信除错*/
*************************************************************
if (LSRValue & LSR_RDR) /* Receive Data Ready uart.h中定义RDR=0x01,LSR对应位表明缓冲区包含有效数字 */
{
/* If no error on RLS, normal ready, save into the data buffer. */
/* Note: read RBR will clear the interrupt */
UARTBuffer[UARTCount++] = LPC_UART->RBR; //读取缓冲区变量到数组UARTBuffer,地址变量UARTCount累加1
if (UARTCount == BUFSIZE) //地址变量UARTCount超出数组预定义长度64时清零。
{
UARTCount = 0; /* buffer overflow */
}
}
}
else if (IIRValue == IIR_RDA) /* Receive Data Available uart.h中定义IIR_RDA)=0x02, IIRValue右移两位再&0x07,查手册IIR处于RDA中断(接收数据可用状态),但反推IIRvalue的值似乎尚有疑问?*/
{
/* Receive Data Available */
UARTBuffer[UARTCount++] = LPC_UART->RBR;
if (UARTCount == BUFSIZE)
{
UARTCount = 0; /* buffer overflow 读数据同上*/
}
}
else if (IIRValue == IIR_CTI) /* Character timeout indicator CTI中断表明通讯超时,FCR的7:6位定义通信的最小字节数,当上位机信号不是最小字节数的整数倍时余项字节将触发CTI中断,本例的串口初始化函数void UARTInit(uint32_t baudrate)中已定义最小字节为零,故理论上不会触发CTI */
{
/* Character Time-out indicator */
UARTStatus |= 0x100; /* Bit 9 as the CTI error */
}
else if (IIRValue == IIR_THRE) /* THRE, transmit holding register empty 这部分用来给UARTTxEmpty 赋值,协助发送程序判断fifo是否可用 */
{
/* THRE interrupt */
LSRValue = LPC_UART->LSR; /* Check status in the LSR to see if
valid data in U0THR or not */
if (LSRValue & LSR_THRE)
{
UARTTxEmpty = 1;
}
else
{
UARTTxEmpty = 0;
}
}
return;
}
void UARTSend(uint8_t *BufferPtr, uint32_t Length)
{
while ( Length != 0 )
{
/* THRE status, contain valid data */
#if !TX_INTERRUPT
while ( !(LPC_UART->LSR & LSR_THRE) );
LPC_UART->THR = *BufferPtr;
#else
/* Below flag is set inside the interrupt handler when THRE occurs. */
while ( !(UARTTxEmpty & 0x01) );
LPC_UART->THR = *BufferPtr;
UARTTxEmpty = 0; /* not empty in the THR until it shifts out */
#endif
BufferPtr++;
Length--;
}
return;