您的位置:首页 > 其它

S5PV210串口通信学习

2016-07-23 19:23 351 查看

ARM裸机学习——S5PV210串口通信

一、串口通信相关概念及原理

异步串行:universal asynchronous reciver and transmitter,通用异步收发器,简称UART

同步串行:SPI(Serial Peripheral interface),串行外围设备接口

1.电平信号

在串口中使用2根线,一根是GND,一根是信号线;通过比较2根线之间的电压差得到信号,如电压差为5V表示1,为0V表示0.

2.差分信号

差分信号也是2根线,没有表示GND的线了,都是信号线,由信号线之间的电压差来表示1和0

3.TTL电平

TTL电平(全名是晶体管-晶体管逻辑集成电路(Transistor-Transistor Logic)),一般用5V表示1,0V表示0

4.RS232电平

RS232电平,逻辑1的电平为-3~-15V,逻辑0的电平为+3~+15V,注意电平的定义反相了一次。

5.并行接口和串行接口

这2个其实就是表示同时可以传递的数据量是多少,在使用电平信号传递时,传递一个二进制位需要1根线,如果有3根线(RXD,TXD,GND),那么一次就能同时传递2个二进制位,要传递8位二进制也就是一个字符,则需要9根线;如果采用差分信号,传递一个二进制位就需要2根线,要传递8位二进制位的话就需要16根线了。

6.起始位、数据位、奇偶校验位、停止位

这4个组合起来就是一个通信单元,暂且叫做一帧数据(注意:实际上数据帧是表示N字节,在这N字节中有包括信息头、数据、校验等多个8位二进制单元组合而成,除了数据以外,其他的是自己定义的),通常数据位用8位二进制来表示,这是因为我们通常我们通过串口传递的数据按照字符格式也就是ASCII码进行编码,刚好就是8位。奇偶校验位就是计算出数据位中1的个数是多少,奇数个校验位就是1,偶数个就是0 。停止位就表示这一个通信单元的数据已经发送完毕,可以开始下一次发送了,或者不发送,一般用1位,1.5位,2位等来表示停止位

7.波特率

波特率就是表示每1秒可以发送多少个二进制位,如波特率位115200,那么发送一个二进制位的时间就是1/115200,波特率不能随便乱设置,一般从几个常用的值中选择一个就可以了,如9600(51单片机)、115200(高速单片机、ARM),发送方和接收放的波特率必须设成一致。

8.同步和异步

同步:发送方和接收方必须工作在同一个时钟频率,发送方和接收方随时都在通信

异步:发送方和接收方工作时钟频率由自己决定,不一定随时在发,发一会儿,休息一会儿再发

9.单工通信,半工通信,全工通信

单工:单向通信,只有2根线,要么只能发送,要么只能接收,发送方和接收方是固定方向的

半工:可以双向通信,有3根线,但是同一时刻只能发送或者接收,不能同时进行

全工:3根线,发送的同时也可以接收

10.串口通信的接口DB9





早期的计算机由于主要是用串口来进行通信,对数据的准确度要求严格,因此加入了流控,也就是除GND、TXD、RXD其他的引脚。

而现在可以使用其他的方式来进行通信,例如USB、Internet,所以基本上就三根线

二.S5PV210的串口

1.S5PV210有4个串口,分别是UART0,UART1,UART2,UART3,我所使用的开发板只引出了2个串口UART0和UART2

简介:

S5PV210每个串口支持的最大波特率位3Mbps。

每个串口都有2个FIFO来接收和发送数据:串口0,256字节;串口1,64字节;串口2、3,16字节

每个UART都包含一个transmitter(发送器)、receiver(接收器)、control unit(控制单元)、baud-rate generator(波特率产生器)

baud-rate generator(波特率产生器)使用的时钟是PCLCK_PSYS或者SCLK_UART

原理图:



Peripheral BUS:外围设备总线(APB总线),也是时钟来源

transmitter:包含一个transmitter buffer register(发送缓冲区,将要发送的数据编码后放入这个缓冲区)和transmitter shifter(发送移位器,硬件自动完成移位,将发送缓冲区的数据移位到Tx信号线上)

receiver:同transmitter。

以下摘自《朱有鹏老师物联网大讲堂-ARM裸机串口通信部分课堂记录》

(1)串口通信分为发送/接收2部分。发送方一般不需要(也可以使用)中断即可完成发送,接收方必须(一般来说必须,也可以轮询方式接收)使用中断来接收。

(2)发送方可以选择使用中断,也可以选择不使用中断。使用中断的工作情景是:发送方先设置好中断并绑定一个中断处理程序,然后发送方丢一帧数据给transmitter,transmitter发送耗费一段时间来发送这一帧数据,这段时间内发送方CPU可以去做别的事情,等transmitter发送完成后会产生一个TXD中断,该中断会导致事先绑定的中断处理程序执行,在中断处理程序中CPU会切换回来继续给transmitter放一帧数据,然后CPU切换离开;不使用中断的工作情景是:发送方事先禁止TXD中断(当然也不需要给相应的中断处理程序了),发送方CPU给一帧数据到transmitter,然后transmitter耗费一段时间来发送这帧数据,这段时间CPU在这等着(CPU没有切换去做别的事情),待发送方发送完成后CPU再给它一帧数据继续发送直到所有数据发完。CPU是怎么知道transmitter已经发送完了?原来是有个状态寄存器,状态寄存器中有一个位叫发送缓冲区空标志,transmitter发送完成(发送缓冲区空了)就会给这个标志位置位,CPU就是通过不断查询这个标志位为1还是0来指导发送是否已经完成的。

