通讯过程分为3个步骤:html
同步和异步的区别 :linux
发送方和接收方按照同一个时钟节拍工做就叫同步,发送方和接收方没有统一的时钟节拍、而各自按照本身的节拍工做就叫异步。程序员
同步通讯中,通讯双方按照统一节拍工做,因此配合很好;通常须要发送方给接收方发送信息同时发送时钟信号,接收方根据发送方给它的时钟信号来安排本身的节奏。同步通讯用在通讯双方信息交换频率固定,或者常常通讯时。编程
异步通讯又叫异步通知。在双方通讯的频率不固定时(有时3ms收发一次,有时3天才收发一次)不适合使用同步通讯,而适合异步通讯。异步通讯时接收方没必要一直在乎发送方,发送方须要发送信息时会首先给接收方一个信息开始的起始信号,接收方接收到起始信号后就认为后面紧跟着的就是有效信息,才会开始注意接收信息,直到收到发送方发过来的结束标志。数据结构
电平信号的2根通讯线之间的电平差别容易受到干扰,传输容易失败;差分信号不容易受到干扰所以传输质量比较稳定,现代通讯通常都使用差分信号,电平信号几乎没有了。异步
看起来彷佛相同根数的通讯线下,电平信号要比差分信号要快;可是实际仍是差分信号快,由于差分信号抗干扰能力强,所以1个发送周期更短。async
串行、并行主要是考虑通讯线的根数,就是发送方和接收方同时能够传递的信息量的多少函数
譬如在电平信号下,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
咱们台式电脑后面的串口插座就是RS232接口的,在工业上用串口时都用这个,传输距离小于15米;TTL电平通常用在电路板内部两个芯片之间。咱们台式电脑后面的串口插座就是RS232接口的,在工业上用串口时都用这个,传输距离小于15米;TTL电平通常用在电路板内部两个芯片之间。
对编程来讲,RS232电平传输仍是TTL电平是没有差别的。因此电平标准对硬件工程师更有意义,而软件工程师只要略懂便可。(把TTL电平和RS232电平混接是不能够的)
为何波特率不能够随便指定?主要是由于:第一,通讯双方必须事先设定相同的波特率这样才能成功通讯,若是发送方和接收方按照不一样的波特率通讯则根本收不到,所以波特率最好是你们熟知的而不是随意指定的。第二,经常使用的波特率通过长久发展,就造成了共识,你们经常使用就是9600或者115200.
串口通讯时由于是异步通讯,因此通讯双方必须事先约定好通讯参数,这些通讯参数包括:波特率、数据位、奇偶校验位、中止位(串口通讯中起始位定义是惟一的,因此通常不用选择)
串口通讯属于基层基本性的通讯规约,它本身自己不会去协商通讯参数,须要通讯前通讯双方事先约定好通讯参数(通常4个最重要的)
串口通讯的任何一个关键参数设置错误,都会致使通讯失败。譬如波特率调错了,发送方发送没问题,接收方也能接收,可是接收到全是乱码···
串口通讯的发送方每隔必定时间(时间固定为1/波特率,单位是秒)将有效信息(1或者0)放到通讯线上去,逐个二进制位的进行发送。
接收方经过定时(起始时间由读到起始位标志开始,间隔时间由波特率决定)读取通讯线上的电平高低来区分发送给个人是1仍是0。依次读取数据位、奇偶校验位、中止位,中止位就表示这一个通讯单元(帧)结束,而后中间是不定长短的非通讯时间(发送方有可能紧接着就发送第二帧,也可能半天都不发第二帧,这就叫异步通讯),下来就是第二帧·····
总结:第一,波特率很是重要,波特率错了整个通讯就乱套了;数据位、奇偶校验位、中止位也很重要,不然可能认不清数据。第三,经过串口无论发数字、仍是文本仍是命令仍是什么,都要先对发送内容进行编码,编码成二进制再进行逐个位的发送。总结:第一,波特率很是重要,波特率错了整个通讯就乱套了;数据位、奇偶校验位、中止位也很重要,不然可能认不清数据。第三,经过串口无论发数字、仍是文本仍是命令仍是什么,都要先对发送内容进行编码,编码成二进制再进行逐个位的发送。
串口发送的通常都是字符,通常都是ASCII码编码后的字符,因此通常设置数据位都是8,方便恰好一帧发送1个字符。
S5PV210的数据手册中串口控制器在section8.1,串口的官方名称叫:universal asynchronous reciver and transmitter,通用异步收发器
英文缩写是uart,中文简称串口。
总结:发送缓冲区和接收缓冲区是关键。发送移位器和接收移位器的工做都是自动的,不用编程控制的,因此咱们写串口的代码就是:首先初始化(初始化的实质是读写寄存器)好串口控制器(包括发送控制器和接收控制器),而后要发送信息时直接写入发送缓冲区,要接收信息时直接去接收缓冲区读取便可。可见,串口底层的工做(譬如怎么移位的、譬如起始位怎么定义的、譬如TTL电平仍是RS232电平等)对程序员是隐藏的,程序员不用去管。软件工程师对串口操做的接口就是发送/接收缓冲区(实质就是寄存器,操做方式就是读写内存)
串口控制器中有一个波特率发生器,做用是产生串口发送/接收的节拍时钟。波特率发生器其实就是个时钟分频器,它的工做须要源时钟(APB总线来),而后内部将源时钟进行分频(软件设置寄存器来配置)获得目标时钟,而后再用这个目标时钟产生波特率(硬件自动的)。
为何须要流控?流控的目的是让串口通讯很是可靠,在发送方速率比接收方快的时候流控能够保证发送和接收不会漏掉东西。
如今为何不用流控?如今计算机之间有更好更高级(usb、internet)的通信方式,串口已经基本被废弃了。如今串口的用途更可能是SoC用来输出调试信息的。因为调试信息不是关键性信息、并且因为硬件发展串口自己速度已经相对慢的要死了,因此硬件都能协调发送和接收速率,所以流控已经失去意义了,因此如今基本都废弃了。
串口通讯分为发送/接收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是用来辅助设置的,目的是为了校准波特率的。
整个串口通讯相关程序包含2部分:uart_init负责初始化串口,uart_putc负责发送一个字节
定义好了访问寄存器的宏以后,未来写代码时直接使用便可。
给GPA0CON的相应bit位赋值为相应值,用C语言位操做来完成。
依据上节中分析的值进行依次设置便可。
第一步,用PCLK_PSYS和目标波特率去计算DIV_VAL: DIV_VAL = (PCLK / (bps x 16)) -1
第二步,UBRDIV0寄存器中写入DIV_VAL的整数部分
第三步,用小数部分*16获得1个个数,查表得uBDIVSLOT0寄存器的设置值
写发送函数,主要发送前要用while循环等待发送缓冲区为空才能发送。
(1)#include <stdio.h>
(2)stdio:standard input output,标准输入输出
(3)标准输入输出就是操做系统定义的默认的输入和输出通道。通常在PC机的状况下,标准输入指的是键盘,标准输出指的是屏幕。
(4)printf函数和scanf函数能够和底层输入/输出函数绑定,而后这两个函数就能够和stdio绑定起来。也就是说咱们直接调用printf函数输出,内容就会被从标准输出输出出去。
(5)在咱们这里,标准输出固然不是屏幕了,而是串口。标准输出也不是键盘,而是串口。
(1)printf函数工做时内部实际调用了2个关键函数:一个是vsprintf函数(主要功能是格式化打印信息,最终获得纯字符串格式的打印信息等待输出),另外一个就是真正的输出函数putc(操控标准输出的硬件,将信息发送出去)
(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