S5PV210串口通信学习

来源:互联网 发布:怎样手机做淘宝客赚钱 编辑:程序博客网 时间:2024/05/18 02:11

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
DB9接口外观图
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);}
0 0