S5PV210串口通信

以下内容源于《朱有鹏物联网大讲堂》,如有侵权,请告知删除。

一、电子通信的一些概念
1、同步通信和异步通信

发送方和接收方按照同一个时钟节拍工作就叫同步;发送方和接收方按照自己的节拍工作就叫异步;
同步通信中,通信双方按照统一节拍工作,所以配合很好;一般需要发送方给接收方发送信息同时发送时钟信号,接收方根据发送方给它的时钟信号来安排自己的节奏。同步通信用在通信双方信息交换频率固定,或者经常通信时。
异步通信又叫异步通知。在双方通信的频率不固定时(有时3ms收发一次,有时3天才收发一次)不适合使用同步通信,而适合异步通信。异步通信时接收方不必一直在意发送方,发送方需要发送信息时会首先给接收方一个信息开始的起始信号,接收方接收到起始信号后就认为后面紧跟着的就是有效信息,才会开始注意接收信息,直到收到发送方发过来的结束标志。
2、电平信号和差分信号
电平信号和差分信号是用来描述通信线路传输方式的,即如何在通信线路上表达1和0。
电平信号的传输线中有一个参考电平线(一般是GND),然后信号线上的信号值是由信号线电平和参考电平线的电压差决定。
差分信号的传输线中没有参考电平,所有都是信号线,1和0的表达依靠信号线之间的电压差。
电平信号的2根通信线之间的电平差异容易受到干扰,传输容易失败;差分信号不容易受到干扰因此传输质量比较稳定,现代通信一般都使用差分信号。
3、并行接口和串行接口
串行、并行主要是考虑通信线的根数,就是发送方和接收方同时可以传递的信息量的多少;
譬如在电平信号下,1根参考电平线+1根信号线可以传递1位二进制;如果我们有3根线(2根信号线+1根参考线)就可以同时发送2位二进制;如果想同时发送8位二进制就需要9根线。在差分信号下,2根线(彼此差分)可以同时发送1位二进制;如果需要同时发送8位二进制,需要16根线。
似乎并行接口比串行接口要快(串行接口一次只能发送1位二进制,而并行接口一次可以发送多位二进制)要更优秀;但是实际上串行接口才是王道,用的比较广。因为更省信号线,而且对传输线的要求更低、成本更低;而且串行时可以通过提高通信速度来提高总体通信性能,不一定非得要并行。经过这么多年发展,最终胜出的是:异步、串行、差分,譬如USB和网络通信。

