Chinaunix首页 | 论坛 | 博客
  • 博客访问: 90307
  • 博文数量: 71
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 30
  • 用 户 组: 普通用户
  • 注册时间: 2015-05-13 20:27
文章分类

全部博文(71)

文章存档

2015年(71)

我的朋友

分类: 嵌入式

2015-07-02 19:23:26

原文地址:s5pc100串口配置 作者:草根老师

S5PC100 串口配置


一、数据通信的方式


数据通信的基本方式可分为并行通信和串行通信两种。

(1)并行通信:利用多条数据线将数据的各位同时传送。其特点是传输速度快,适用于短距离通信。

(2)串行通信:利用一条数据将数据一位一位地顺序传送,特点是通信线路简单,成本低,适用用于远距离通信。


二、UART介绍


UART英文名叫Universal Asynchronous Receiver and Transmitter,中文名叫通用异步收发器。

很多初学者,总是不明白什么是同步,什么异步。简单来说,同步方式指的是,在数据传输的过程中,需要一根时钟线同步。例如IIC,SPI总线,通过他们进行数据传输的时候,必须有一根时钟线,用来同步。异步方式指的是,数据传输的过程中,不需要时钟线,直接发送数据就可以了。例如我们常说的串口采用的就是异步方式,发送方和接收方之间是没有时钟信号线的,他们各自使用自己的时钟。

搞明白同步和异步之后,继续看UART。我们可以认为它是集成在微处理器内部的一个东西,由两部分组成:一个将串行比特流转换成微处理器可以使用的并行数据接收器(Rx)和一个将来自微处理器的并行数据转换为串行形式发送的发送器(Tx)。UART提供一些状态信息,比如接收器是否已满或者发送器是否为空。现在许多微处理器芯片都内置了片上UART 。


三、串口


串行接口简称串口,也称串行通信接口(通常指COM接口),是采用串行通信方式的扩展接口。串行通信是指,数据在传输的过程中,按位来进行传递,即一位一位的传递。

我们经常说的串口指的是RS-232C接口,它是在1970年由美国电子工业协会(EIA)联合贝尔系统调制解调器厂家及计算机终端生产厂家共同制定的用于串行通讯标准。它的全名是“数据终端设备(DTE)和数据通讯设备(DCE)之间串行二进制数据交换接口技术标准”。传统的RS-232-C接口标准有22根线,采用标准25芯D型插头座(DB25),后来使用简化为9芯D型插座(DB9),现在应用中25芯插头座已很少采用。 我们的S5PC100上的串口采用的是DB9。


虽然它给我提供了九根线,很多时候我们只用了两个线,RX和TX。

结合前面所说的UART,两个设备间通过串口通信,接线如下:


串口间的通信是一种异步的串行通信方式,为了保证输出的传输正确,必须要有一种协议来约定。在这里我们叫串行通信协议。如下图:


起始位:先发出一个逻辑”0”的信号,表示传输字符的开始。

数据位:可以是5-8位,常用的是8位数据位,表示一个字符。

奇偶校验位:在数据位的后面加上一位,使得”1”的个数为偶数(偶校验)或奇数(奇校验),以此来校验数据的传输正确性。

停止位:它一个字符数据结束的标志。可以是1位,也可以是2位。

空闲位:处于逻辑”1”状态,表示当前线路上没有数据传送。

还有一个非常重要的参数是波特率,它是衡量数据传送的速率。表示每秒钟传送的二进制位数。例如波特率为115200即表示每秒传送的

字符个数为115200/10 = 11520个。有人会问,不是除以8吗?我们的实际一个字符是8bit,但是串行通信的时候还需要起始位和停止位。通常情况下分别用一位表示,这样就是10位了。

四、S5PC100的UART


S5PC100的UART有四个独立的异步串行输入和输出端口。每个端口可以基于中断或者DMA进行操作。换句话说,UART控制器可以在CPU和UART之间产生一个中断或者DMA请求来传输数据。在系统时钟下,UART的第0个端口和第二个端口最高支持的波特率是115.2k bps,第1和第三端口最高支持的波特率是3Mbps。如果使用外部时钟提供UCLK,UART的速度还可以更高。每个UART通各含有两个64字节的接收和发送FIFO。



通过上图我们可以看到,每个UART控制器中大致分为发送器和接收器两部分,在发送器中如果当前UART处于FIFO模式,则有64字节的缓冲寄存器,一般在发送数据时CPU会将数据先暂存到这64字节中来,如果当前UART处于非FIFO模式,则这64字节的缓冲寄存器是没用的,我们只用到了这64字节中最低一个字节的缓冲寄存器来存放数据也叫做Transmit Holding Register,而关键的一点是在发送器中发送缓冲器中的数据并不是直接送到输出引脚上的,还必须要先送到发送移位寄存器也就是Transmit Shifter,然后再由Transmit Shifter送出到输出引脚。而接收端这边大概都是一样。发送移位寄存器和接收移位寄存器对数据的发送和接收都是在波特率发生器产生的波特率下来进行控制的。而波特率的产生也需要在时钟源的控制下才行。

