本章目标:

了解UART原理;
掌握S3C2410/S3C2440中UART的使用

11.1 UART原理及UART内部使用方法

11.1.1 UART原理说明

    UART用于传输串行数据:
    发送数据时,CPU将并行数据写入UART,UART按照一定的格式在一根电线上串行发出;
    接收数据时,UART检测另一根电线上的信号,将串行收集放在缓冲区中,CPU即可读取
UART获得这些数据。
    UART之间以全双工方式传输数据,最精简的连接方式只有3根线:TxD、RxD、Gnd。
    UART使用标准的TTL/CMOS逻辑电平(0~5V、0~3.3V、0~2.5V或0~1.8V)来表示数据,
高电平表示1,低电平表示0.为了增强数据抗干扰能力、提高传输长度,通常将TTL/CMOS
逻辑电平转换为RS-232逻辑电平,3~12V表示0,-3~-12V表示1。

11.1.2 S3C2410/S3C2440 UART的特性

    S3C2410/S3C2440中UART功能类似,有3个独立的通道,每个通道都可以工作于中断
或DMA模式。即UART可以发出中断或DMA请求以便在UART、CPU间传输数据。
    UART由波特率发生器、发送器、接收器和控制逻辑组成。
    使用系统时钟时,S3C2410的UART波特率可以达到230.4Kbit/s,S3C2440则可以达到
115.2Kbit/s;如果使用UEXTCLK引脚提供的外部时钟,则可以达到更高的波特率。波特率
可以通过编程进行控制。
    S3C2410 UART的每个通道都有16字节的发送FIFO和16字节的接收FIFO,S3C2440 UART
的FIFO深度为64。
    S3C2410/S3C2440 UART的每个通道支持的停止位有1、2位,数据位有5、6、7或8位,
支持校验功能,另外还有红外发送/接收功能。

11.1.3 S3C2410/S3C2440 UART的使用

    在使用UART之前需要设置波特率、传输格式(多少数据位、是否使用校验位、是奇校验
还是偶校验、有多少停止位、是否使用流量控制);对于S3C2410/S3C2440,还要选择所涉及
管脚为UART功能、选择UART通道的工作模式为中断模式或DMA模式。设置好之后,向某个寄存器
中写入数据即可发送,读取某个寄存器即可得到接收到的数据。可以通过查询状态寄存器或
设置中断来获知数据是否已经发送完毕、是否已经接收到数据。
    针对上述过程,下面一一说明。
1.将所涉及的UART通道管脚设为UART功能
2.UBRDIVn寄存器(UART BAUD RATE DIVISOR):设置波特率
    S3C2410 UART 的时钟源有两种选择:PCLK、UEXTCLK;S3C2440 UART的时钟源有
三种选择:PCLK、UEXTCLK、FCLK/n,其中n的值通过UCON0~UCON2联合设置。
    根据给定的波特率、所选择的时钟源的频率,可以通过如下公式计算UBRDIVn寄
存器(n为0~2,对应3个UART通道)的值。
    UBRDIVn = (int)(UART clock / (buad rate * 16)) - 1
    上面计算出来的UBRDIVn寄存器不一定是整数,只要其误差在1.87%之内即可。误
差计算公式如下:
    tUPCLK = (UBRDIVn + 1) * 16 * 1Frame/(UART clock)    //实际的UART时钟
    tUEXACT = 1Frame / baud-rate                  //理论的UART时钟
    UART error = (tUPCLK - tUEXACT) / tUEXACT * 100%     //误差
3.ULCONn寄存器(n:0~2)(UART LINE CONTROL):设置传输格式
4.UCONn寄存器(UART CONTROL)
    UCONn寄存器用于选择UART时钟源、设置UART中断方式等。由于S3C2410的UART
只有两个时钟源,S3C2440有3个时钟源,所以在选择和设置时钟源时有所不同。
    S3C2410的UCONn寄存器格式如下表11.2所示。
    S3C2440的UCONn寄存器在UART时钟的选择方面与S3C2410有所不同,从位[10]往上
