ARM裸机(七)串口通讯详解

1.通讯涉及的几个基础概念

通讯过程分为3个步骤:html

  • 首先发送方先按照信息编码方式对有效信息进行编码(编程成能够在通讯线路上传输的信号形态)
  • 而后编码后的信息在传输介质上进行传输,输送给接收方
  • 最后接收方接收到编码信息后进行解码,解码后获得能够理解的有效信息。

1.1 同步通讯和异步通讯

同步和异步的区别 :linux

发送方和接收方按照同一个时钟节拍工做就叫同步,发送方和接收方没有统一的时钟节拍、而各自按照本身的节拍工做就叫异步。程序员

同步通讯中,通讯双方按照统一节拍工做,因此配合很好;通常须要发送方给接收方发送信息同时发送时钟信号,接收方根据发送方给它的时钟信号来安排本身的节奏。同步通讯用在通讯双方信息交换频率固定,或者常常通讯时。编程

异步通讯又叫异步通知。在双方通讯的频率不固定时(有时3ms收发一次,有时3天才收发一次)不适合使用同步通讯,而适合异步通讯。异步通讯时接收方没必要一直在乎发送方,发送方须要发送信息时会首先给接收方一个信息开始的起始信号,接收方接收到起始信号后就认为后面紧跟着的就是有效信息,才会开始注意接收信息,直到收到发送方发过来的结束标志。数据结构

1.2 电平信号和差分信号

  • 电平信号和差分信号是用来描述通讯线路传输方式的。也就是说如何在通讯线路上表达1和0.
  • 电平信号的传输线中有一个参考电平线(通常是GND),而后信号线上的信号值是由信号线电平和参考电平线的电压差决定。
  • 差分信号的传输线中没有参考电平,全部都是信号线。而后1和0的表达靠信号线之间的电压差。

电平信号的2根通讯线之间的电平差别容易受到干扰,传输容易失败;差分信号不容易受到干扰所以传输质量比较稳定,现代通讯通常都使用差分信号,电平信号几乎没有了。异步

看起来彷佛相同根数的通讯线下,电平信号要比差分信号要快;可是实际仍是差分信号快,由于差分信号抗干扰能力强,所以1个发送周期更短。async

1.3 并行接口和串行接口

串行、并行主要是考虑通讯线的根数,就是发送方和接收方同时能够传递的信息量的多少函数

譬如在电平信号下,1根参考电平线+1根信号线能够传递1位二进制;若是咱们有3根线(2根信号线+1根参考线)就能够同时发送2位二进制;若是想同时发送8位二进制就须要9根线。在差分信号下,2根线(彼此差分)能够同时发送1位二进制;若是须要同时发送8位二进制,须要16根线。譬如在电平信号下,1根参考电平线+1根信号线能够传递1位二进制;若是咱们有3根线(2根信号线+1根参考线)就能够同时发送2位二进制;若是想同时发送8位二进制就须要9根线。在差分信号下,2根线(彼此差分)能够同时发送1位二进制;若是须要同时发送8位二进制,须要16根线。性能

听起来彷佛并行接口比串行接口要快(串行接口一次只能发送1位二进制,而并行接口一次能够发送多位二进制)要更优秀;可是实际上串行接口才是王道,用的比较广。由于更省信号线,并且对传输线的要求更低、成本更低;并且串行时能够经过提升通讯速度来提升整体通讯性能,不必定非得要并行。ui

2.串口通讯的基本概念

2.一、串口通讯的特色:异步、电平信号、串行

  • 异步:串口通讯的发送方和接收方之间是没有统一的时钟信号的。
  • 电平信号:串口通讯出现的时间较早,速率较低,传输的距离较近,因此干扰还不太明显,所以当时使用了电平信号传输。后期出现的传输协议都改为差分信号传输了。
  • 串行通讯:串口通讯每次同时只能传输1个二进制位。

2.二、RS232电平和TTL电平

  • 电平信号是用信号线电平减去参考线电平获得电压差,这个电压差决定了传输值是1仍是0.
  • 在电平信号时多少V表明1,多少V表明0不是固定的,取决于电平标准。譬如RS232电平中-3V~-15V表示1;+3~+15V表示0;TTL电平则是+5V表示1,0V表示0.
  • 无论哪一种电平都是为了在传输线上表示1和0.区别在于适用的环境和条件不一样。RS232的电平定义比较大,适合干扰大、距离远的状况;TTL电平电压范围小,适合距离近且干扰小的状况。

