[smart210] UART设置与编程

来源:互联网 发布:mac获取最高权限 编辑:程序博客网 时间:2024/06/08 00:18

平台:smart210

CPU:S5PV210

目标:通过官方文档【S5PV210_UM_REV1.1.pdf】,获取UART设置的相关信息,进一步学习UART编程

1.通过搜索UART,在P853找到该芯片的串口功能介绍

 

 1.    摘取关键点,我们能够知道,210提供了4个UART接口,支持中断模式或者DMA(直接存储器访问)模式,每个UART包含有两个FIFO缓冲区(读与写),当然每个UART通道所支持的最大FIFO缓冲区也是有限制的,其中UART0支持256字节,UART1支持64字节,UART2与UART3各支持16字节的缓冲区。

 2.   然后就是串口常见的波特率、停止位、校验位、帧宽、等设置,其中波特率来源于PCLK或者SCLK_UART,如图右框图部分

要想获得SLCK_UART,就得先通过某个CLK_SRC寄存器选择时钟信号源,然后再通过某个CLK_DIV寄存器设置分频得到。 当然我们也不需要这样,直接使用默认的PCLK作为串口输入时钟就行了

由于默认是PCLK,而且由官方文档得知UART工作在PSYS domain下,则推理得出UART的工作时钟应该是PCLK_PSYS,在我上一篇文章中已经讲解了子时钟源的设置步骤,照着那个思路去做,PCLK_PSYS就能设置(官方推荐值66Mhz)。只要得到PCLK_PSYS时钟,再设置一些寄存器就能设置波特率了。

3.  S5PV210的UART所具备的功能

 

可知,普通的Rxd与Txd可以用来基于DMA或中断模式的使用,而各自配合上RTS与CTS,将具备自动流量控制功能。由于我们一般把UART用在RS232通讯上,所以一些多余的功能暂时用不到。

4.以UART0为例,介绍各个寄存器

基本常用的那几个有ULCON0、UCON0、UFCON0、UMCON0、UTXH0、URXH0、UTRSTAT0等

其中,ULCON0用来配置一些参数,如 普通/红外模式,奇偶校验,停止位,帧宽。

UCON0用来配置UART0的功能,包括接收/发送模式(中断或轮询/DMA),在一帧的时间内发送中断信号,回环模式,中断相关的一系列设置,DMA设置、波特率设置等

UFCON0是有关FIFO的一系列设置,首位是使能位,接下来是清空缓冲区,FIFO触发中断的阀值设置等。

UMCON0是跟AFC(自动流量控制)相关的,感觉上和FIFO的设置有点像,应该很少会用到这个功能,但是关掉是必须的。

UTRSTAT0的第0位用来查询接收缓冲区是否非空(0为空),第1位用来查询发送缓冲区是否空(0为非空),第2位是同时查询发送移位寄存器与发送缓冲区是否空(0为非空)

如果使用了FIFO,设置了FIFO触发中断阀值为0时,可以使用UTRSTAT0来查询缓冲区。

如果使用了FIFO,设置了FIFO触发中断阀值不为0时,则需要查询UFSTAT0而不是UTRSTAT0。

5.   特别讲解之比特率设置的方法

UBRDIV0(16位)与UDIVSLOT0(16位)是与UCLK相关的寄存器,进一步决定了baud rate(波特率)的值(单位是bps),在有了PCLK_PSYS与目标波特率的情况下,怎么设置UBRDIV0与UDIVSLOT0呢?

这里引进了一个中间变量DIV_VAL,这个中间变量与PCLK_PSYS、bps有这样的函数关系:DIV_VAL=(PCLK_PSYS/(bps*16))-1

同时DIV_VAL与UBRDIV0与UDIVSLOT0也有这样的函数关系:DIV_VAL=UBRDIV0+光棍数/16   (光棍数是指UDIVSLOT0这个16位数在二进制形式下,1的数目,三星好神奇!)

举个小例子吧,假设我现在好不容易有了PCLK_PSYS=66Mhz,那么假设我需要115200bps,那么DIV_VAL=66000000/(115200*16)-1=34.81左右,对应过来就是UBRDIV0=34,光棍数=12.96约为13吧,

那么UDIVSLOT0=b0001 1111 1111 1111 =0x1fff了,数一数,是不是13根光棍呢?

再举一个例子,假设现在的PCLK_PSYS=66.5Mhz,需要115200bps,则DIV_VAL=35.079左右,对应过来UBRDIV0=35,光棍数1.26左右,约为1,那么UDIVSLOT0=0x1。

刚又测试成功,PCLK_PSYS=66.5Mhz,需要9600,算得UBRDIV0=431,UDIVSLOT0=0xefff。

6.  程序实例分析(这个是准备被调用的uart.c,main就一个很简单的getc()然后putc()而已)

#define GPA0CON ( *((volatile unsigned long *)0xE0200000) )#define GPA1CON ( *((volatile unsigned long *)0xE0200020) )// UART相关寄存器#define ULCON0 ( *((volatile unsigned long *)0xE2900000) )#define UCON0 ( *((volatile unsigned long *)0xE2900004) )#define UFCON0 ( *((volatile unsigned long *)0xE2900008) )#define UMCON0 ( *((volatile unsigned long *)0xE290000C) )#define UTRSTAT0 ( *((volatile unsigned long *)0xE2900010) )#define UERSTAT0 ( *((volatile unsigned long *)0xE2900014) )#define UFSTAT0 ( *((volatile unsigned long *)0xE2900018) )#define UMSTAT0 ( *((volatile unsigned long *)0xE290001C) )#define UTXH0 ( *((volatile unsigned long *)0xE2900020) )#define URXH0 ( *((volatile unsigned long *)0xE2900024) )#define UBRDIV0 ( *((volatile unsigned long *)0xE2900028) )#define UDIVSLOT0 ( *((volatile unsigned long *)0xE290002C) )#define UINTP ( *((volatile unsigned long *)0xE2900030) )#define UINTSP ( *((volatile unsigned long *)0xE2900034) )#define UINTM ( *((volatile unsigned long *)0xE2900038) )//上面提到的波特率分频值#define UART_UBRDIV_VAL35#define UART_UDIVSLOT_VAL0x1void uart_init(){GPA0CON = 0x22222222;//配置这些GPIO作为串口通讯用GPA1CON = 0x2222;UFCON0 = 0x1;//FIFO启动,中断阀值设为0,UMCON0 = 0x0;//流控制就不用了ULCON0 = 0x3;//0000_0011  no parity,no stop bit,normal,8bitsUCON0  = 0x5;//读写均采用中断或者轮询模式,由于还关了中断相关设置,则只能用轮询模式了 UBRDIV0 = UART_UBRDIV_VAL;UDIVSLOT0 = UART_UDIVSLOT_VAL;}char getc(void){while (!(UTRSTAT0 & (1<<0)));//由于使用了FIFO但是阀值为0,所以可以使用UTRSTAT来查询,接收区状态为1即非空,!(1&1)=0,跳出轮询以读取缓冲区数据return URXH0;                   }void putc(char c){while (!(UTRSTAT0 & (1<<2)));//发送区与发送移位寄存器空的时候UTRSTAT0的bit2为1,!(1&1)=0,跳出轮询以发送数据到缓冲区UTXH0 = c;                      }


 

 

 

 

 

 

 

 

 

原创粉丝点击