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); }
相关文章推荐
- #新闻拍一拍# IBM 招聘广告要求应聘者具备至少 12 年 K8S 使用经验
- vivi下重新调整分区
- ARM Linux系统启动
- Linux及ARM Linux程序开发笔记(零基础入门篇)
- 深入分析Visual C++进行串口通信编程的详解
- C#串口通信程序实例详解
- 零基础入门篇之Linux及Arm-Linux程序开发笔记
- 我的 ARM+Linux 学习路线
- 64位Ubuntu 14.04上使用musleabi最小化交叉编译Android版PHP7
- 关于ARM启动的一篇文章
- ARM 的堆栈初始化详解
- ARM条件码与CPSR标志位的关系
- 加载/存储指令
- 关于ARM 汇编的一些疑问
- ARM汇编伪指令介绍
- linux的防火墙及arm与虚拟机共享
- 编译单个驱动的Makefile文件。
- ARM Linux系统调用的原理
- Android LKM Rootkit,查找sys_call_table
- LKM Tricks to Android Devices,查找sys_call_table