咱们台式电脑后面的串口插座就是RS232接口的,在工业上用串口时都用这个,传输距离小于15米;TTL电平通常用在电路板内部两个芯片之间。咱们台式电脑后面的串口插座就是RS232接口的,在工业上用串口时都用这个,传输距离小于15米;TTL电平通常用在电路板内部两个芯片之间。

对编程来讲,RS232电平传输仍是TTL电平是没有差别的。因此电平标准对硬件工程师更有意义,而软件工程师只要略懂便可。(把TTL电平和RS232电平混接是不能够的)

2.三、波特率

  • 波特率(bandrate),指的是串口通讯的速率,也就是串口通讯时每秒钟能够传输多少个二进制位。譬如每秒种能够传输9600个二进制位(传输一个二进制位须要的时间是1/9600秒,也就是104us),波特率就是9600.
  • 串口通讯的波特率不能随意设定,而应该在一些值中去选择。通常最多见的波特率是9600或者115200(低端单片机如51经常使用9600,高端单片机和嵌入式SoC通常用115200).

为何波特率不能够随便指定?主要是由于:第一,通讯双方必须事先设定相同的波特率这样才能成功通讯,若是发送方和接收方按照不一样的波特率通讯则根本收不到,所以波特率最好是你们熟知的而不是随意指定的。第二,经常使用的波特率通过长久发展,就造成了共识,你们经常使用就是9600或者115200.

2.四、起始位、数据位、奇偶校验位、中止位

  • 串口通讯时,收发是一个周期一个周期进行的,没周期传输n个二进制位。这一个周期就叫作一个通讯单元,一个通讯单元是由:起始位+数据位+奇偶校验位+中止位组成的。
  • 起始位表示发送方要开始发送一个通讯单元;数据位是一个通讯单元中发送的有效信息位;奇偶校验位是用来校验数据位,以防止数据位出错的;中止位是发送方用来表示本通讯单元结束标志的。
  • 起始位的定义是串口通讯标准事先指定的,是由通讯线上的电平变化来反映的。
  • 数据位是本次通讯真正要发送的有效数据,串口通讯一次发送多少位有效数据是能够设定的(通常可选的有六、七、八、9,99%状况下咱们都是选择8位数据位。由于咱们通常经过串口发送的文字信息都是ASCII码编码的,而ASCII码中一个字符恰好编码为8位。)
  • 奇偶校验位是用来给数据位进行奇偶校验(把待校验的有效数据逐个位的加起来,总和为奇数奇偶校验位就为1,总和为偶数奇偶校验位就为0)的,能够在必定程度上防止位反转。
  • 中止位的定义是串口通讯标准事先指定的,是由通讯线上的电平变化来反映的。常见的有1位中止位,1.5位中止位,2位中止位等。99%状况下都是用1位中止位。

串口通讯时由于是异步通讯,因此通讯双方必须事先约定好通讯参数,这些通讯参数包括:波特率、数据位、奇偶校验位、中止位(串口通讯中起始位定义是惟一的,因此通常不用选择)

3.串口通讯的基本原理

3.一、三根通讯线:Rx Tx GND

  • 任何通讯都要有信息传输载体,或者是有线的或者是无线的。
  • 串口通讯是有线通讯,是经过串口线来通讯的。
  • 串口通讯线最少须要2根(GND和信号线),能够实现单工通讯,也可使用3根通讯线(Tx、Rx、GND)来实现全双工。
  • 通常开发板都会引出SoC上串口引脚直接输出的TTL电平的串口(X210开发板没有),插座用插针式插座,每一个串口引出的都有3个线(Tx、Rx、GND),能够用这些插座直接链接外部的TTL电平的串口设备。

3.二、收发双方事先规定好通讯参数(波特率、数据位、奇偶校验位、中止位等)

串口通讯属于基层基本性的通讯规约,它本身自己不会去协商通讯参数,须要通讯前通讯双方事先约定好通讯参数(通常4个最重要的)

串口通讯的任何一个关键参数设置错误,都会致使通讯失败。譬如波特率调错了,发送方发送没问题,接收方也能接收,可是接收到全是乱码···

3.三、信息以二进制流的方式在信道上传输

