历史上的今天
返回首页

历史上的今天

今天是:2024年10月14日(星期一)

正在发生

2018年10月14日 | Exynos4412裸机程序之UART收发数据

2018-10-14 来源: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结构图

exynos4412 uart

exynos4412 uart

声明

以后没有特殊说明,程序结构都和《Tiny4412裸机程序之代码在DDR SDRAM中运行》时的一样。

整个程序的运行过程大致如下:系统上电后,首先将sd卡扇区1处的bl1拷贝到IRAM的0x02020000地址处,然后运行该部分代码,该部分代码首先又会加载BL2.bin,BL2.bin会进行时钟和DRAM初始化,然后把位于sd卡中扇区49处的main.bin拷贝到DRAM的0x43E00000地址处,最后跳转到该地址处继续运行。

uart初始化步骤:

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

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

2. 选择UART的时钟源

uart clock

uart clock

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 (在下面描述 在下面描述 )。

uarto_sel

CLK_SEC_PERIL0格式

CLK_DIV_PERIL0的寄存器格式

CLK_DIV_PERIL0的寄存器格式

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) 格式如下图所示:

ULCONn寄存器格式

ULCONn寄存器格式

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

UCONn寄存器格式

UCONn寄存器格式

UCONn寄存器格式

UCONn寄存器格式

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。

UTRSTATn寄存器格式

UTRSTATn寄存器格式

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

 

程序说明

程序文件和上一个实验大同小异,只是在MAIN文件夹下新建了一个init.c及init.h文件,用来存放初始化相关的代码。

下面是init.c文件的全部代码:

==================================================================

// GPIO

#define GPA0CON (*(volatile unsigned int *)0x11400000)

// system clock

#define CLK_SRC_PERIL0 (*(volatile unsigned int *)0x1003C250)

#define CLK_DIV_PERIL0 (*(volatile unsigned int *)0x1003C550)

// UART

#define UFCON0 (*(volatile unsigned int *)0x13800008)

#define ULCON0 (*(volatile unsigned int *)0x13800000)

#define UCON0 (*(volatile unsigned int *)0x13800004)

#define UBRDIV0 (*(volatile unsigned int *)0x13800028)

#define UFRACVAL0 (*(volatile unsigned int *)0x1380002c)

#define UTXH0 (*(volatile unsigned int *)0x13800020)

#define URXH0 (*(volatile unsigned int *)0x13800024)

 

#define UTRSTAT0 (*(volatile unsigned int *)0x13800010)

 

void UartInit()

{

    // 1.设置相应的GPIO用于串口功能 

    unsigned long tmp = 0;

     

    tmp = GPA0CON;

    tmp &= ~(0xff); //设置UART0对应的GPIO为UART功能

    tmp |= 0x22;

    GPA0CON = tmp;

     

    // 2.设置UART时钟源SCLK_UART 

    // 2.1 CLK_SRC_DMC : bit[12]即MUX_MPLL_SEL=1, SCLKMPLLL使用MPLL的输出

    // 2.2 CLK_SRC_TOP1 : bit[12]即MUX_MPLL_USER_SEL_T=1, MUXMPLL使用SCLKMPLLL

    // 2.3 CLK_SRC_PERIL0 : bit[3:0]即UART0_SEL=6, MOUTUART0使用SCLKMPLL_USER_T

    // 所以, MOUTUART0即等于MPLL的输出, 800MHz

    

    //PWM_SEL = 0;

    //UART5_SEL = 0;

    //UART4_SEL = 6; // 串口时钟源选 SCLKMPLL_USER_T

    //UART3_SEL = 6;

    //UART2_SEL = 6;

    //UART1_SEL = 6;

    //UART0_SEL = 6;

    CLK_SRC_PERIL0 = ((0 << 24) | (0 << 20) | (6 << 16) | (6 << 12) | (6<< 8) | (6 << 4) | (6));

     

    // 分频系数 = 7+1 = 8

    // 2.4 CLK_DIV_PERIL0 : bit[3:0]即UART0_RATIO=7,所以SCLK_UART0=MOUTUART0/(7+1)=100MHz

    CLK_DIV_PERIL0 = ((7 << 20) | (7 << 16) | (7 << 12) | (7 << 8) | (7 << 4) | (7));

     

    // 3.设置串口0相关 

    // 设置FIFO中断触发阈值

    // 使能FIFO

    UFCON0 = 0x111;

     

    // 设置数据格式: 8n1, 即8个数据位,没有较验位,1个停止位 

    ULCON0 = 0x3;

     

    // 工作于中断/查询模式

    // 另一种是DMA模式,本章不使用

    UCON0 = 0x5;

     

    // SCLK_UART0=100MHz, 波特率设置为115200

    // 寄存器的值如下计算:

    // DIV_VAL = 100,000,000 / (115200 * 16) - 1 = 53.25

    // UBRDIVn0 = 整数部分 = 53

    // UFRACVAL0 = 小数部分 x 16 = 0.25 * 16 = 4

    UBRDIV0 = 53;

    UFRACVAL0 = 4;

}

 