二、串口通信的基本概念
1、串口通信的特点:异步、电平信号、串行
异步:串口通信的发送方和接收方之间是没有统一的时钟信号的。
电平信号:串口通信出现时间早,速率较低,传输的距离较近,所以干扰还不太明显,因此当时使用了电平信号传输。后期出现的传输协议都改成差分信号传输了。
串行通信:串口通信每次同时只能传输1个二进制位。
2、RS232电平和TTL电平
(1)电平信号是用信号线电平减去参考线电平得到电压差,这个电压差决定了传输值是1还是0。
(2)在电平信号时多少V代表1,多少V代表0不是固定的,取决于电平标准。
譬如RS232电平中-3V~-15V表示1;+3~+15V表示0;TTL电平则是+5V表示1,0V表示0。
RS232的电平定义比较大,适合干扰大、距离远的情况;TTL电平电压范围小,适合距离近且干扰小的情况。
台式电脑后面的串口插座就是RS232接口的,在工业上用串口时都用这个,传输距离小于15米;TTL电平一般用在电路板内部两个芯片之间。
3、波特率
(1)波特率(bandrate),指的是串口通信的速率,也就是串口通信时每秒钟可以传输多少个二进制位。
譬如每秒种可以传输9600个二进制位(传输一个二进制位需要的时间是1/9600秒,也就是104us),波特率就是9600。
(2)串口通信的波特率不能随意设定,而应该在一些值中去选择。
一般最常见的波特率是9600或者115200(低端单片机如51常用9600,高端单片机和嵌入式SoC一般用115200)。
为什么波特率不可以随便指定?第一,通信双方必须事先设定相同的波特率这样才能成功通信,如果发送方和接收方按照不同的波特率通信则根本收不到,因此波特率最好是大家熟知的而不是随意指定的。第二,常用的波特率经过长久发展,就形成了共识,大家常用就是9600或者115200。
4、起始位、数据位、奇偶校验位、停止位
串口通信时,一个通信单元由“起始位+数据位+奇偶校验位+停止位”组成。
起始位表示发送方要开始发送一个通信单元;数据位是一个通信单元中发送的有效信息位;奇偶校验位是用来校验数据位,以防止数据位出错的;停止位是发送方用来表示本通信单元结束标志的。
起始位的定义是串口通信标准事先指定的,是由通信线上的电平变化来反映的。
数据位是本次通信真正要发送的有效数据,串口通信一次发送多少位有效数据是可以设定的(一般可选的有6、7、8、9,99%情况下我们都是选择8位数据位。因为我们一般通过串口发送的文字信息都是ASCII码编码的,而ASCII码中一个字符刚好编码为8位。)
奇偶校验位是用来给数据位进行奇偶校验(把待校验的有效数据逐个位的加起来,总和为奇数奇偶校验位就为1,总和为偶数奇偶校验位就为0)的,可以在一定程度上防止位反转。
停止位的定义是串口通信标准事先指定的,是由通信线上的电平变化来反映的。常见的有1位停止位,1.5位停止位,2位停止位等。99%情况下都是用1位停止位。
串口通信时因为是异步通信,所以通信双方必须事先约定好通信参数,这些通信参数包括:波特率、数据位、奇偶校验位、停止位(串口通信中起始位定义是唯一的,所以一般不用选择)
三、串口通信的基本原理
1、单工通信、双工通信、半双工通信
如果只能A发B收则单工,A发B收或者B发A收(两个方向不能同时)叫半双工,A发B收同时B发A收叫全双工。
2、三根通信线:Rx Tx GND
任何通信都要有信息传输载体,或者是有线的或者是无线的。串口通信是有线通信,是通过串口线来通信的。
串口通信线最少需要2根(GND和信号线),可以实现单工通信,也可以使用3根通信线(Tx、Rx、GND)来实现全双工。
一般开发板都会引出SoC上串口引脚直接输出的TTL电平的串口(X210开发板没有),插座用插针式插座,每个串口引出的都有3个线(Tx、Rx、GND),可以用这些插座直接连接外部的TTL电平的串口设备。
3、收发双方事先规定好通信参数(波特率、数据位、奇偶校验位、停止位等)
串口通信属于基层基本性的通信规约,它自己本身不会去协商通信参数,需要通信前通信双方事先约定好通信参数(一般4个最重要的);
串口通信的任何一个关键参数设置错误,都会导致通信失败。譬如波特率调错了,发送方发送没问题,接收方也能接收,但是接收到全是乱码。
4、信息以二进制流的方式在信道上传输
串口通信的发送方每隔一定时间(时间固定为1/波特率,单位是秒)将有效信息(1或者0)放到通信线上去,逐个二进制位的进行发送。
接收方通过定时(起始时间由读到起始位标志开始,间隔时间由波特率决定)读取通信线上的电平高低来区分内容是1还是0。依次读取数据位、奇偶校验位、停止位,停止位就表示这一个通信单元(帧)结束,然后中间是不定长短的非通信时间(发送方有可能紧接着就发送第二帧,也可能半天都不发第二帧,这就叫异步通信),下来就是第二帧……
波特率非常重要,波特率错了整个通信就乱套了;数据位、奇偶校验位、停止位也很重要,否则可能认不清数据;通过串口不管发数字、还是文本还是命令还是什么,都要先对发送内容进行编码,编码成二进制再进行逐个位的发送。
串口发送的一般都是字符,一般都是ASCII码编码后的字符,所以一般设置数据位都是8位,方便刚好一帧发送1个字符。
四、DB9接口介绍
(1)DB9接口是串口通信早期比较常用的一种规范化接口。
(2)串行通信在早期是计算机与外界通信的主要手段,那时候的计算机都有标准配置的串口以实现和外部通信。那时候就定义了一套标准的串口规约,DB9接口就是标准接口。
(3)DB9接口中有9根通信线,其中3根很重要,为GND、Tx、Rx,必不可少;剩余6根都是和流控有关的,现代我们使用串口都是用来做调试一般都禁用流控,不然可能发生意想不到的问题,所以这6根没用。