(3)因为串口通信是异步的,异步的意思就是说发送方占主导权。也就是说发送方随时想发就能发,但是接收方只有时刻等待才不会丢失数据。所以这个差异就导致发送方可以不用中断,而接收方不得不使用中断模式。

2.S5PV210串口编程
(1).根据底板原理图发现串口TXD、RXD分别接到了GPA0_1和GPA0_0上,需将GPA0_1和GPA0_0配置成UART模式,即设置GPA0CON[0]为0x0010,GPA0CON[1]为0x0010


#define GPA0CON 0xE0200000
#define rGPA0CON (*(volatile unsigned int *)GPA0CON)

rGPA0CON &= ~0xff;
rGPA0CON |= 0x22;


(2).设置相关寄存器(本次使用的是UART0,没有用到中断,所以就不配置中断相关的寄存器)
a.ULCON0: Specifies the UART Channel 0 Line Control Register
b.UCON0:Specifies the UART Channel 0 Control Register
c.UFCON0:Specifies the UART Channel 0 FIFO Control Register
d.UMCON0:Specifies the UART Channel 0 Modem Control Register
e.UTRSTAT0:Specifies the UART Channel 0 Tx/Rx Status Register
f.UTXH0:Specifies the UART Channel 0 Transmit Buffer Register
g.URXH0:Specifies the UART Channel 0 Receive Buffer Register
h.UBRDIV0:Specifies the UART Channel 0 Baud Rate Divisor Register
i.UDIVSLOT0:Specifies the UART Channel 0 Dividing Slot Register


/*UART*/
#define ULCON0      0xE2900000
#define UCON0       0xE2900004
#define UFCON0      0xE2900008
#define UMCON0      0xE290000C
#define UTRSTAT0    0xE2900010
#define UTXH0       0xE2900020
#define URXH0       0xE2900024
#define UBRDIV0     0xE2900028
#define UDIVSLOT0   0xE290002C

#define rULCON0         (*(volatile unsigned int *)ULCON0)
#define rUCON0          (*(volatile unsigned int *)UCON0)
#define rUFCON0         (*(volatile unsigned int *)UFCON0)
#define rUMCON0         (*(volatile unsigned int *)UMCON0)
#define rUTRSTAT0       (*(volatile unsigned int *)UTRSTAT0)
#define rUTXH0          (*(volatile unsigned int *)UTXH0)
#define rURXH0          (*(volatile unsigned int *)URXH0)
#define rUBRDIV0        (*(volatile unsigned int *)UBRDIV0)
#define rUDIVSLOT0      (*(volatile unsigned int *)UDIVSLOT0)

/*GPIO*/
#define GPA0CON     0xE0200000

#define rGPA0CON (*(volatile unsigned int *)GPA0CON)

void uart_init(void)
{
/*初始化GPA0CON*/
rGPA0CON &= ~0xff;
rGPA0CON |= 0x22;

/*初始化UART0相关寄存器*/
rULCON0 = 0x3;      //数据位为8位
rUCON0 = 0x5;       //时钟源选择PCLK_PSYS,无中断
rUFCON0 = 0x0;      //关闭FIFO
rUMCON0 = 0x0;      //关闭流控AFC

/*
*波特率设置
*本次使用的是PCLK_PSYS,而根据官方手册得出PCLK_PSYS = 66MHz,实际上通过计算得出应为66.7MHz
*   DIV_VAL = UBRDIVn + (num of 1's in UDIVSLOTn)/16
*   DIV_VAL = (PCLK / (bps x 16)) −1
*   or
*   DIV_VAL = (SCLK_UART / (bps x 16)) −1
*   (num of 1's in UDIVSLOTn)/16 = 余数
*
*1.用66MHz来计算
*   DIV_VAL =  (66000000/115200/16-1) = 34.8
*   0.8 * 16 = 12.8     13个1  通过查看手册UDIVSLOT0的值应设置为0xDFDD(1101_1111_1101_1101b)
***************************************************************************************************
*2.用66.7MHz来计算
*   DIV_VAL = (66700000/115200/16-1) = 35.2
*   0.2 * 16 = 3.2      3个1  通过查看手册UDIVSLOT0的值应设置为0x0888(0000_1000_1000_1000b)
*/
rUBRDIV0 = 0x22;    //34
rUDIVSLOT0 = 0xDFDD;

//rUBRDIV0 = 0x23;  //35
//rUDIVSLOT0 = 0x0888;

}
//UART0发送程序,按字符发送
void uart_send(char c)
{
//UTRSTAT0[1]   0:空
while(!(rUTRSTAT0 & 0x2));
rUTXH0 = c;
}

//UART0接收程序
char uart_receive(void)
{
//UTRSTAT0[0]   0:空
while(!(rUTRSTAT0 & 0x1));
return (rURXH0 & 0xff);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息