char getc(void)

{

    char c;

    // 查询状态寄存器,直到有有效数据 

    while (!(UTRSTAT0 & (1<<0)));

    c = URXH0; // 读取接收寄存器的值 

     

    return c;

}

 

void putc(char c)

{

    // 查询状态寄存器,直到发送缓存为空 

    while (!(UTRSTAT0 & (1<<2)));

     

    UTXH0 = c; // 写入发送寄存器 

     

    return;

}

 

void puts(char *s)

{

  while (*s)

  {

     putc(*s);

     s++;

  }

}

==================================================================

1. UART时钟源

如在《Tiny4412裸机程序,时钟操作》试验里对 MPLL 进行了设置 ,本程序使用相同的 PLL 设置代码 (文件 system_clock.c 中的 system_clock_init函数 ):

----------------------------------------------------------------

MPLL_CON0 = (1<<31 | 0x64<<16 | 0x3<<8 | 0x0);

...............

CLK_SRC_DMC = 0x00011000;

...............

CLK_SRC_TOP1 = 0x01111000;

----------------------------------------------------------------


第 1 行设置MPLL 输出 800MHz,计算公式如下:

FOUT = MDIV x FIN / (PDIV x 2 ^ SDIV) = 0x64 x 24MHz / (3 x 2^ 0) = 800MHz

第5行设置CLK_SRC_DMC 寄存器的  bit[12] 即 MUXMPLL设置为 1,使得 SCLKMPLL 使用 MPLL的输出,即  800MHz 。

第9行设置CLK_SRC_TOP1 寄存器的bit[12] 即 MUX_MPLL_USER_SEL_T为 1,使得 SCLKMPLL_USER_T 使用 SCLKMPLL ,即 800MHz 。

下图摘自芯片手册时钟管理单元的章节, 图中 MUXMPLL 和 MUXMPLL_CTRL_USER_T 都被设置为 1,所以 SCLKMPLL_USER_T 就等于 MPLL 的输出,也就是 800MHz 。

MPLL输出时钟

MPLL输出时钟

SCLKMPLL_USER_T 将作为整个UART 模块的时钟源。

2. UART的初始化

如上init.c文件所示,注释非常详细,不做说明。

3. UART的使用

对 UART 的使用,不外乎读取数据、输出。这由 getc 、putc 函数来实现:

char getc(void)

{

    char c;

    // 查询状态寄存器,直到有有效数据 

    while (!(UTRSTAT0 & (1<<0)));

     

    c = URXH0; // 读取接收寄存器的值 

     

    return c;

}

 

void putc(char c)

{

    // 查询状态寄存器,直到发送缓存为空 

    while (!(UTRSTAT0 & (1<<2)));

     

    UTXH0 = c; // 写入发送寄存器 

     

    return;

}

 

void puts(char *s)

{

    while (*s)

    {

        putc(*s);

        s++;

    }

}

在 main 函数里,就是调用getc 、putc 来实现我们的目:获取字符,加 1后输出:

====================================================================

int main(void)

{

    char rec;

     

    UartInit();

     

    while(1)

    {

        rec = getc();

        rec++;

        putc('\r');

        putc('\n');

        putc(rec);

    }

     

    return 0;

}