对于UART的配置重点要配置好它的工作模式(s5pc100的UART可以设置成普通模式和红外模式),奇偶校验位,停止位和波特率。

在这里我们将UART配置成普通模式(轮训模式),无奇偶校验位,1位停止位,不使能FIFO,不使能中断,波特率为115200bps。下满对涉及到的寄存器简单说明:

ULCON:



根据我们的要求,这个寄存器应该配置如下:

[6]:0   [5:3]:00   [2]:0   [1:0]:11 

ULCON = 0x3;


UCON:

这里我们使用系统时钟PCLK,直接将这个寄存器的值设为0就可以了。

UCON = 0x0;

UFCON : FIFO控制寄存器


不使用FIFO,即将第0位设为0即可。

UFCON = 0;

 最后说一下波特率的设置:

前面我们已经将UART的时钟设为由PCLK(66MHZ)提供。S5PC100的UART波特率由UBRDIVn和UDIVSLOTn两个寄存器决定。计算规则如下:




我们要产生115200bps的波特率,就应该这样设置:


设置UART0的波特率为115200

DIV_VAL =(PCLK / (bps x 16) ) ?1

DIV_VAL = UBRDIVn(整数部分) + (num of 1's in UDIVSLOTn)/16(  数部分)

DIV_VAL = (PCLK / (bps x 16 ) ) ? 1

     = (66MHZ / (115200 * 16)) - 1

     =  34.8

其中整数部分存放在寄存器UBRDIVn中。小数部分是0.8,它由


(
num of 1's in UDIVSLOTn)/16 长生。即:

(num of 1's in UDIVSLOTn)/16 = 0.8 

num of 1's in UDIVSLOTn = 0.8 * 16 = 12.8 = 12



通过查表可以知道,12对应的是0xDDDD。即UDIVSLOTn的值为0xDDDD。


五、核心 代码



#define
 UART_0_RCV_OK(x)  (x = UART0.UTRSTAT0 & (1 << 0))

#define UART_0_SED_OK(x)  (x = UART0.UTRSTAT0 & (1 << 1))

void uart_0_init()

{

//设置GPIO的工作模式为UART_0_RXD,UART_0_TXD

GPA0.GPA0CON = GPA0.GPA0CON & ~(0xff << 0) | (0x22 << 0);

/*不使能PCLK为UART的时钟*/

CLK_GATE_D1.CLK_GATE_D1_4 &= (1 << 0);

/*UART0 数据传输

 *mode     :normal mode   [6]   0

 *parity   :no parity     [5:3] 000

 *stop bit :one stop bit  [2]   0

 *length   :8bit          [1:0] 11

 */

UART0.ULCON0 = 0x3;

/*UART0 控制寄存器

 *Clock select  :  PCLK    [11:10] 00

 *Transmit mode :  polling [3:2]   01

 *Receive  mode :  polling [1:0]   01

 */

 UART0.UCON0 = (0x1 << 2) | (0x1 << 0);

 /*不使能FIFO*/

 UART0.UFCON0 = 0x0;

 /*Disable AFC*/

 UART0.UMCON0 = 0x0;

 /*设置UART0的波特率为115200

  *DIV_VAL =(PCLK / (bps x 16) ) ?1

  *DIV_VAL = UBRDIVn(整数部分) + (num of 1's in UDIVSLOTn)/16(小数部分)

  *

  *DIV_VAL = (PCLK / (bps x 16 ) ) ? 1

  *        = (66MHZ / (115200 * 16)) - 1

  *        =  34.8

  *

  */

 UART0.UBRDIV0   = 34;

 UART0.UDIVSLOT0 = 0xDDDD;

 /*屏蔽UART0的所有中断*/

 UART0.UINTM0 = 0xf;

 /*使能PCLK为UART的时钟,UART开始工作*/

 CLK_GATE_D1.CLK_GATE_D1_4 &= (1 << 0);

 return;

}

/*发送一个字符*/

void send_char(unsigned char ch)

{

int flag = 0;

UART0.UTXH0 = ch;

while(!UART_0_SED_OK(flag));

return;

}

/*接受一个字符*/

unsigned char recv_char(void)

{

int flag;

unsigned char ch;

while(!UART_0_RCV_OK(flag));

ch =  UART0.URXH0;

return ch;

}


最后附上整个实验的代码:uart.rar

阅读(536) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~