通訊過程分爲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