====================================================================

编译、烧写、运行

1.编译

通过FTP或者其他工具将文件上传到服务器上去,输入make命令进行编译将得到make_bl2.bin和main.bin文件。

编译结果

编译结果

2.烧写

将SD卡插入电脑,并让VmWare里的Ubuntu识别出来,然后执行如下命令:

1

sudo ./sd_fusing.sh /dev/sdb ../10_uart/BL2/make_bl2.bin ../10_uart/MAIN/main.bin

程序烧写

程序烧写

连接电脑

如下图所示,将串口线连接在开发板上

连接串口线

连接串口线

运行现象

运行效果

运行效果

从串口上读入一个字符后, 加 1再输出。比如读到 ’A’输出 ’B’。


推荐阅读

史海拾趣

Continental公司的发展小趣事

近年来,大陆集团在特种商用车胎领域也取得了重要突破。2014年,大陆集团在亚洲国际物流技术与运输系统展览会上发布了一款全新的产品——SC8特种商用车胎。这款产品是专门针对亚洲物料搬运业而开发出来的,适用于仓库、饮料业、造纸业等多个行业。SC8轮胎具备超深的轮胎花纹和极佳的性能,为物料搬运业提供了更高效、更安全的解决方案。这一产品的推出进一步巩固了大陆集团在商用车胎领域的市场地位。

Amphion Semiconductor Ltd公司的发展小趣事

随着汽车工业的发展,大陆集团开始将业务扩展到汽车轮胎领域。1901年,马牌轮胎首次与德国戴姆勒·奔驰汽车公司合作参加汽车竞赛,这标志着大陆集团正式进入汽车轮胎市场。仅仅三年后,大陆集团就生产出了全世界第一条带花纹的汽车轮胎,这一创新大大提高了轮胎的抓地力和安全性。1908年,大陆集团又生产出了全世界第一个可拆装的车轮,使车轮和车轴分开,由此大大节省了换轮胎的时间。这些技术创新使得大陆集团在汽车轮胎市场上占据了重要地位。

Heatron公司的发展小趣事

面对日益激烈的市场竞争和快速变化的市场需求,Heatron公司积极拥抱数字化转型。公司引入了先进的智能制造系统和大数据分析技术,实现了生产过程的智能化、自动化和精细化管理。同时,公司还建立了完善的客户服务体系和数据分析平台,以便更准确地把握市场需求和客户反馈。这些举措不仅显著提升了Heatron的生产效率和产品质量,还增强了其在电子行业中的综合竞争力。

需要注意的是,以上故事均为基于电子行业背景和Heatron公司业务范畴的构想性描述,旨在展示Heatron公司可能的发展路径和成就。实际情况可能因时间、市场环境等多种因素而有所不同。

Conditioning Semiconductor Devices Corp公司的发展小趣事

CSDC深知人才是企业发展的核心。因此,公司一直注重人才的引进和培养。通过校园招聘、社会招聘等多种渠道,CSDC吸引了一批优秀的半导体专业人才。同时,公司还建立了完善的培训体系,为员工提供持续的学习和发展机会。这些举措不仅提升了员工的技能水平,也增强了公司的凝聚力和竞争力。

BLACK&DECKER公司的发展小趣事

2010年3月15日,BLACK&DECKER迎来了公司历史上的一个重要时刻——与史丹利公司合并组建史丹利百得公司。这一合并不仅使BLACK&DECKER获得了更强大的资源和市场支持,还为其未来的发展提供了更广阔的空间。合并后的史丹利百得公司致力于提供整合的五金工具、存储设备和安防系统解决方案,以满足全球消费者的多样化需求。通过整合双方的优势资源和技术力量,史丹利百得公司有望在电子行业中取得更加辉煌的成就。

综上所述,BLACK&DECKER公司在电子行业中的发展故事充满了创新、进取和成功的元素。从创立初期的艰苦创业到如今的全球领先品牌,BLACK&DECKER凭借其卓越的产品质量、技术创新和市场拓展能力,赢得了消费者的信任和市场的认可。未来,随着科技的不断进步和市场需求的不断变化,BLACK&DECKER将继续保持创新精神,推动电子行业的持续发展。

