UART配置流程
S3C2440A 的通用异步收发器(UART)配有3 个独立异步串行I/O(SIO)端口,每个都可以是基于中断或基于DMA 模式的操作。换句话说,UART 可以通过产生中断或DMA 请求来进行CPU 和UART 之间的数据传输。UART 通过使用系统时钟可以支持最高115.2Kbps 的比特率。如果是外部器件提供UEXTCLK 的UART,则UART可以运行在更高的速度。每个UART 通道包含两个的64 字节的FIFO 给发送和接收。
作为最基本的外设,S3C2440A 的通用异步收发器(UART )配有3 个独立异步串行I/O 端口。不同于51,2440的每个UART均不占用定时器来产生波特率。并且每个UART都拥有一个独立用于收发的缓冲区FIFO。本节我们就使用mini2440携带的uart0,实现一个与pc双向通信的串口程序。实现波特率为9600,n,8,1。为了方便,本次实验不使用FIFO。
FIFO模式中,缓冲寄存器的64字节都用于FIFO寄存器。
非FIFO模式中,只有1个字节用于保持寄存器。
上图所示的外设总线是指地址控制总线,也就是我们访问寄存器时使用的地址转换为实际信号的总线。通过该总线可以访问到控制单元,其实就是之后我们要用的一堆寄存器。它们可以用来控制波特率发生器,读取收到的数据,写入我们要发送的数据。数据进入发送保持寄存器之后,会自动进入发送位移器,然后数据就按照串口通信的时序从硬件引脚上逐次发送出去了。
上图UART线路控制寄存器ULCONn决定通信所需的奇偶校验位、数据位、停止位等信息。红外模式是2440专门为红外设备设计的,这里我们使用普通模式。
UART控制寄存器是一个非常重要的寄存器,内容比较多,而且中文手册不全。我们参考英文手册并从后向前分析这个寄存器的作用。
UART控制寄存器的低四位用于指定串口收发时的工作方式,分别是不使能接收,中断或查询方式和DMA方式。这里我们不用DMA方式,并且还要允许接收,自然是设置为01了。[3:2]两个比特于此类似,不过是用于设置发送的。之后我们将模仿在51中的做法,用查询方式发送,用中断方式接收。
UART控制寄存器UCONn的4~9位就比较简单了,分别设置为正常传输、正常操作、不产生接收错误状态中断和脉冲方式。使用脉冲而不是电平很显然是因为不能在正在收数据的时候产生中断,而是应该在数据接收完整之后再产生中断。
UART控制寄存器UCONn的10~15比特看着很复杂的样子,起始这一块主要是用于设置波特率的。[11:10]用于选择uart的时钟源的。分别是PCLK,UEXTCLK和FCLK。这里的UEXTCLK指的是外部时钟,PCLK和FCLK在时钟配置主题中我们设置成了400M和50M。一旦时钟被选择,那么波特率就可以通过公式(int)( 被选时钟/ (波特率* 16)) – 1来计算,并将这个公式计算的结果存入UBRDIVn寄存器。比如我们选择使用PCLK,即50M,波特率为9600,那么公式计算的结果就是324.52,取整得325,把这个数存到UBRDIVn波特率就设置好了,简直不要太方便。如果我们把uart的时钟设置为FCLK,那么uart的实际工作频率就由该寄存器的[15:12]决定,有兴趣的读者可以自行尝试。
uart状态寄存器是用来查询uart的状态的,第2比特可用于判断数据是否发送完毕,类似于51的RI,同理,第1比特和第2比特的区别在于一个是位移寄存器为空,另外一个是位移寄存器不一定为空。
发送数据缓冲寄存器:类似51的SUBF寄存器,要发送的数据写入这个寄存器,2440会自动把数据放入位移寄存器发送。
接收缓冲寄存器:接收到的数据从这个寄存器读出来。
波特率分频寄存器用于保存我们计算好的那个初值。上面说过,这个初值在9600下是325。
此外,由于需要使用引脚产生实际信号,UART对应的GPIO也要设置好;在数据接收时需要使用中断,所以相关的中断也要配置好。UART在中断设置方面需要注意的是UART中断有子终端掩码和子终端挂起寄存器。因此在设置和处理中断时要加以处理。
至此,时钟的配置已经完成。
void init_uart0(void)
{unsigned int t;GPHCON &= ~(0x0F << 4);GPHCON |= (2 << 4) | (2 << 6);t = ULCON0;t &= ~((1 << 6) | (7 << 3) | (1 << 2)) ;t |= (3 << 0);ULCON0 = t;t = UCON0;t &= ~((3 << 10) | (3 << 8) | (0x0F << 4));t &= ~(0x0F << 0);t |= (1 << 2) | (1 << 0);UCON0 = t;UBRDIV0 = 325;INTSUBMSK &= ~(1 << 0);enable_irq(28);register_irq(28, uart0_handler);pos = 0;
}