串口通讯的发送方每隔必定时间(时间固定为1/波特率,单位是秒)将有效信息(1或者0)放到通讯线上去,逐个二进制位的进行发送。

接收方经过定时(起始时间由读到起始位标志开始,间隔时间由波特率决定)读取通讯线上的电平高低来区分发送给个人是1仍是0。依次读取数据位、奇偶校验位、中止位,中止位就表示这一个通讯单元(帧)结束,而后中间是不定长短的非通讯时间(发送方有可能紧接着就发送第二帧,也可能半天都不发第二帧,这就叫异步通讯),下来就是第二帧·····

总结:第一,波特率很是重要,波特率错了整个通讯就乱套了;数据位、奇偶校验位、中止位也很重要,不然可能认不清数据。第三,经过串口无论发数字、仍是文本仍是命令仍是什么,都要先对发送内容进行编码,编码成二进制再进行逐个位的发送。总结:第一,波特率很是重要,波特率错了整个通讯就乱套了;数据位、奇偶校验位、中止位也很重要,不然可能认不清数据。第三,经过串口无论发数字、仍是文本仍是命令仍是什么,都要先对发送内容进行编码,编码成二进制再进行逐个位的发送。

串口发送的通常都是字符,通常都是ASCII码编码后的字符,因此通常设置数据位都是8,方便恰好一帧发送1个字符。

3.五、DB9接口介绍

  • DB9接口是串口通讯早期比较经常使用的一种规范化接口。
  • 串行通讯在早期是计算机与外界通讯的主要手段,那时候的计算机都有标准配置的串口以实现和外部通讯。那时候就定义了一套标准的串口规约,DB9接口就是标准接口。
  • DB9接口中有9根通讯线,其中3根很重要,为GND、Tx、Rx,必不可少;剩余6根都是和流控有关的,现代咱们使用串口都是用来作调试通常都禁用流控,因此这6根没用。
  • 如今通常使用串口时要记得把流控禁止掉,否则可能发生意想不到的问题。

4.S5PV210串行通讯接口详解1

 S5PV210的数据手册中串口控制器在section8.1,串口的官方名称叫:universal asynchronous reciver and transmitter,通用异步收发器
英文缩写是uart,中文简称串口

4.一、S5PV210的串口控制器工做原理框图

  1. 整个串口控制器包含transmitter和receiver两部分,两部分功能彼此独立,transmitter负责210向外部发送信息,receiver负责从外部接收信息到210内部。
  2. 总线角度来说,串口控制器是接在APB总线上的。对咱们编程有影响的是:未来计算串口控制器的源时钟时是以APB总线来计算的。
  3. transmitter由发送缓冲区和发送移位器构成。咱们要发送信息时,首先将信息进行编码(通常用ASCII码)成二进制流,而后将一帧数据(通常是8位)写入发送缓冲区(从这里之后程序就不用管了,剩下的发送部分是硬件自动的),发送移位器会自动从发送缓冲区中读取一帧数据,而后自动移位(移位的目的是将一帧数据的各个位分别拿出来)将其发送到Tx通讯线上。
  4. receiver由接收缓冲区和接收移位器构成。当有人经过串口线向我发送信息时,信息经过Rx通讯线进入个人接收移位器,而后接收移位器自动移位将该二进制位保存入个人接收缓冲区,接收完一帧数据后receiver会产生一个中断给CPU,CPU收到中断后便可知道receiver接收满了一帧数据,就会来读取这帧数据。

总结:发送缓冲区和接收缓冲区是关键。发送移位器和接收移位器的工做都是自动的,不用编程控制的,因此咱们写串口的代码就是:首先初始化(初始化的实质是读写寄存器)好串口控制器(包括发送控制器和接收控制器),而后要发送信息时直接写入发送缓冲区,要接收信息时直接去接收缓冲区读取便可。可见,串口底层的工做(譬如怎么移位的、譬如起始位怎么定义的、譬如TTL电平仍是RS232电平等)对程序员是隐藏的,程序员不用去管。软件工程师对串口操做的接口就是发送/接收缓冲区(实质就是寄存器,操做方式就是读写内存)

串口控制器中有一个波特率发生器,做用是产生串口发送/接收的节拍时钟。波特率发生器其实就是个时钟分频器,它的工做须要源时钟(APB总线来),而后内部将源时钟进行分频(软件设置寄存器来配置)获得目标时钟,而后再用这个目标时钟产生波特率(硬件自动的)。

