zoukankan      html  css  js  c++  java
  • [smart210] UART设置与编程

    平台: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_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;                          
    }
  • 相关阅读:
    让网络编程更轻松和有趣 t-io
    设计一个百万级的消息推送系统
    前端安全系列之二:如何防止CSRF攻击
    Maven仓库下载jar包失败的处理方案
    SpringBoot2中配置文件的调整,升级SpringBoot2时候注意的坑
    Table折叠小技巧html-demo
    mysql如何分类统计数量
    前台登录和Token信息交互流程
    windows下安装mysql5.6
    【读书笔记】-- 你不知道的JavaScript
  • 原文地址:https://www.cnblogs.com/tinyfeather/p/3260470.html
Copyright © 2011-2022 走看看