zoukankan      html  css  js  c++  java
  • Cortex-A9 UART

    一、Exynos4412 UART 的特性

          Exynos4412 中UART,有4 个独立的通道,每个通道都可以工作于中断模式或DMA 模式,即 UART 可以发出中断或 DMA 请求以便在UART 、CPU 间传输数据。UART 由波特率发生器、发送器、接收器和控制逻辑组成。

        使用系统时钟时,Exynos4412 的 UART 波特率可以达到 4Mbps 。波特率可以通过编程进行 。

        Exynos4412 UART 的通道 0有 256 字节的发送 FIFO 和 256 字节的接收FIFO ;通道 1、4有 64 字节的发送 FIFO 和 64 字节的接收FIFO;通道 2、3有 16 字节的发送FIFO 和 16 字节 的接收 FIFO 。发送数据时, CPU 先将数据写入发送FIFO 中,然后 UART 会自动将FIFO 中的数据复制到“发送移位器” (Transmit Shifter )中,发送移位器将数据一位一位地发送到 TxDn 数据线上 (根据设定的格式,插入开始位 、较验和停止)。接收数据时,“移位器” (Receive Shifter )将 RxDn 数据线上的数据一位一位的接收进来,然后复制到FIFO 中, CPU即可从中读取数据。

         Exynos4412 UART的每个通道支持停止位有 1位、 2位,数据位有 5、6、7或 8位,支持校验功能,另外还有红外发送 /接收功能。

    Exynos4412 UART结构图:

    二、uart初始化步骤:

    1、将所涉及的UART通道管脚设为UART功能

          比如 UART 通道 0中, GPA0_0 、GPA0_1 分别用作 RXD0 、TXD0,要使用 UART 通道 0时,先设置 GPA0CON 寄存器将 GPA0_0 、GPA0_1 引脚的功能设为 RXD0 、TXD0 。

    2、 选择UART的时钟源

       

            Exynos4412 UART的时钟源有八种选择: XXTI 、XusbXTI 、SCLK_HDMI24M 、SCLK_USBPHY0 、 SCLK_HDMIPHY 、SCLKMPLL_USER_T 、SCLKEPLL 、SCLKVPLL ,由 CLK_SRC_PERIL0 寄存器控制。
    选择好时钟源后,还可以通过 DIVUART0 ~4设置分频系数 设置分频系数 ,由 CLK_DIV_PERIL0 寄存器控制。 从分频器得到的时钟被称为SCLK UART 。

           SCLK UART 经过上图中的“ UCLK Generator”后,得到UCLK ,它的频率就是UART 的波特率。“ Generator UCLK Generator ”通过这 2个寄存器来设置: UBRDEVn 、UFRACVALn (在下面描述)。

     

    3.、设置波特率:UBRDIVn寄存器(UART BAUD RATE DIVISOR)、UFRACVALn寄存器

          根据给定的波特率、所选择时钟源频率,可以通过以下公式计算 UBRDIVn 寄存器 (n 为 0~4,对应 5个 UART 通道 )的值。

          UBRDIVn = (int)( UART clock / ( buad rate x 16) ) – 1

         上式计算出来的 UBRDIVn 寄存器值不一定是整数, UBRDIVn 寄存器取其整数部分,小部分由 UFRACVALn 寄存器设置, UFRACVALn 寄存器的引入,使产生波特率更加精确。

    例如,当UART clock为100MHz时,要求波特率为115200 bps,则:

    100000000/(115200 x 16) – 1 = 54.25 – 1 = 53.25

    UBRDIVn = 整数部分 = 53

    UFRACVALn/16 = 小数部分 = 0.25

    UFRACVALn = 4



    4. 设置传输格式:ULCONn寄存器(UART LINE CONTROL)

    ULCONn 寄存器 (n 为 0~4) 格式如下图所示:

    5. 设置UART工作模式:UCONn寄存器(UART CONTROL)

     

    6. UFCONn寄存器(UART FIFO CONTROL)、UFSTATn寄存器(UART FIFO STATUS)

            UFCON n寄存器用于设置是否使用FIFO,设置各 FIFO的触发阀值,即发送 FIFO中有多少个数据时产生中断、接收 FIFO 中有多少个数据时产生中断。并可以通过设置UFCON n寄存器来复位各个 FIFO 。

            读取 UFSTAT n寄存器可以知道各个 FIFO 是否已经满、其中有多少个数据。

    不使用 FIFO 时,可以认为 FIFO 的深度为1,使用 FIFO 时 Exynos4412 的 FIFO 深度最高可达到256 。


    7. UMCONn寄存器(UART MODEM CONTROL)、UMSTATn寄存器(UART MODEM STATUS)

           这两类寄存器用于流量控制,这里不介绍。


    8. UTRSTATn寄存器(UART TX/RX STATUS)

           UTRSTAT n寄存器用来表明数据是否已经发送完毕、是否已经接收到数据,格式如下表所示,下面说的“缓冲区”,其实就是下图中的 FIFO ,不使用 FIFO 功能时可以认为其深度为 1。

    9. UERSTATn寄存器(UART ERROR STATUS)

          用来表示各种错误是否发生,位 [0] 至位 [3] 为 1时分别表示溢出错误、校验错误、帧错误、检测到“ break ”信号。读取这个寄存器时,它会自动清 0。

          需要注意的是,接收数据时如果使用 FIFO ,则 UART 内部会使用一个“错误 FIFO ”来表明接收 FIFO 中哪个数据在接收过程发生了错误。 CPU 只有在读出这个错误的数据时,才会觉察到发生了错误 。要想清除“FIFO ”,则必须读出错误的数据,并读出UERSTATn 寄存器。

     

    10. UTXHn寄存器(UART TRANSMIT BUFFER REGISTER)

           CPU 将数据写入这个寄存器, UART即会将它保存到缓冲区中,并自动发送出去。

    11. URXHn寄存器(UART RECEIVE BUFFER REGISTER)

          当 UART 接收到数据时,读取这个寄存器,即可获得数据。

    三、示例程序编写

    复制代码
    #include "exynos_4412.h"
    
    void delay_ms(unsigned int time);
    void sendch(const char ch);
    void sendstr(const char *str);
    void recvch(char *ch);
    void recvstr(char *str);
    
    void myuart_init(void)
    {
        //设置引脚功能 UART RX TX
        GPA1.CON = GPA1.CON & ~0xff | 0x22;
        //设置传输格式  无校验 停止位:1 数据位:8
        UART2.ULCON2 = UART2.ULCON2 & ~0x7f | 0x3;
        //设置接收、发送方式
        UART2.UCON2 = UART2.UCON2 & ~0xf | 0x5;
        //设置波特率 115200
        UART2.UBRDIV2 = 53;
        UART2.UFRACVAL2 = 4;
        //DIV_VAL = (SCLK_UART / (bps * 16)) - 1
    }
    
    int main()
    {
        char buf[] = "uart send: hello world!
    ";
        char recvbuf[100];
        myuart_init();
    
        while(1)
        {
            sendstr(buf);
            delay_ms(1000);
        }
    
        return 0;
    }
    
    void delay_ms(unsigned int time)
    {
        int i, j;
        while(time--)
        for(i = 0; i < 5; i++)
            for(j = 0; j < 610; j++);
    }
    void sendch(const char ch)
    {
        /*等待发送器发送完成*/
        while(!(UART2.UTRSTAT2 & 0x2));
        UART2.UTXH2 = ch;
        if (ch == '
    ')
        {
            sendch('
    ');
        }
    }
    
    void sendstr(const char *str)
    {
        while(*str != '')
        {
            sendch(*str++);
        }
    }
    
    void recvch(char *ch)
    {
        /*等待接收完成*/
        while(!(UART2.UTRSTAT2 & 0x1));
        *ch = UART2.URXH2;
    }
    
    void recvstr(char *str)
    {
        while(1)
        {
            recvch(str);
            if(*str == '
    ' )
            {
                *str = '';
                break;
            }
            str++;
        }
    }
  • 相关阅读:
    十月二十七学习报告
    十月二十六学习报告
    十月二十五学习报告
    十月二十四学习报告
    十月二十三学习报告
    十月二十二学习报告
    十月二十一学习报告
    十月十九学习报告
    十月十七学习报告
    十月十六学习报告
  • 原文地址:https://www.cnblogs.com/wanghuaijun/p/7586851.html
Copyright © 2011-2022 走看看