S3C2440的Uart包含两种模式:FIFO模式和非FIFO模式
FIFO模式:
发送数据:数据先写到发送FIFO寄存器,然后数据从发送FIFO寄存器复制到发送移位寄存器,最后数据从TXDn移出。
接收数据:数据从RXDn引脚接收数据到接受移位寄存器,然后数据从接受移位寄存器复制到接受FIFO寄存器。最后CPU从接收FIFO寄存器中读取数据。
非FIFO模式:
发送数据:数据先写入到发送保持寄存器,然后数据从发送保持寄存器复制到发送移位寄存器,最后数据从数据引脚TXDn发送出去。
接受数据:数据从RXDn引脚接受数据到接受移位寄存器,然后复制到接受保持寄存器,最后CPU从接受保持寄存器中读取数据。
由图中可以看出在非FIFO模式下 , Transmit buffer Register 里底下一个为发送保持寄存器。而Receive buffer Register 里最上面的一个为接受保持寄存器
由上图可以看出,时钟有三个来源
1.PCLK
2.FCLK/n
3.UEXTCLK
在基本使用Uart时(不涉及硬件流控制),涉及的寄存器有:
1.ULCONn 配置数据长度,停止位,奇偶校验等
2.UCONn 配置发送模式,接受模式
3.UBRDIVn 设置波特率
4.UTRSTATn 串口状态信息
5. UTXHn和URXHn 发送和接受缓冲器
波特率的计算公式:
初始化串口的一般步骤:
1.设置GPH相应引脚为第二功能,RX和TX (GPHCON)
2.设置通信数据协议,(ULCONn)
3.设置发送模式(中断,查询等)(UCONn)
4.设置波特率(UBRDIVn)
5.设置中断向量表(pISR_UARTn = ...)
6.使能中断(需要注意,UART有子中断,需要使能相应的子中断(INTMSK,INTSUBMSK))
示例代码:
/* 程序的功能是使用串口从PC接收数据并发送回PC
** 在接受的数据中,如果接收到了s则关闭led,o则点亮led
*/
#include "2440addr.h"
#include "config.h"
#define PCLK 50000000
void UartInit(int baudrate);
void __irq uartISR(void);
void ledInit(void);
void Main(void)
{
UartInit(115200);
ledInit();
while(1)
;
}
void UartInit(int baudrate)
{
/* 设置IO为RX和TX */
rGPHCON &= ~((3<<4) | (3<<6));
rGPHCON |= (2<<4) | (2<<6);
/* 正常模式,无奇偶校验,一个停止位,和8位数据 */
rULCON0 &= ~(0xff);
rULCON0 |= (3<<0);
/* 时钟来源PCLK,发送和接受都是中断或者查询模式 */
rUCON0 &= ~(0xffff);
rUCON0 |= (1<<2) | (1<<0);
/* 设置波特率 */
rUBRDIV0 = (int)(PCLK/baudrate/16) - 1;
pISR_UART0 = (unsigned int)uartISR;
rSUBSRCPND |= ((1<<0) | (1<<1));
rSRCPND |= (1<<28);
rINTPND |= (1<<28);
/* 使能发送和接受中断 */
rINTSUBMSK &= ~((1<<0) | (1<<1));
rINTMSK &= ~(1<<28);
}
void ledInit(void)
{
rGPBCON &= ~(3<<10);
rGPBCON |= (1<<10);
rGPBDAT &= (1<<5);
}
void __irq uartISR(void)
{
char buf;
if (rSUBSRCPND & (1<<0)) //RX
{
buf = rURXH0;
if (buf == 's')
rGPBDAT |= (1<<5);
else if (buf == 'o')
rGPBDAT &= ~(1<<5);
rUTXH0 = buf;
rSUBSRCPND |= (1<<0);
}
else
{
rSUBSRCPND |= (1<<1);
}
rSRCPND |= (1<<28);
rINTPND |= (1<<28);
}