的位含义不一样,并且原来的位[4]用于徐娜则是否发出“break”信号,这些位的含义
如表11.3所示。

    UCON0、UCON1、UCON2这三个寄存器的位[15:12]一起用来确定n的值,它们的意义如下。
    (1)UCON2[15]:“FCLK/n”使能位。
    它等于0时,禁止使用“FCLK/n”作为UART时钟源;等于1时,可以用作UART时钟源。
    (2)n的值设置。
    UCON0[15:12]、UCON1[15:12]、UCON2[14:12]三者用于设置n的值,当其中一个被射程非
0时,其他两个必须为0.
    ① n的值处于7~21处时,UART时钟 = FCLK/(divider + 6),divider 为UCON0[15:12]的值,大于0。 
    ② n的值处于22~36时,UART时钟 = FCLK/(divider + 21),divider为UCON1[15:12]的值,大于0。
    ③ n的值处于37~43时,UART时钟 = FCLK/(divider + 36),divider为UCON2[14:12]的值,大于0.
    ④ UCON0[15:12]、UCON1[15:12]、UCON2[14:12]都等于0时,UART时钟:FCLK/44。
5.UFCONn寄存器(UART FIFO CONTROL)、UFSTATn寄存器(UART FIFO STATUS)
    UFCONn寄存器用于设置是否使用FIFO,设置个FIFO的触发值。并可以通过设置UFCONn
寄存器来复位个寄存器。
    读取UFSTATn寄存器可以知道各个FIFO是否已经满、其中有多少个数据。
    不使用FIFO时,可以认为FIFO的深度为1,使用FIFO时,S3C2410的FIFO深度为16,
S3C2440的FIFO深度为64.这两类寄存器各位的含义请参考数据手册,后面的实例部分没有
使用FIFO。
6.UMCONn寄存器(UART MODEM CONTROL)、UMSTATn寄存器(UART MODEM STATUS)
    这两类寄存器用于流控,这里不介绍。
7.UTRSTATn寄存器(UART TX/RX STATUS)
    UTRSTATn寄存器用于表明数据是否已经发送完毕、是否已经接收到数据,格式如表11.4
所示。缓冲区起始就是图11.3中的FIFO,只不过不使用FIFO功能时可以认为其深度为1。

8.UERSTATn寄存器(UART ERROR STATUS)
    用于表示各种错误是否发生,位[0]~位[3]为1时分别表示溢出错误、校验错误、帧错误、
检测到“break”信号。读取这个寄存器时,它会自动清零。
    注意:接收数据时,如果使用FIFO,则UART内部会使用一个“错误FIFO”来表明接收FIFO
中哪个数据在接收过程中发生了错误。CPU只有在读出这个错误的数据时,才会察觉到发生了错
误。要想清除“错误FIFO”,则必须读出错误的数据,并读出UERSTATn寄存器。
9.UTXHn寄存器(UART TRANSMIT BUFFER REGISTER)
    CPU将数据写入这个寄存器,UART即将它保存到缓冲区中,并自动发送出去。
10.URXHn寄存器(UART RECEIVE BUFFER REGISTER)
    当UART接收到数据时,CPU读取这个寄存器,即可获得数据。

11.2 UART 操作实例

11.2.1 代码详解

    本实例代码在/work/hardware/uart目录下。目的是在串口上输入一个字符,单板收到后将
它的ASCII值加1后,从串口输出。
    首先设置MPLL提高系统时钟,令PCLK为50MHz,UART将选择PCLK作为时钟源。将代码复制到
SDRAM之后,调用main函数。这些代码与第10章相似。重点在于main函数对UART0的初始化、收发
数据,这由3个函数实现:usat0_init、getc和putc,它们在serial.c文件中。
1.UART初始化
    uart0_init函数代码如下:
 #define PCLK              50000000    //init.c中的clock_init函数设置PCLK为50MHz
#define UART_CLK PCLK //UART0的时钟源设为PCLK
#define UART_BAUD_RATE 115200
#define UART_BRD ((UART_CLK / (UART_BAUD_RATE * 16)) - 1) /*
*初始化UART0
*115200, 8N1, 无流控
*/
void uart0_init(void)
{
GPHCON |= 0xa0; //GPH2、GPH3用作TXD0、RXD0
GPHUP = 0x0c; //GPH2、GPH3内部上拉 ULCON0 = 0x03; //波特率:115200,8N1
UCON0 = 0x05; //查询方式,UART时钟源为PCLK
UFCON0 = 0x00; //不使用FIFO
UMCON0 = 0x00; //不使用流控
UBRDIV0 = UART_BRD; //波特率:115200
}

