历史上的今天
返回首页

历史上的今天

今天是:2024年12月10日(星期二)

正在发生

2021年12月10日 | Exynos4412裸机开发 —— UART

2021-12-10 来源:eefocus

一、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 接收到数据时,读取这个寄存器,即可获得数据。


三、示例程序编写


下面是一个小demo,实现在终端上的回显功能,并通过在终端上输入“beep_on”、"beep_off"实现蜂鸣器的开启和停止:


头文件定义:


  1. /*****************************************    UART  * *************************************/  

  2. /* UART0*/  

  3. typedef struct {  

  4.                 unsigned int ULCON0;  

  5.                 unsigned int UCON0;  

  6.                 unsigned int UFCON0;  

  7.                 unsigned int UMCON0;  

  8.                 unsigned int UTRSTAT0;  

  9.                 unsigned int UERSTAT0;  

  10.                 unsigned int UFSTAT0;  

  11.                 unsigned int UMSTAT0;  

  12.                 unsigned int UTXH0;  

  13.                 unsigned int URXH0;  

  14.                 unsigned int UBRDIV0;  

  15.                 unsigned int UFRACVAL0;  

  16.                 unsigned int UINTP0;  

  17.                 unsigned int UINTSP0;  

  18.                 unsigned int UINTM0;  

  19. }uart0;  

  20. #define UART0 ( * (volatile uart0 *)0x13800000 )  

