傳輸是從串口發送字節數據到串口服務器進行數據傳輸,發送的原理與接受相似。
傳輸原理:當計算機要從串行端口(到外部電纜)發送一個字節時,CPU 將計算機內部總線上的字節發送到串行端口的 I/O 地址。串行端口獲取字節,并在串行電纜連接器的傳輸引腳上一次一位(串行位流)發送出去。
UART芯片在串口完成了大部分工作,可以說UART就是串口引擎。為了傳輸一個數據字節,串口設備驅動程序向串口I/O地址發送一個數據。該數據進入串行端口中的 1 字節“傳輸移位寄存器”。從這個移位寄存器中,一個比特一個字節地從數據中取出,并在串行線上被一個比特地發送出去。然后,當最后一位發送完畢并且移位寄存器需要發送另一個字節數據時,它可以只要求確認 CPU 向其發送另一個字節數據。這樣很簡單,但可能會引入延遲,因為 CPU 可能無法立即獲取字節。畢竟,CPU 通常除了處理串口之外,還會做其他事情。
消除這種延遲的一種方法是安排一些事情,以便 CPU 在移位寄存器需要之前獲取字節數據并將其存儲在串行端口硬件緩沖區中。然后當移位寄存器發送完字節數據并立即需要一個新字節時,串口硬件只是將下一個字節從自己的緩沖區傳輸到移位寄存器。無需調用 CPU 來獲取新字節。
這個串口緩沖區的大小原本只有一個字節;今天它通常是 16 個字節。現在仍然存在一個問題,即保持這個緩沖區足夠的字節數,以便當移位寄存器需要一個字節來傳輸時,它總是會在那里找到一個字節(除非沒有更多的字節要發送)。CPU 使用中斷來做到這一點。
當移位寄存器從緩沖區中取出字節并且緩沖區需要另一個字節時,它會通過在計算機總線上的專用線上施加電壓來向 CPU 發送中斷。除非 CPU 正在做一些非常重要的事情,否則中斷會強制它停止正在做的事情并開始運行一個程序,該程序將為端口的緩沖區提供另一個字節。此緩沖區的目的是在硬件中保持一個額外的字節(等待發送)排隊,以便在從串行端口電纜傳輸字節時不會出現間隙。
一旦 CPU 得到中斷,它就會知道是誰發送了中斷,因為每個串口都有一條專用的中斷線(除非中斷是共享的)。
然后 CPU 將開始運行串行設備驅動程序,它檢查 I/0 地址上的寄存器以找出發生了什么。它發現串行的發送緩沖區為空并等待另一個字節。因此,如果要發送更多字節,它將下一個字節發送到串行端口的 I/0 地址。當前一個字節仍在傳輸移位寄存器中并且仍在逐位傳輸時,下一個字節應該到達。
回顧一下,當一個字節從串行端口的傳輸線完全傳輸出去并且移位寄存器現在是空的時,以下 3 件事幾乎同時發生:
● 下一個字節從發送緩沖器移入發送移位寄存器。
● 這個新字節的傳輸(逐位)開始。
● 發出另一個中斷以告訴設備驅動程序將另一個字節發送到現在為空的傳輸緩沖區。
因此我們說串口是中斷驅動的。每次串口發出中斷;CPU 再發送一個字節。一旦一個字節被 CPU 發送到發送緩沖區,CPU 就可以自由地進行一些其他活動,直到它得到下一個中??斷。串口以固定速率傳輸比特,由用戶(或應用程序)選擇。它有時被稱為波特率。串行端口還會為每個字節(開始、停止和奇偶校驗位)添加額外的位,因此每個字節通常會發送 10 位。以每秒 19,200 位 (bps) 的速率(也稱為速度),因此有 1,920 字節/秒(以及 1,920 個中斷/秒)。
完成所有這些工作對 CPU 來說是大量的工作。這是事實,原因有很多。首先,僅通過 32 位數據總線(甚至 64 位)一次發送一個 8 位字節并不是對總線寬度的非常有效的使用。此外,處理每個中斷有很多開銷。當接收到中斷時,設備驅動程序只知道有什么東西在串口上引起了中斷,但不知道這是因為發送了一個字符。設備驅動程序必須進行各種檢查以找出發生了什么。相同的中斷可能意味著接收到一個字符、其中一條控制線改變了狀態等。
一個主要的改進是將串行端口的緩沖區大小從 1 字節擴大到 16 字節。這意味著當 CPU 收到中斷時,它會給串行端口最多 16 個新字節進行傳輸。這是服務中斷,但數據仍必須在寬總線上一次一個字節地傳輸。16 字節的緩沖區實際上是一個 FIFO(先進先出)隊列,通常稱為 FIFO。
通過串行端口接收字節類似于發送原理,只是方向相反。它也是中斷驅動的。
對于帶有 1 字節緩沖區的過時類型的串行端口,當從外部電纜完全接收到一個字節時,它會進入 1 字節接收緩沖區。然后端口給 CPU 一個中斷,告訴它選擇那個字節,這樣串行端口就有空間來存儲當前正在接收的下一個字節。對于具有 16 字節緩沖區的較新串行端口,可以在接收緩沖區中有 14 個字節后發送此中斷(以獲取字節)。然后 CPU 停止正在執行的操作,運行中斷服務程序,并從端口獲取 14 到 16 個字節。對于在接收到第 14 個字節時發送的中斷,如果自中斷以來還有 2 個字節到達,則可能有 16 個字節要獲取。但是如果還有 3 個字節到達(而不是 2 個),那么 16 字節的緩沖區就會溢出。通過以這種方式設置或由于超時,它也可能拾取少于 14 個字節。
我們已經討論了小型 16 字節串行端口硬件緩沖區,但主內存中還有更大的緩沖區。當 CPU 從硬件的接收緩沖區中取出一些字節時,它會將它們放入主內存中一個更大(比如 8k 字節)的接收緩沖區中。然后,從串行端口獲取字節的程序從大緩沖區中獲取它接收的字節(在程序中使用“讀取”語句)。對于要傳輸的字節也存在類似的情況。當 CPU 需要獲取一些要發送的字節時,它會將它們從主內存中的大(8k 字節)發送緩沖區中取出,并將它們放入硬件中的 16 字節小發送緩沖區中。