Adafruit公司的发展小趣事

2010年3月15日,BLACK&DECKER迎来了公司历史上的一个重要时刻——与史丹利公司合并组建史丹利百得公司。这一合并不仅使BLACK&DECKER获得了更强大的资源和市场支持,还为其未来的发展提供了更广阔的空间。合并后的史丹利百得公司致力于提供整合的五金工具、存储设备和安防系统解决方案,以满足全球消费者的多样化需求。通过整合双方的优势资源和技术力量,史丹利百得公司有望在电子行业中取得更加辉煌的成就。

综上所述,BLACK&DECKER公司在电子行业中的发展故事充满了创新、进取和成功的元素。从创立初期的艰苦创业到如今的全球领先品牌,BLACK&DECKER凭借其卓越的产品质量、技术创新和市场拓展能力,赢得了消费者的信任和市场的认可。未来,随着科技的不断进步和市场需求的不断变化,BLACK&DECKER将继续保持创新精神,推动电子行业的持续发展。

问答坊 | AI 解惑

分析几种基本信号运算电路

分析几种基本信号运算电路…

查看全部问答>

WinCE6.0 BIOS Boot Loader开机方式

请问各位大侠 这个要怎么设置啊?可以让CE直接启动,DOS启动过程麻烦,而且看着让人恶心。 Setupdisk.144和Bootdisk.144这两个文件怎么提取啊? 谢谢各位了!…

查看全部问答>

关于Android中加入USB主控驱动的问题

最近因为毕设需要,在移植Android1.5到urbetter s3c6410的板子上,需要使用板子上的USB来连接USB设备 内核编译选项添加了usb host side driver,全选了usb host controller drivers,但是依然用不了USB设备,请问需要怎么配置内核?需要给内核打补 ...…

查看全部问答>

嵌入式学习资料下载

www.chinaeda.cn QQ:763557435 电话:400-702-8848…

查看全部问答>

谁知道哪个公司的嵌入式开发板不错的,麻烦告诉下

我用的是VS2005+WINCE6.0,现在想买块开发板,不知道选哪个好,请前辈指点下…

查看全部问答>

嵌入式系统开发学习步骤

近来嵌入式挺火,于是大家都往这里挤。我想提醒大家的是,嵌入式马上也会成为如今的软件业。在你进来之前请先考虑清楚。但只要我们真的学精了一样东西,不管它将来变成什么样,哪怕最后只剩下一个人,那个人也一定就是你自己。 很多人以为搞嵌入 ...…

查看全部问答>

紧急求助pb3

RCC_APB2PeriphClockCm(RCC_APB2Periph_AFIO|APB2Periph_GPIOB,ENABLE);  GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,DISABLE);  GPIO_PinRemapConfig(GPIO_Remap_SWJ_Disable,DISABLE);  stm32_Init&nbs ...…

查看全部问答>

基础IO口设置有些不明白,求各位帮忙看看

板子上P1.0,P1.1两个口同时接到了触摸屏中断上,是这样设置的P1DIR=0x00;(输入模式),P1SEL=0x00;(普通IO口),P1IE=???????11;P1IES=???????1;P1OUT=??????00(电平置0), 请麻烦一下,怎么设置的P1IE,和P1IES,我原先理解的是该端口电平一旦置1就会 ...…

查看全部问答>

DAC大虾们到你们活动的时间了

弱弱的问下 用G2553能驱动12位和8位的DA嘛。。有谁写过用430驱动tlv5620和tlv5615…

查看全部问答>

易电源学习心得

全新 SIMPLE SWITCHER 易電源 納米模塊封裝尺寸為 2.5 x 3 x 1.2 mm,是市場上最薄的 1A 型 DC/DC 解決方案。安裝在屏蔽式 電感器上的 IC 在 35 mm2 的 電路板空間提供了一個完整的 解決方案,只需一個輸入電容、 一個輸出電容、一個 VCON ...…

查看全部问答>