[smart210] UART设置与编程

平台:smart210

CPU:S5PV210

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

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

[smart210] UART设置与编程_第1张图片

 

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

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

[smart210] UART设置与编程_第2张图片

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

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

3.  S5PV210的UART所具备的功能

 

[smart210] UART设置与编程_第3张图片

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

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

[smart210] UART设置与编程_第4张图片

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

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

[smart210] UART设置与编程_第5张图片

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

[smart210] UART设置与编程_第6张图片

[smart210] UART设置与编程_第7张图片

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

[smart210] UART设置与编程_第8张图片

[smart210] UART设置与编程_第9张图片

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_VAL        35
#define UART_UDIVSLOT_VAL        0x1

void uart_init()
{
    GPA0CON = 0x22222222;//配置这些GPIO作为串口通讯用
    GPA1CON = 0x2222;
    UFCON0 = 0x1;//FIFO启动,中断阀值设为0,
    UMCON0 = 0x0;//流控制就不用了
    ULCON0 = 0x3;//0000_0011  no parity,no stop bit,normal,8bits
    UCON0  = 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;                          
}

转载于:https://www.cnblogs.com/tinyfeather/p/3260470.html

你可能感兴趣的:([smart210] UART设置与编程)