serial.c->uart0_init()

2.发送字符的函数
    本实例不使用FIFO,发送字符前,先判断上一个字符是否已经发送出去。如果没有,
则不断查询UTRSTAT0寄存器的位[2],当它为1时表示已经发送完毕。于是,即可向UTXH0寄
存器中写入要发送的字符。代码如下(宏TXD0READY被定义为“(1 << 2)”):
 /*
*发送一个字符
*/
void putc(unaigned char c)
{
/*等待,直到发送缓冲区中的数据已经全部发送出去*/
while(!(UTRSTAT0 & TXD0READY)); /*向UTXH0寄存器中写数据,UART自动将其发送出去*/
UTXH0 = c;
}

serial.c->putc()

3.接收字符的函数
    试图读取数据前,先查询UTRSTAT0寄存器的位[1],当它为1时,表示接收缓冲区中有数据。
于是,即可读取URXH0得到数据。代码如下(宏RXD0READY被定义为“(1)”):
 /*
*接收字符
*/
unsigned char getc(void)
{
/*等待,知道接收缓冲区中有数据*/
while(!(UTRSTAT0 & RXD0READY)); /*直接读取URXH0寄存器,即可获得接收到的数据*/
return URXH0;
}

serial.c->getc()

4.主函数
    初始化完UART0之后,不断地读取串口数据,并判断它是否是数据或字符。如果是的话,
将它加1后从串口输出。代码如下:
 #include "serial.h"

 int main()
{
unsigned char c;
uart0_init(); //波特率:115200,8N1 while()
{
//从串口接收数据后,判断其是否为数字或字母,若是则加1后输出
c = getc();
if(isDigit(c) || (isLetter(c)))
putc(c+);
} return ;
}

main.c

11.2.2 实例测试

1.PC上的串口工具推荐
    Windows下推荐使用SecureCRT工具,Linux下推荐使用kermit。
    下面介绍在Linux下安装、使用kermit的方法。
    确保Linux能上网,然后使用下面命令安装,会安装一个kermit命令。
$ sudo apt-get install ckermit
    在使用kermit之前,先建立一个配置文件,在/home/book(假设用户名为book)目录下创
建名为.kermrc的文件,内容如下:
 set line /dev/ttyS0
set speed
set carrier-watch off
set handshake none
set flow-control none
robust
set file type bin
set file name lit
set rec pack
set send pack
set window

配置kermrc

    然后,运行“$ sudo kermit -c”命令即可开启串口:要关闭串口,可以先输入
“Ctrl+\”,然后按住“C”键,最后输入“exit”后回车。
2. 测试方法
    首先使用串口线将开发板的COM0和PC的串口连接,打开PC上的串口工具并设置其波
特率为115200、8N1。
    然后,在uart目录下运行make命令生成可执行文件uart.bin,将它烧入NAND Flash
中运行。
    最后,在PC上串口工具中输入数字或字母,可以看到输出另一个字符(加了1):如果
输入其他字符,则无输出。
    /work/hardware/stdio目录下的程序在串口0上实现printf、scanf等函数,它使用
scanf、sscanf和printf等函数从串口接收一个十进制数字序列,然后将它转换为十六进制
输出。步骤与UART实例相似,读者可自行操作。
附:代码:
链接: https://pan.baidu.com/s/1kV24a9L 密码: tfab