4.二、自动流控(AFC:Auto flow control)

为何须要流控?流控的目的是让串口通讯很是可靠,在发送方速率比接收方快的时候流控能够保证发送和接收不会漏掉东西。

如今为何不用流控?如今计算机之间有更好更高级(usb、internet)的通信方式,串口已经基本被废弃了。如今串口的用途更可能是SoC用来输出调试信息的。因为调试信息不是关键性信息、并且因为硬件发展串口自己速度已经相对慢的要死了,因此硬件都能协调发送和接收速率,所以流控已经失去意义了,因此如今基本都废弃了。

5.S5PV210串行通讯接口详解2

5.一、FIFO模式及其做用

  1. 典型的串口设计,发送/接收缓冲区只有1字节,每次发送/接收只能处理1帧数据。这样在单片机中没什么问题,可是到复杂SoC中(通常有操做系统的)就会有问题,会致使效率低下,由于CPU须要不断切换上下文。
  2. 解决方案就是想办法扩展串口控制器的发送/接收缓冲区,譬如将发送/接收缓冲器设置为64字节,CPU一次过来直接给发送缓冲区64字节的待发送数据,而后transmitter慢慢发,发完再找CPU再要64字节。可是串口控制器原本的发送/接收缓冲区是固定的1字节长度的,因此作了个变相的扩展,就是FIFO。
  3. FIFO就是first in first out,先进先出。fifo实际上是一种数据结构,这里这个大的缓冲区叫FIFO是由于这个缓冲区的工做方式相似于FIFO这种数据结构。

5.二、DMA模式及其做用

  1. DMA direct memory access,直接内存访问。DMA原本是DSP中的一种技术,DMA技术的核心就是在交换数据时不须要CPU参与,模块能够本身完成。
  2. DMA模式要解决的问题和上面FIFO模式是同一个问题,就是串口发送/接收要频繁的折腾CPU形成CPU反复切换上下文致使系统效率低下。
  3. 传统的串口工做方式(无FIFO无DMA)效率是最低的,适合低端单片机;高端单片机上CPU事物繁忙因此都须要串口可以本身完成大量数据发送/接收。这时候就须要FIFO或者DMA模式。FIFO模式是一种轻量级的解决方案,DMA模式适合大量数据迸发式的发送/接收时。

5.三、IrDA模式及其用法

  1. IrDA其实就是红外,红外就是红外线通讯(电视机、空调遥控器就是红外通讯的)。
  2. 红外通讯的原理是发送方固定间隔时间向接收方发送红外信号(表示1或0)或者不发送红外信号(表示0或者1),接收方每隔固定时间去判断有无红外线信号来接收1和0
  3. 分析可知,红外通讯和串口通讯很是像,都是每隔固定时间发送1或者0(判断1或0的物理方式不一样)给接收方来通讯。所以210就利用串口通讯来实现了红外发送和接收。
  4. 210的某个串口支持IrDA模式,开启红外模式后,咱们只须要向串口写数据,这些数据就会以红外光的方式向外发射出去(固然是须要一些外部硬件支持的),而后接收方接收这些红外数据便可解码获得咱们的发送信息。

6.S5PV210串行通讯接口详解3

6.一、串行通讯与中断的关系

串口通讯分为发送/接收2部分。发送方通常不须要(也可使用)中断便可完成发送,接收方必须(通常来讲必须,也能够轮询方式接收)使用中断来接收。

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

由于串口通讯是异步的,异步的意思就是说发送方占主导权。也就是说发送方随时想发就能发,可是接收方只有时刻等待才不会丢失数据。因此这个差别就致使发送方能够不用中断,而接收方不得不使用中断模式。

6.二、210串行通讯接口的时钟设计

串口通讯为何须要时钟?由于串口通讯须要一个固定的波特率,因此transmitter和receiver都须要一个时钟信号。

时钟信号从哪里来?源时钟信号是外部APB总线(PCLK_PSYS,66MHz)提供给串口模块的(这就是为何咱们说串口是挂在APB总线上的),而后进到串口控制器内部后给波特率发生器(实质上是一个分频器),在波特率发生器中进行分频,分频后获得一个低频时钟,这个时钟就是给transmitter和receiver使用的。