五、串口通信实战编程1
这节课还是看看寄存器为主,只是引子,看一个就可以,
这里写图片描述
这里写图片描述

串口初始化的关键步骤:
1.初始化串口的Tx和Rx引脚所对应的GPIO:GPA0CON(0xE0200000):bit[3:0] = 0b0010,bit[7:4] = 0b0010,即把引脚设置为UART_?(这里为0)的作用状态

这里写图片描述
这里写图片描述
2、GPA0CON(0xE020_0000),bit【0~3】 = 0b0010 bit【4:7】 = 0b0010

这里写图片描述

3、接下来是几个关键性的寄存器
UCON0 ULCON0 UMCON0 UFCON0 UBRDIV0 UDIVSLOTO
红外模式:0:普通模式、1:红外模式;
奇偶校验模式:0:无、1:奇数、2:偶数;
终止位:0:1位,1:2位;
字长:5-8bit
这里写图片描述

UCONn
这里写图片描述

这里写图片描述

UMCONn全都设置为0

这里写图片描述

UFCON0 FIFO相关的
这里写图片描述
这里写图片描述

E、UTRSTATn寄存器,是状态寄存器
Transmitter empty 移位器和发送缓冲寄存器是否有可用数据发送,0:非空,1:空;
Transmitter buffer empty发送缓冲寄存器 ,0:非空,1:空
Recieve buffer empty发送缓冲寄存器,0:非空,1:空

这里写图片描述

UBRDIVn和UDIVSLOTn和波特率有关,后面根据公式去算。
这里写图片描述
这里写图片描述

这里写图片描述
波特率设置方法:DIV_VAL = (PCLK / (bps x 16)) −1
如66.7MHz/(115200*16) = 36.187
则UBRDIV n中的值就是36-1=35;
0.187*16=2.992 ,则UDIVSLOTn中1的个数为3个,则UDIVSLOTn寄存器的值根据上表,应该写入0x0888。

UTXHn寄存器、URXHn寄存器
这里写图片描述

六、主要代码


void main(void)
{
    uart_init();

    while(1)
    {
        uart_putc('a');
        delay();
    }
}

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

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

// 串口初始化程序
void uart_init(void)
{
    // 初始化Tx Rx对应的GPIO引脚
    rGPA0CON &= ~(0xff<<0);            // 把寄存器的bit0~7全部清零
    rGPA0CON |= 0x00000022;         // 0b0010, Rx Tx

    // 几个关键寄存器的设置
    rULCON0 = 0x3;//0校验位、8数据位、1停止位
    rUCON0 = 0x5;//发送和接收都是polling mode
    rUMCON0 = 0;//禁止modem、afc
    rUFCON0 = 0;//禁止FIFO模式

    // 波特率设置    DIV_VAL = (PCLK / (bps x 16))-1
    // PCLK_PSYS用66MHz算     余数0.8
    //rUBRDIV0 = 34;    
    //rUDIVSLOT0 = 0xdfdd;

    // PCLK_PSYS用66.7MHz算       余数0.18
    // DIV_VAL = (66700000/(115200*16)-1) = 35.18
    rUBRDIV0 = 35;
    // (rUDIVSLOT中的1的个数)/16=上一步计算的余数=0.18
    // (rUDIVSLOT中的1的个数 = 16*0.18= 2.88 = 3
    rUDIVSLOT0 = 0x0888;        // 3个1,查官方推荐表得到这个数字
}


// 串口发送程序,发送一个字节
void uart_putc(char c)
{                   
    // 串口发送一个字符,其实就是把一个字节丢到发送缓冲区中去
    // 因为串口控制器发送1个字节的速度远远低于CPU的速度,所以CPU发送1个字节前必须
    // 确认串口控制器当前缓冲区是空的(意思就是串口已经发完了上一个字节)
    // 如果缓冲区非空则位为0,此时应该循环,直到位为1
    while (!(rUTRSTAT0 & (1<<1)));//缓冲区为空时(即状态寄存器的第2bit为1时),说明可以发送该字节到缓冲区了
    rUTXH0 = c;
}

// 串口接收程序,轮询方式,接收一个字节
char uart_getc(void)
{
    while (!(rUTRSTAT0 & (1<<0)));
    return (rURXH0 & 0x0f);//为什么要与,bit0~bit3????????
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值