JZ2440 裸机驱动 第11章 通用异步收发器UART的更多相关文章

  1. JZ2440 裸机驱动 第13章 LCD控制器(1)

    本章目标  了解LCD显示器的接口及时序: 掌握S3C2410/S3C2440 LCD控制器的使用方法: 了解帧缓冲区的概念,掌握如何设置帧缓冲区来显示图像: 13.1 LCD和LCD控制器 13.1 ...

  2. JZ2440 裸机驱动 第12章 I2C接口

    本章目标: 了解I2C总线协议: 掌握S3C2410/S3C2440中I2C接口的使用方法: 12.1 I2C总线协议及硬件介绍 12.1.1 I2C总线协议 1 I2C总线的概念 2 I2C总线的信 ...

  3. JZ2440 裸机驱动 第9章 中断体系结构

    本章目标:     了解ARM体系CPU的7种工作模式     了解S3C2410/S3C2440中断体系结构     掌握S3C2410/S3C2440的中断服务程序的编写方法 9.1 S3C241 ...

  4. JZ2440 裸机驱动 第7章 内存管理单元MMU

    本章目标:     了解虚拟地址和物理地址的关系:     掌握如何通过设置MMU来控制虚拟地址到物理地址的转化:     了解MMU的内存访问权限机制:     了解TLB.Cache.Write ...

  5. JZ2440 裸机驱动 第6章 存储控制器

    本章目标:     了解S3C2410/S3C2440地址空间的布局     掌握如何通过总线形式访问扩展的外设,比如内存.NOR Flash.网卡等 ························ ...

  6. JZ2440 裸机驱动 第5章 GPIO接口

    本章目标:     掌握嵌入式开发的步骤:编程.编译.烧写程序.运行     通过GPIO的操作了解软件如何控制硬件 5.1 GPIO硬件介绍     S3C2440A有130个多功能输入/输出口引脚 ...

  7. JZ2440 裸机驱动 第14章 ADC和触摸屏接口

    本章目标:     了解S3C2410/S3C2440和触摸屏的结构:     了解电阻触摸屏的工作原理和等效电路图:     了解S3C2410/S3C2440触摸屏控制器的多种工作模式:     ...

  8. JZ2440 裸机驱动 第10章 系统时钟和定时器

    本章目标      了解S3C2410/S3C2440的时钟体系结构     掌握通过设置MPLL改变系统时钟的方法     掌握在不同的频率下设置存储控制器的方法     掌握PWM定时器的用法   ...

  9. JZ2440 裸机驱动 第8章 NAND Flash控制器

    本章目标  了解NAND Flash 芯片的接口 掌握通过NAND Flash控制器访问NAND Flash的方法 8.1 NAND Flash介绍和NAND Flash控制器使用     NAND ...

随机推荐

  1. python dict 构造函数性能比较

    from time import time t1 = time() {i: "%d" % i for i in range(5000)} t2 = time() print(t2- ...

  2. sgu 121. Bridges painting 列举情况 难度:1

    121. Bridges painting time limit per test: 0.25 sec. memory limit per test: 4096 KB New Berland cons ...

  3. pyinstaller又踩一坑, configparser os.mknod

    在使用pyinstaller时,有使用configparser模块. 使用相对路径.在pycharm中测试,正常,打包成exe,就出错了 换用绝对路径, print(os.getcwd()) fp_d ...

  4. 远程访问Centos6.5上的mysql或者mariadb(navicat)

    问题背景 1 环境 物理主机操作系统Centos6.5 虚拟主机KVM:centos6.5 64位min版本(虚拟机安装有台) 网络:桥接模式 2 问题 yum安装mariadb10/mysql6.5 ...

  5. L1-016 查验身份证

    一个合法的身份证号码由17位地区.日期编号和顺序编号加1位校验码组成.校验码的计算规则如下: 首先对前17位数字加权求和,权重分配为:{7,9,10,5,8,4,2,1,6,3,7,9,10,5,8, ...

  6. 用MyEclipse JPA创建项目(四)

    MyEclipse 3.15 Style——在线购买低至75折!火爆开抢>> [MyEclipse最新版下载] 本教程介绍了MyEclipse中的一些基于PA的功能. 阅读本教程时,了解J ...

  7. Python装饰器的通俗理解

    转载:http://blog.csdn.net/u013471155 在学习Python的过程中,我相信有很多人和我一样,对Python的装饰器一直觉得很困惑,我也是困惑了好久,并通过思考和查阅才能略 ...

  8. vector类转换Mat类

    前言 一个个数据push back到vector之后,可以使用Mat()函数将vector类型转换为Mat类型. 在opencv中Mat类的构造函数中有一个构造函数可以直接把vector类转换为Mat ...

  9. 【codeforces div3】【E. Cyclic Components】

    E. Cyclic Components time limit per test 2 seconds memory limit per test 256 megabytes input standar ...

  10. Python模块之virtualenvwrapper

    Python的virtualenv工具可以创建隔离的Python环境, virtualenvwrapper是virtualenv的进一步封装工具,可以让它更好用. 安装 Linux 系统下: pip ...