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

相關文章
相關標籤/搜索