对LPC2103串口的一些理解
LPC2103含有个相互独立的通用异步串行接口 (UART0 UART1),其特点是具有16字节的接收和发送FIFO,符合550工业标准(我对这个标准不了解),接收触发可以设置为1字节、4字节、8字节、14字节。
在实际应用时,需要配置的主要的寄存器有(以UART0为例):线控制寄存器U0LCR,除数锁存器U0DLM、U0DLL,中断使能寄存器U0IER,FIFO控制寄存器U0FCR,中断标志寄存器U0IIR。在使用的时候,最让我困惑的是U0FCR的触发选择位U0FCR[7:6], 这两位的不同组合代表不同的触发字节:00--1字节触发;01--4字节触发;10--8字节触发;11--14字节触发。当我将它设置为8字节触发,并使能接收中断后,使用串口调试助手向LPC2103的UART0发送数据,发现可以进入中断,却无法执行中断服务程序。
中断服务程序的代码如下:
void __irq uart0_isr(void)
{
uint8 i;
if(U0IIR&0x0f == 0x04)
{
for(i=0;i<8;i++)
lcd_write_char(2,i,U0RBR);
}
VICVectAddr = 0x00;
}
通过调试器单步调试,发现U0IIR&0x0f == 0x04的条件始终不成立,watch窗口显示U0IIR的值为0x000000cc,而尝试读取U0IIR寄存器的值之后,发现该寄存器的值立即变为0x000000c1。于是感觉多字节触发的功能不可用,改用单字节触发,发现工作正常,而每次读取U0IIR寄存器之后该寄存器的值也立即复位。于是查阅NXP的data sheet,找到了答案:The U0IIR must be read in order to clear the interrupt prior to exiting the Interrupt Service Routine. 说明在中断服务程序中必须读取U0IIR的值才能清楚中断标志,当然寄存器的值也就复位了。但是为什么用8字节触发的功能无法使用呢?查阅data sheet,发现当U0IIR的低4位为0xc时表示接收超时。为什么总是会接收超时呢?我想起来每次调试时我都是用串口调试助手发送一个字符,而当设置为8字节触发时,接收到一个字符后,接收器经过一定的时间后没有接收到字符,就会触发中断,提示接收超时。大概了解问题出在哪里了,于是我尝试一次发送8个以上字符,采用8字节触发的接收方式,发现发送的字符串的前8个可以正常接收,说明接收中断正常触发了,没有出现超时。
经过这番折腾,总算是明白了所谓的多字节触发是什么意思了。本来以为设置为多字节触发,不论接收到的字符是一次性收到还是分时收到,都会积累起来,直到达到预设的上限然后触发。以这种想当然的思路去设计程序,跑出来的结果与预期的完全不符,并且在这种情况下很难检查出问题。由此深深地感觉到,做事情不能总是想当然,还是要踏踏实实,不能丢下细节的东西。
—————————————————转自Nostalgia's BLOG
http://blog.sina.com.cn/nostalgia2009