串口通讯中时钟的设置主要看寄存器设置。重点的有:寄存器源设置(为串口控制器选择源时钟,通常选择为PCLK_PSYS,也能够是SCLK_UART),还有波特率发生器的2个寄存器。

波特率发生器有2个重要寄存器:UBRDIVn和UDIVSLOTn,其中UBRDIVn是主要的设置波特率的寄存器,UDIVSLOTn是用来辅助设置的,目的是为了校准波特率的。

 

7.S5PV210串行通讯编程实战1

7.一、整个程序流程分析

整个串口通讯相关程序包含2部分:uart_init负责初始化串口,uart_putc负责发送一个字节

7.二、串口控制器初始化关键步骤

  1. 初始化串口的Tx和Rx引脚所对应的GPIO(查原理图可知Rx和Rx分别对应GPA0_1和GPA0_0)
  2. GPA0CON(0xE0200000),bit[3:0] = 0b0010    bit[7:4] = 0b0010
  3. 初始化这几个关键寄存器UCON0 ULCON0 UMCON0 UFCON0 UBRDIV0 UDIVSLOT0

7.三、主要的几个寄存器

  1. ULCON0 = 0x3        // 0校验位、8数据位、1中止位
  2. UCON0 = 0x5        // 发送和接收都是polling mode
  3. UFCON0 = 0x0        // 禁止FIFO模式
  4. UMCON0 = 0x0        // 禁止modem、afc
  5. UBRDIV0和UDIVSLOT0和波特率有关,要根据公式去算的

7.四、在C源文件中定义访问寄存器的宏

定义好了访问寄存器的宏以后,未来写代码时直接使用便可。

8.S5PV210串行通讯编程实战2

8.一、串口Tx、Rx对应的GPIO的初始化

给GPA0CON的相应bit位赋值为相应值,用C语言位操做来完成。

8.二、UCON、ULCON、UMCON、UFCON等主要控制寄存器

依据上节中分析的值进行依次设置便可。

8.三、波特率的计算和设置

第一步,用PCLK_PSYS和目标波特率去计算DIV_VAL: DIV_VAL = (PCLK / (bps x 16)) -1

第二步,UBRDIV0寄存器中写入DIV_VAL的整数部分

第三步,用小数部分*16获得1个个数,查表得uBDIVSLOT0寄存器的设置值

8.四、串口发送和接收函数的编写

写发送函数,主要发送前要用while循环等待发送缓冲区为空才能发送。

9.uart stdio的移植1

9.一、什么是stdio

(1)#include <stdio.h>

(2)stdio:standard input output,标准输入输出

(3)标准输入输出就是操做系统定义的默认的输入和输出通道。通常在PC机的状况下,标准输入指的是键盘,标准输出指的是屏幕。

(4)printf函数和scanf函数能够和底层输入/输出函数绑定,而后这两个函数就能够和stdio绑定起来。也就是说咱们直接调用printf函数输出,内容就会被从标准输出输出出去。

(5)在咱们这里,标准输出固然不是屏幕了,而是串口。标准输出也不是键盘,而是串口。

9.二、printf函数的工做原理

(1)printf函数工做时内部实际调用了2个关键函数:一个是vsprintf函数(主要功能是格式化打印信息,最终获得纯字符串格式的打印信息等待输出),另外一个就是真正的输出函数putc(操控标准输出的硬件,将信息发送出去)

9.三、移植printf函数的三种思路

(1)咱们但愿在咱们的开发板上使用printf函数进行(串口)输出,使用scanf函数进行(串口)输入,就像在PC机上用键盘和屏幕进行输入输出同样。所以须要移植printf函数/scanf函数

(2)咱们说的移植而不是编写,咱们不但愿本身彻底重新编写而是想尽可能借用已有的代码(叫移植)

(3)通常移植printf函数能够有3个途径获取printf的实现源码:最原始最本来的来源就是linux内核中的printk。难度较大、关键是麻烦;稍微简单些的方法是从uboot中移植printf;更简单的方法就是直接使用别人移植好的。

(4)咱们课程中使用第三种方法,别人移植好的printf函数来自于友善之臂的Tiny210的裸机教程中提供的。

GCC 预处理器选项 https://blog.csdn.net/dllbl/article/details/2841896

Gcc编译选项  http://blog.chinaunix.net/uid-29767867-id-4413146.html

相关文章
相关标签/搜索