UART.c

  1. #include "exynos_4412.h"  

  2. #include "pwm.h"  

  3.   

  4. void mydelay_ms(int time)  

  5. {  

  6.     int i, j;  

  7.     while(time--)  

  8.     {  

  9.         for (i = 0; i < 5; i++)  

  10.             for (j = 0; j < 514; j++);  

  11.     }  

  12. }  

  13.   

  14. int strcmp(const char *src, const char *des)  

  15. {  

  16.     while(*src || *des)  

  17.     {  

  18.         if(*src > *des)  

  19.             return 1;  

  20.         else if(*src < *des)  

  21.             return -1;  

  22.         else  

  23.         {  

  24.             src++;  

  25.             des++;  

  26.         }  

  27.     }  

  28.     return 0;  

  29. }  

  30.   

  31. void uart0_init()  

  32. {  

  33.   

  34.     /*UART0 initialize*/  

  35.     GPA0.CON = (GPA0.CON & ~0xFF ) | (0x22); //GPA1_0:RX;GPA1_1:TX  

  36.   

  37.     UART0.ULCON0 = 0x3; //Normal mode, No parity,One stop bit,8 data bits  

  38.     UART0.UCON0 = 0x5;  //Interrupt request or polling mode  

  39.     //Baud-rate : src_clock:100Mhz  

  40.     UART0.UBRDIV0 = 53;  

  41.     UART0.UFRACVAL0 = 0x4;  

  42. }  

  43.   

  44. void putc0(const char data)  

  45. {  

  46.     while(!(UART0.UTRSTAT0 & 0X2));  

  47.     UART0.UTXH0 = data;  

  48.     if (data == 'n')  

  49.             putc0('r');  

  50. }  

  51. char getc0(void)  

  52. {  

  53.     char data;  

  54.     while(!(UART0.UTRSTAT0 & 0x1));  

  55.     data = UART0.URXH0;  

  56.     if ((data == 'n') || (data == 'r'))  

  57.     {  

  58.         putc0('n');  

  59.         putc0('r');  

  60.     }  

  61.     else  

  62.         putc0(data);  

  63.   

  64.     return data;  

  65. }  

  66. void puts0(const  char  *pstr)  

  67. {  

  68.     while(*pstr != '')  

  69.         putc0(*pstr++);  

  70. }  

  71.   

  72. void gets0(char *p)  

  73. {  

  74.     char data;  

  75.     while((data = getc0())!= 'r')  

  76.         *p++ = data;  

  77.     if(data == 'r')  

  78.         *p++ = 'r';  

  79.     *p = '';  

  80. }  

  81.   

  82.   

  83. /* 

  84.  *  裸机代码,不同于LINUX 应用层, 一定加循环控制 

  85.  */  

  86. int main (void)  

  87. {  

  88.     char ch[20];  

  89.     pwm_init();  

  90.     uart0_init();  

  91.     char *q = "hello UART!";  

  92.     puts0(q);  

  93.     while(1)  

推荐阅读

史海拾趣

Davicom公司的发展小趣事

为了进一步提升自身的技术实力和市场竞争力,Davicom积极寻求与业界巨头的合作。经过多轮谈判,Davicom最终与一家国际知名的IC设计大厂达成战略合作协议。双方共同研发出一系列高性能、低功耗的网络通讯IC产品,这些产品一经推出便受到市场的热烈欢迎。

智烽维(CDA)公司的发展小趣事

在超级电容器领域不断取得突破的同时,智烽维也在积极探索新的技术领域。2018年,公司成功实现了锂离子电容器的研发突破。这一成果不仅填补了公司在这一领域的空白,也为公司未来的发展开辟了新的道路。锂离子电容器以其高能量密度、高功率密度和长寿命等特点,在新能源汽车、智能电网等领域具有广阔的应用前景。

ADATA公司的发展小趣事

随着技术的不断成熟和市场的不断拓展,智烽维在2015年开始面向全球开展业务。公司凭借卓越的产品质量和优质的服务,成功打入了国际市场,并在多个国家和地区建立了稳定的销售网络。全球业务的拓展不仅为智烽维带来了更多的商机,也进一步提升了公司的品牌影响力和市场竞争力。

Blue Creation公司的发展小趣事

Blue Creation公司深知人才是企业发展的核心。因此,公司高度重视人才队伍建设,通过校园招聘、社会招聘等多种渠道吸引优秀人才加入。同时,公司还建立了完善的培训体系,为员工提供持续的学习和发展机会。这些举措使得Blue Creation拥有一支高素质、专业化的人才队伍,为公司的快速发展提供了有力保障。

Antex公司的发展小趣事

Antex公司始于1917年,当时它主要从事锻件的制造和销售。这一时期的Antex,凭借着对锻造技术的深入研究和不断创新,逐渐在电子行业中崭露头角。公司注重产品质量和客户需求,通过设计、锻造、机械加工、装配的一站式服务,赢得了客户的信赖。

CDIL[Continental Device India Pvt. Ltd.]公司的发展小趣事

随着全球化进程的加速,CDIL积极寻求与国际知名企业的合作,共同推动电子产业的发展。通过与全球领先企业的合作,CDIL不仅引进了先进的技术和管理经验,还拓展了国际市场,进一步提升了公司的国际影响力。如今,CDIL的产品已远销海外多个国家和地区,为全球电子产业的发展作出了重要贡献。

这五个故事展示了CDIL在电子行业中的发展历程和取得的成就。从半导体制造的先驱到IC封装与电子制造服务的转型,再到产能提升、新技术研发以及国际合作与市场拓展,CDIL始终保持着对技术的追求和对市场的敏锐洞察。正是这些努力,使CDIL在激烈的市场竞争中脱颖而出,成为电子行业中备受瞩目的企业。

问答坊 | AI 解惑

Altium(Protel) 公司出“年报预告”信息了

根据Altium(Protel) 公司在2010年7月12日向悉尼证交所提交的2010年年报预告信息,该公司2009年7月1日至2010年6月30日止,预计共完成销售额是4650万美元,同比下降9% 。 在大中国地区(包括台湾和香港),预计共完成销售额是440万美元,同比下降43% ...…

查看全部问答>

关于在U-boot中添加命令的问题

  大家好,小弟现在正在学习嵌入式这一块,最近看到U-Boot,现在希望能在其中添加一条自己的命令,可是却遇到了这样的问题。   小弟所用的版本是1.3.3,算是比较新的版本。基本上是依照网上介绍的做法来添加的。可是把u-boot ...…

查看全部问答>

求助:网卡全双工/半双工概念问题

请问各位,网卡的全双工/半双工是对MAC而言还是对PHY说的啊,我现在的项目是MAC+PHY结构,自己看资料,发现设置全双工半双工是在PHY芯片上,但是看MAC的工作原理是,全双工半双工控制着MAC的发送流程,看资料上说的是半双工的时候,MAC发送数据要检 ...…

查看全部问答>

求职嵌入式开发

小弟经过2道笔试面试上华为的外包公司文思,虽然也是linux开发有4.75K,但是我真的特别爱好嵌入式,工资比这个低也不介意,不想到时候 又花时间转嵌入式,一次到位算了,想做这个好久了,自己都有些基础 例如操作系统原理,信号,进程,IPC 多线程 ...…

查看全部问答>

SD卡注册表存储

2440 WinCE5.0 目前已实现Flash注册表Hive存储,现在希望存储在SD卡中 存储在Flash中时的注册表是: [HKEY_LOCAL_MACHINE\\System\\StorageManager\\AutoLoad\\MSFlash]     \"DriverPath\"=\"Drivers\\\\BuiltIn\\\\MSFlash\" &nbs ...…

查看全部问答>

请教关于vxworks下位域定义及操作的问题

我的系统是2410+vxworks,最近有个应用问题想使用位域来解决,我定义了如下结构体: typedef union {     struct     {         unsigned char Type   : 3;    &nbs ...…

查看全部问答>

想调用平均值函数

#include <msp430g2231.h>#include <intrinsics.h>   long volMeasured[8];unsigned char volMeasuredPosition = 0;long volAverage;   //  定义一个求平均值函数long Measured[8];long Average(long Measured[8]){&nbs ...…

查看全部问答>

一个开关电源电路图的分析

一个开关电源电路图的分析,+310V电压经过1R1,1R2,稳压二极管1D1(防止栅极因电压过高击穿)给开关管G12栅极提供电压,使其导通,G12导通后,变压器初级56对地导通,+310V给变压器充电,由于电感对初级电流的阻碍作用,变压器上的电流从小到大,当 ...…

查看全部问答>

STM32F429开发板,你愿意DIY吗?

STM32F429的性能真好,很多人对其垂涎。在这里调查一下的目的是,如果响应的人多,愿意为大家做PCB。 …

查看全部问答>