分享到plurk 分享到twitter 分享到facebook

版本 71c00e987dc1914471c55f192141187e823a5384

embedded/USART

Changes from 71c00e987dc1914471c55f192141187e823a5384 to current

---
title: Universal Asynchronous Receiver/Transmitter 
title: Universal Asynchronous Receiver/Transmitter (USART)
categories: ARM, USART, UART, STM32, STM32F4, STM32F429
...

USART簡介與特性
...................
串列傳輸為CPU與周邊裝置或CPU與CPU間的資料傳輸方法之一,而USART(universal synchronous asynchronous receiver transmitter),通用同步/非同步收發傳輸器,則常被用於一般的串列傳輸應用中。可依照NZR工業非同步資料傳輸格式,與其他設備進行資料交換。並且此種裝置使用fractional baud rate產生器,提供大範圍的baud rate供使用者選擇。
==========================
串列傳輸為CPU與周邊裝置或CPU與CPU間的資料傳輸方法之一,而USART(universal synchronous asynchronous receiver transmitter),通用同步/非同步收發傳輸器,則常被用於一般的串列傳輸應用中。可依照NRZ工業非同步資料傳輸格式,與其他設備進行資料交換。並且此種裝置使用fractional baud rate產生器,提供大範圍的baud rate供使用者選擇。

此外,亦支援同步傳輸、單線半雙工傳輸、LIN(local connection network)、Smartcard protocol、IrDA(Infrared data association) SIR ENDEC標準。

高速資料傳輸,則使用DMA去設定多重緩衝區來達到此目的。

NRZ標準資料格式(Mark/Space)
==========================

   NRZ(Nonreturn to Zero):不歸零編碼

   這是一種傳送資訊的編碼方式,它以正脈波代表1,負脈波代表0,當訊號連續為'1'時,則保持正脈波,直到出現'0'為止
   這是一種傳送資訊的編碼方式,它通常以正電位代表'1', 負電位代表'0'

   它的特色是編碼解碼較為簡單,但缺乏同步傳輸的能力,且無法提供較佳的訊號校正能力。

.. image:: /NRZcode.png
![](/NRZcode.png)

圖片來源:[wikipedia](http://zh.wikipedia.org/wiki/%E4%B8%8D%E6%AD%B8%E9%9B%B6)

半雙工/全雙工
===================
 - 半雙工:允許二台設備之間的雙向資料傳輸,但不能同時進行。因此同一時間只允許一設備傳送資料,若另一設備要傳送資料,需等原來傳送資料的設備傳送完成後再處理。例:無線電

 - 全雙工:允許二台設備間同時進行雙向資料傳輸。例:手機

Synchronous 同步傳輸
=========================

   - 同步: 額外提供時脈訊號,使兩端機器在溝通時能夠藉此同步收發資料。比起非同步傳輸,同步傳輸不需要start/stop bit,因此能夠一次傳較多的資料。同步傳輸需要解決時鐘偏移對資料傳輸造成的影響,除此之外,額外的時脈分佈網也需要大量的驅動電路,比起非同步傳輸增加了更多的耗能。一般同步系統會用阻斷時脈的方式(clock gating),來令不需運作的模組進入睡眠狀態(sleeping mode)到省電的目的,這個機制需要額外的電路及再次同步的額外延遲,不僅造成多餘的能源損耗,也增加了電路設計上的困難度。


.. image:: /synchronous_transmission.png
![](/synchronous_transmission.png)

.. image:: /usart_syn.png
![](/usart_syn.png)


CLOCK SKEW
------------

時鐘偏移(clock skew)是指時脈訊號到達數位電路各個部分所用時間的差異,這是由於時脈訊號到各個電子元件的所經路徑長度不同而產生。STM32F429的clock tree設計亦考慮到此問題,故將clock source用多層邏輯閘配置給系統中的各元件,藉此降低clock skew(如果只使用單個、或少數個邏輯閘,因其fan out有上限,最多不超過20個,若超過也會產生clock skew)。



Asynchronous 非同步傳輸
======================

   - 非同步: 在傳送資料時插入額外資訊,表示資料起始、結束。好處是設定時間短、硬體成本低、機器時脈不同也能傳資料,缺點是單次傳輸的資料量較少。

.. image:: /embedded/ASYNC.gif
![](/embedded/ASYNC.gif)

來源: [webopedia](http://www.webopedia.com/FIG/ASYNC.gif)


半/全雙工、同步/非同步 & Serial bus 示意圖
=========================================

.. image:: /embedded/USART_connection_type.jpg
![](/embedded/USART_connection_type.jpg)



RS232 介面標準
=============
在RS-232標準中,資料是以串列(serial)方式傳輸,其最常用的編碼格式是非同步起停(asynchronous start-stop)格式,它使用一個start bit後面緊跟7或8個資料位元(bit),然後是可選的奇偶校驗位元,最後是一或兩個停止位元。所以傳送一個字元至少需要10位元,主要功能為提供DTE以及DCE的實體連接。

RS-232電器與機械特性
-------------
RS-232電器特性

 - 最大電壓範圍為±25V;
 - -3V至-25V定義為邏輯“1”(負邏輯),稱為marking,功能意義為OFF;
 - +3V至+25V定義為邏輯“0” (負邏輯),稱為spacing,功能意義為ON;
 - 接近零的電位是無效的(±3V之間);
 - 接收信號端的輸入阻抗必須在3KΩ~7KΩ之間,輸入電容小於2500pF;
 - 接收信號端開路時,端點電壓必須小於2V;
 - 發送信號的一端輸出阻抗必須大於300Ω。

RS-232的機械特性

 - 連接器有25pin及9pin,現多用9pin,因較節省空間及成本。
 - 最大傳輸線長度為50呎(15公尺),且資料傳輸速率在20Kbps以下。
 - Data terminal equipment,數位資料的接收或輸出端,並用傳輸協定對資料傳收流程做控制的機器。常見的機器為電腦。
 - Data circuit-terminating equipment,對類比訊號做編解碼,藉此傳收數位資料的機器。常見的機器為數據機。

.. image:: /RS232_DB9pin2.png
![](/RS232_DB9pin2.png)

.. image:: /embedded/RS232_DB9Name3.png
![](/embedded/RS232_DB9Name3.png)

RS-232訊號傳輸
-------------

.. image:: /RS232_Signal.png
![](/RS232_Signal.png)

 - 傳送單一封包時,一個package有1個startbit、8個data bits,1個stop bit。傳送完成後再傳送一個idle。

.. image:: /signal_noidle.jpg
![](/signal_noidle.jpg)

 - 而傳送多個連續封包時,在資料傳輸完以前並不會傳送idle,代表還沒有結束傳輸,原因是因為UART傳輸速度太慢,放入idle則會浪費頻寬。

例:由示波器的高低電位可以得出邏輯0010 0100 由於是從LSB開始傳,所以必須翻轉變成0010 0100換成16進位為0x24,就是符號 "$"
 
null modem 
 - modem: modulator-demodulator,將數位訊號編碼為類比訊號、或將類比訊號解碼為數位訊號。類比訊號可為無線電、紅外線、電流等,常見的應用有wifi、手機、藍芽、有線電話、光纖網路等。

 - 一般的modem接法為DTE-DCE-circuit-DCE-DTE,若要使DTE-DTE或DCE-DCE相連,則要透過NULL Modem的方式,其實就是為了欺騙電腦,讓電腦以為它所連接的是一部數據機,而能夠順利地進行數據傳輸,在這裡用了跳線的接法。

 - 跳線就是一個傳送的訊號必須到達對方的接收腳位,如此才能形成一個完整的通路,所以通路的形成就是將一方的傳送與接收的腳位作對調;如此一來,甲方的傳送資料必定到達乙方的接收通道;而乙方的傳送資料則會到達甲方的接收通道,雙方的送收形成一個完整的迴路,最精簡的情形就是只使用2、3、5即可以完成資料傳輸。 

.. image:: /embedded/USART_NullModemBriefview.jpg
![](/embedded/USART_NullModemBriefview.jpg)

也有市售的接頭

.. image:: /embedded/USART_NullModem.jpg
![](/embedded/USART_NullModem.jpg)

RS-232阻礙

  - 過大的電壓擺幅,造成耗電量的增加
  - 單端訊號對於雜訊抑制的能力並不佳
  - DB25的接頭過大

單端信號傳輸與差分信號傳輸

以前,個人電腦所連接電纜的信號傳輸的主流方式是單端信號方式,其代表性特點是列表機連接使用並行接口(parallel port),調制解調器(modem)使用RS-232C。

單端信號傳輸

.. image:: /embedded/single-ended.png
![](/embedded/single-ended.png)

 - 採用的是多個信號線共同使用信號返回的地線的方式。進行電壓檢測時,通過地線信號的電位,判斷邏輯。

在這種方式下,列舉如下兩個提高傳輸速率的方法:

 - 提高各信號線的傳輸速度
 - 增加信號線個數

如果增加信號線個數,連接器會更加大型化,電纜也變得更粗。如果單純地提高信號的速度,那麼不僅需要昂貴的IC,而且輻射的電磁干擾噪音也會變強。
如果降低電壓振幅,由於信號的上升/下降時間會縮短,高速傳輸也變得相對容易。但是如果電壓降低,那麼由於外部噪音的影響,很容易發生錯誤,為了解決這些問題,差分傳輸技術開始被廣泛使用。

差分信號傳輸

![Image](/embedded/Differential)Signal.png
![](/embedded/Differential Signal.png)

 - 使用兩根信號線,這兩個信號的振幅相同,相位相反,電流在彼此間逆向流動,信號接收端比較這兩個電壓的差值來判斷發送端發送的是邏輯0還是邏輯1。在電路板上,差分走線必須是等長、等寬、緊密靠近、且在同一層面的兩根線,USB3.0就是高速差分傳輸的一種。

至於來自於外部的噪音,即使在正負兩端的信號線外施加同樣的噪音,因差分傳輸而容易發現信號線間的電位差,所以噪音會被消除,不易引發錯誤。

.. image:: /embedded/differential_noise.png
![](/embedded/differential_noise.png)

 - 通過相互間逆向流過電流,抵消磁通,由此降低信號高次諧波所引發的電磁干擾噪音。

但若電路板的面積非常吃緊,單端信號可以只有一根信號線,地線走地平面,而差分信號一定要走兩根等長、等寬、緊密靠近、且在同一層面的線。這常常發生在晶片的pin腳間距很小,以至於只能穿過一根走線的情況下。

STM32 USART介紹與特性
.................................
==========================

 - 可調整oversampling長度(8 or 16),藉此在速度以及時脈之間做取捨。

 - Factional baud rate generator systems。常見的tx/rx baud rate設定法,

 - 可程式化的資料長度 (8 or 8+1 bits)

 - 可程式化的停止位元 (1 or 2 bits),在Smartcard模式支援0.5及1.5(建議)bits。

 - LIN 主從同步資料傳輸,使用break傳輸/偵測達到此目的。

 - 同步傳輸模式下,提供tx的CLK信號

 - IrDA SIR 編解碼器

 - 可做為Smartcard模擬器
   
 - 支援單線半雙工通訊

 - 可用DMA(Direct Memory Access)設定多重緩衝區並進行資料交換。
  
 - TX/RX都有各自獨立的Enable Bit(TE、RE)

 - 3個傳輸檢測標誌

 - 檢測控制

 - 4個錯誤檢測標誌

 - 支援10種中斷

 - 多處理器通訊,最多可將16個節點串成同一個網路(因USART_CR2_ADD只有四位元)。

 - 2種喚醒接收器的方式

USART Block Diagram
======================================
.. image:: /embedded/USART_pic296.jpg
![](/embedded/USART_pic296.jpg)

Ref: [RM0090 Reference Manual P.949](http://www.st.com/web/en/resource/technical/document/reference_manual/DM00031020.pdf)

此通訊界面以三個腳位與其他設備連接。任何USART雙向通信至少需要兩個腳位:接收資料輸入(RX)和發送資料輸出(TX)
   - RX: 接收資料輸入。藉由Oversampling技術判斷有效資料及噪音
   - TX: 發送資料。若發送器沒有被啟用,則此腳位會回到I/O port設定狀態。當發送器被啟動時,如果沒有傳送數據,則TX保持高電位。在單線半雙工模式或Smartcard 模式時,此I/O同時被用於資料的傳送和接收(以USART角度來看此情況,TX負責傳輸資料,但接收資料由SW_RX負責)。
* 此通訊界面以三個腳位與其他設備連接。任何USART雙向通信至少需要兩個腳位:接收資料輸入(RX)和發送資料輸出(TX)
    - RX: 接收資料輸入。藉由Oversampling技術判斷有效資料及噪音
    - TX: 發送資料。若發送器沒有被啟用,則此腳位會回到I/O port設定狀態。當發送器被啟動時,如果沒有傳送數據,則TX保持高電位。在單線半雙工模式或Smartcard 模式時,此I/O同時被用於資料的傳送和接收(以USART角度來看此情況,TX負責傳輸資料,但接收資料由SW_RX負責)。

以USART傳輸資料時,串列資料由下列frames組成:  
   - 傳輸或接收資料之前,由Idle Line表示。
   - 一個start bit
   - 一個資料word,可為8/9 bits,用least significant bit做資料排序。根據USART_CR1暫存器中的M位選擇8或9位元決定資料長度。
   - 一組0.5, 1, 1.5, 2 stop bits,用以表示該次frame傳輸完畢。
* 以USART傳輸資料時,串列資料由下列frames組成:  
    - 傳輸或接收資料之前,由Idle Line表示。
    - 一個start bit
    - 一個資料word,可為8/9 bits,用least significant bit做資料排序。根據USART_CR1暫存器中的M位選擇8或9位元決定資料長度。
    - 一組0.5, 1, 1.5, 2 stop bits,用以表示該次frame傳輸完畢。

另外包含以下數種register: 
   - 狀態暫存器(USART_SR)
   - 資料暫存器(USART_DR)
   - baud rate暫存器(USART_BRR)。儲存由fractional baud rate generator產生的傳輸速率,以12位整數和4位小數表示
   - Guardtime暫存器(USART_GTPR),供Smartcard模式使用
* 另外包含以下數種register: 
    - 狀態暫存器(USART_SR)
    - 資料暫存器(USART_DR)
    - baud rate暫存器(USART_BRR)。儲存由fractional baud rate generator產生的傳輸速率,以12位整數和4位小數表示
    - Guardtime暫存器(USART_GTPR),供Smartcard模式使用

另外在同步模式中,需要此一腳位:
  
   - SCLK: 在同步模式下,送出傳送器目前的時脈數值。可對應至SPI master mode(在start bit和stop bit不送出clock訊號,另外可用軟體選擇是否在最後一個data bit送出clock訊號)。送出時脈數值的同時,資料可以在RX端被接收。這種特性可用於控制擁有shift暫存器的周邊設備(例: LCD驅動)。時脈的相位以及訊號極性可用軟體設定。在Smartcard模式下,SCLK可對Smartcard提供本身的時脈。
   
在Hardware flow control中,則另外需要下列兩個腳位:
   
   - nCTS: 阻擋發送資料。若在高電位,則當目前資料傳送結束後,中斷下一次的資料傳送
* 另外在同步模式中,需要此一腳位:
    - SCLK: 在同步模式下,送出傳送器目前的時脈數值。可對應至SPI master mode(在start bit和stop bit不送出clock訊號,另外可用軟體選擇是否在最後一個data bit送出clock訊號)。送出時脈數值的同時,資料可以在RX端被接收。這種特性可用於控制擁有shift暫存器的周邊設備(例: LCD驅動)。時脈的相位以及訊號極性可用軟體設定。在Smartcard模式下,SCLK可對Smartcard提供本身的時脈。
   
   - nRTS: 請求發送資料。若在低電位,則表示USART已經準備好接收資料
* 在Hardware flow control中,則另外需要下列兩個腳位:
    - nCTS: 阻擋發送資料。若在高電位,則當目前資料傳送結束後,中斷下一次的資料傳送  
    - nRTS: 請求發送資料。若在低電位,則表示USART已經準備好接收資料

USART data frame & M bit
-------------------------

每次傳輸資料時,USART會以一個frame作為一次傳輸的單元。



.. image:: /embedded/USART_DataFrame.jpg


.. code-block:: c


    在起始位(start bit)期間,資料發送端(TX)處於低電位;在停止位(stop bit)期間,資料發送端(TX)處於高電位。
![](/embedded/USART_DataFrame.jpg)


```
在起始位(start bit)期間,資料發送端(TX)處於低電位;在停止位(stop bit)期間,資料發送端(TX)處於高電位。
```

.. image:: /embedded/USART_8bit_length.jpg
![](/embedded/USART_8bit_length.jpg)


.. code-block:: c

    若將USART_CR1_M 設定為0,則發送的data frame會變成這樣。

    Idle & break frame的長度也會與data frame的長度一樣。Idle 會發送一個frame的高電位、break則是發送一個frame的低電位。
```
若將USART_CR1_M 設定為0,則發送的data frame會變成這樣。

    發送break frame之後,會另外插入1~2 stop bit,藉此區分下一次的data frame(因為data frame的開頭也是低電位)。
Idle & break frame的長度也會與data frame的長度一樣。Idle 會發送一個frame的高電位、break則是發送一個frame的低電位。

發送break frame之後,會另外插入1~2 stop bit,藉此區分下一次的data frame(因為data frame的開頭也是低電位)。
```

.. image:: /embedded/USART_9bit_length.jpg
![](/embedded/USART_9bit_length.jpg)


.. code-block:: c

    若將USART_CR1_M 設定為1,則發送的data frame會比上一張圖多一個bit。

    Idle & break frame的長度也會變長1 bit。
```
若將USART_CR1_M 設定為1,則發送的data frame會比上一張圖多一個bit。

Idle & break frame的長度也會變長1 bit。
```



10種中斷
-------
 – CTS改變(CTSIE, CTS interrupt enable)

 – LIN中斷檢測(LBDIE, LIN break detection interrupt enable)

 – 傳送緩衝區空(TXEIE, Data buffer empty interrupt enable)

 – 傳送完成(TCIE, Transmission complete interrupt enable)

 – 接收緩衝區滿(RXNEIE, Data buffer not empty interrupt enable)

 – 空閒線路檢測(IDLEIE, Idle interrupt enable)

 – 溢出錯誤(Overrun error)

 – Frame錯誤(Framing error)

 – 噪音錯誤(Noise error)

 – 檢驗錯誤(Parity error, PEIE)
 - CTS改變(CTSIE, CTS interrupt enable)
 - LIN中斷檢測(LBDIE, LIN break detection interrupt enable)
 - 傳送緩衝區空(TXEIE, Data buffer empty interrupt enable)
 - 傳送完成(TCIE, Transmission complete interrupt enable)
 - 接收緩衝區滿(RXNEIE, Data buffer not empty interrupt enable)
 - 空閒線路檢測(IDLEIE, Idle interrupt enable)
 - 溢出錯誤(Overrun error)
 - Frame錯誤(Framing error)
 - 噪音錯誤(Noise error)
 - 檢驗錯誤(Parity error, PEIE)

3個傳輸檢測標誌
------------

 – 接收緩衝區滿(RXNE,Data buffer not empty)

 – 傳送緩衝區空(TXE,  Data buffer empty)

 – 傳輸結束(TC,  Transmission complete)
 - 接收緩衝區滿(RXNE,Data buffer not empty)
 - 傳送緩衝區空(TXE,  Data buffer empty)
 - 傳輸結束(TC,  Transmission complete)




Tx傳送器
=======

 - 傳送器依據USART_CR1的M位狀態來決定發送8或9位元的資料。
 - 當transmit enable bit(TE)被設定時,在transmit shift register的資料會經由TX腳位送出,同時,相對應的時鐘脈衝會由SCLK腳位輸出。

資料的傳送
----------

在USART發送期間,TX首先傳送資料的最低有效位元(least significant bit)。在此模式中,USART_DR與內部匯流排和transmit shift register會之間包含一個緩衝器(TDR)。

每個資料在傳送前都會有一個低電位的起始位(start bit);資料傳完之後會接著一組停止位元(stop bit)。

在傳送資料的過程中,不可以去更改TE的設定,否則會導致baud rate counter停止,目前正在傳的資料也會毀損(因只傳了一部份)。
TE被開啟時,會立即送出一個idle frame。

停止位元的數目可由使用者決定為0.5, 1, 1.5或2 bits:

   - 1 bit的stop bit: 預設的停止位位元數
   - 2 bits的stop bit: 一般USART模式、單線傳輸模式和modem modes
   - 0.5 bits的stop bit: Smartcard mode接收數據用
   - 1.5 bits的stop bit: Smartcard mode接收或發送數據用

傳送idle frame時,會連stop bits一起送出,因idle frame本身就包含stop bits。
傳送break時,會連續傳輸10個低電位bits(包含1個stop bit,此時M=0),或是11個低電位bits(包含2個stop bits,此時M=1)。但是不可能傳輸過長的break(大於10/11低電位bits)

**stop bits其實不算是個bit,他是傳輸結束後的一段時間(period),用以區隔每個傳輸的資料,其功用是在非同步傳輸的時候可以告訴接收器,資料傳輸已經結束。透過增加stop bits的長度,可讓接收器能有足夠的時間可以處理該資料**

**另外,由於資料搬移到transmit shift register中最少需要1/2 baud clock,因此在Smartcard mode的接收中,最少必須設定0.5 bit的stop bits**

Ref: [RM0090 Reference Manual P.952](http://www.st.com/web/en/resource/technical/document/reference_manual/DM00031020.pdf)


傳送器的設定
----------

.. image:: /usart_fig298.jpg
![](/usart_fig298.jpg)

.. image:: /embedded/USART_DataTransmission.gif
![](/embedded/USART_DataTransmission.gif)

.. image:: /usart_transmiter.png
![](/usart_transmiter.png)

設定流程如下:

   1. 設定USART_CR1的UE為1來啟動傳輸,如圖中的(a)
   2. 設定USART_CR1的M決定資料長度,如圖中的(b)
   3. 設定USART_CR2中的STOP位來決定停止位元的長度,如圖中的(c)
   4. 採用多重緩衝器的話,則須設定USART_CR3的DMAT啟動DMA,並按照多重緩衝器的章節內容去設定DMA,如圖中的(d)
   5. 利用USART_BRR暫存器設定baud rate,如圖中的(e)
   6. 設定USART_CR1的TE為1,在第一筆資料傳送前,傳送一個空閒的frame,如圖中的(f)
   7. 將欲發送的資料寫入USART_DR中,此動作會一併清除TXE,如圖中的(g)。
   8. 若有多筆資料要傳送,則重複步驟7.,如圖中的(l)。
   9. 當最後一筆資料寫入USART_DR時,要等到TC=1才可以做其他動作。TC=1代表所有資料傳輸已經結束。此動作為的是避免最後一筆資料在傳輸時毀損(因USART此時可能已經被關閉,或是進入halt mode)。


當資料放入USART_DR會由硬體清除TXE位,如圖中的(h),則表示:

   1. 資料已從TDR中放入transmit shift register,而且資料已開始傳送
   2. TDR暫存器無資料
   3. 下一筆資料可放入USART_DR中,並且不會覆蓋前一筆資料


若設定TXEIE為1,則會產生一個中斷,如圖中的(i):

   - 如果USART正在發送資料,對USART_DR的寫入會把資料移到TDR暫存器中,並在目前的資料傳送結束後,把TDR的資料移進transmit shift register中
   
   - 如果USART沒有在發送資料,則對USART_DR寫入資料時,會直接把該筆資料放入transmit shift register中,並啟動傳送,當傳送開始時,硬體會立即設定TXE位。

當一個frame的資料發送完畢(送出stop bits後),TC位會被設定為高電位,如圖中的(j),如果USART_CR1中的TCIE有被設定,則會產生一個中斷,如圖中的(k)。

當最後一筆資料寫入USART_DR後,一定要等到TC=1才可以把USART關掉,或是讓整個控制器進入低功耗模式。

在一般模式下,若要清除TC,可以直接對TC寫入0。如果是使用多重緩衝區模式,則要先讀取USART_SR暫存器,再對USART_DR暫存器做寫入動作。

.. image:: /embedded/USART_pic299.jpg
![](/embedded/USART_pic299.jpg)


傳送斷開符號
------------------------------------
 - 透過設定USART_CR1的SBK位,可以發送一個斷開符號,斷開符號的長度取決於M位。

 - 如果SBK=1,則在目前的資料發送後,在TX線上再發送一個斷開符號。當斷開符號傳送完成後,會由硬體重設SBK至0。

 - USART會由硬體在最後一個斷開符號的結束處插入一個'1',確保能辨識下一個資料的起始位。


傳送空閒符號
------------------------------------
 - 設置USART_CR1的TE,會使得USART在發送第一筆資料前,發送一個空閒符號,喚醒接收端。


接收器
====================================
 - 接收器依據USART_CR1 M位的狀態來決定接收8或9位元的資料。

Oversampling
------------

定義:在訊號處理中,oversampling 是以取樣頻率大於Nyquist rate的取樣訊號處理。因此取樣頻率高於Nyquist rate,即可讓有限的頻寬完美重現。

目的: 可用於改善 影響解析度、減少雜訊和避免aliasing

.. image:: /embedded/oversampling_tmmg.jpg
![](/embedded/oversampling_tmmg.jpg)

起始位元偵測(oversampling)
------------------------------------

.. image:: /usart_fig300.jpg
![](/usart_fig300.jpg)


在USART中,如果辨認出一個特殊的採樣序列( 1 1 1 0 X 0 X 0 X 0 0 0 0 ),則認定偵測到一個起始位。不論是用哪種oversampling(16 or 8)方法,這個序列都一樣。

如果在第一次採樣(第3、5、7採樣點)都收集到0,而且第二次採樣(第8、9、10採樣點)也是都收集到0,則認定已經偵測到start bit(此時RXNE會設定為1,若RXNEIE=1會額外發出interrupt)。

如果在第一次採樣(第3、5、7採樣點)收集到2個以上的0,而且第二次採樣(第8、9、10採樣點)也是收集到2個以上的0,也會認定已經偵測到start bit(此時RXNE會設定為1,若RXNEIE=1會額外發出interrupt)。但是會另外去把NE設定為1,因為可能在接收過程中有噪音訊號。

**如果這兩次採樣結果不相符(例: 一次採到2個0,另一次採到2個1),則接收端停止start bit偵測、回到idle state並等待下一次的電壓下降。**

如果在這兩次採樣過程中,有任何一次只收集到2個0(但另一次收集到3個0),還是會認定已經偵測到start bit,但也會把NE設定為1,理由同上。


**採樣的時間間隔**

.. image:: /usart_sampling.png
![](/usart_sampling.png)

假設baud rate = 9600 bps,則一個bit的傳輸時間為104us,usart會在接收器啟動後的52us,開始採樣

若偵測到開始位元,則開始接收資料,反之則等待104us,再採樣一次

停止位元偵測(oversampling)
-----------------------------------------------------

Stop bits的接收數目可以由USART_CR2去設定,在一般模式可選擇1 or 2,在smartcard模式則可選擇0.5 or 1.5。

   1. 0.5 stop bit(用於smartcard模式的接收器): 不進行採樣,所以沒辦法偵測到framing錯誤,或是偵測出break frame。
   2. 1 stop bit: 在第8, 9, 10個採樣點進行採樣
   3. 1.5 stop bit(用於smartcard模式,包含接收器和傳送器): 1.5 stop bit的採樣是在第16, 17, 18個採樣點進行(在stop bit開始後1個baud clock之後才開始採樣)。而1.5 stop bit可以分成前0.5和後1 stop bit。在前0.5 stop bit甚麼事都不做,在後1 stop bit的中間(16, 17, 18)才開始採樣。在smartcard模式傳輸資料時,必須要確保每筆資料都有正確地送出去。所以接收器一定要把USART_CR1的RE設定為1,然後stop bit會被拿來偵測是否有parity error產生。如果發生了parity error,smartcard會在採樣時強制把資料訊號拉至低電位(此為NACK訊號,這種訊號會被另一端標記成framing error)。在1.5 stop bit結束時,FE和RXNE會同時被設定為1。其餘請參考smartcard章節。
   4. 2 stop bits: 在第一個stop bit會對第8, 9, 10個採樣點進行採樣,如果在第一個stop bit就偵測出framing error,會直接去設立framing error旗標,然後第二個stop bit就不會拿來偵測framing error了。RXNE會在第一個stop bit結束採樣時被設立。


資料的接收
------------------------------------
 - 在USART接收期間,RX從資料最低有效位元(least significant bit)開始接收,因此在此模式中,USART_DR和received shift register之間包含一個緩衝器(RDR)。


接收器的設定
------------------------------------

.. image:: /usart_recevier.png
![](/usart_recevier.png)


   1. 設定USART_CR1的UE為1來啟動USART接收,如圖中的(a)
   2. 設定USART_CR1的M決定資料長度,如圖中的(b)
   3. 設定USART_CR2的STOP來決定停止位元的長度,如圖中的(c)
   4. 若需要採用多重緩衝器接收資料,則須設定USART_CR3的DMAR啟動DMA,並按照多重緩衝器的章節內容去設定DMA,如圖中的(d)
   5. 利用USART_BRR設定baud rate,如圖中的(e)
   6. 設定USART_CR1暫存器中的RE,此動作會啟動接收器並開始偵測起始位,如圖中的(f)

當資料被接收到後:
   1. 硬體會設定RXNE位,表示received shift register中的資料已移入RDR中,亦即資料已被接收並可被讀出(也包含了已經偵測到的錯誤),如圖中的(g)
   2. 若USART_CR1中的RXNEIE被設定時,會產生一個中斷,如圖中的(h)
   3. 資料接收期間如檢測到frame錯誤或是噪音、溢出錯誤等問題,相關的標誌將被設定(FE、NF、ORE)
   4. 若使用多重緩衝區模式,RXNE在每個字元接收後會被設置,並在DMA讀取RDR之後被清除
   5. 在一般模式(單緩衝區)下,藉由軟體讀取USART_DR可清除RXNE,也可以直接對RXNE寫入0。RXNE一定要在"接收下一筆資料"這個動作結束前被清除,以免產生溢出錯誤
* 當資料被接收到後:
    1. 硬體會設定RXNE位,表示received shift register中的資料已移入RDR中,亦即資料已被接收並可被讀出(也包含了已經偵測到的錯誤),如圖中的(g)
    2. 若USART_CR1中的RXNEIE被設定時,會產生一個中斷,如圖中的(h)
    3. 資料接收期間如檢測到frame錯誤或是噪音、溢出錯誤等問題,相關的標誌將被設定(FE、NF、ORE)
    4. 若使用多重緩衝區模式,RXNE在每個字元接收後會被設置,並在DMA讀取RDR之後被清除
    5. 在一般模式(單緩衝區)下,藉由軟體讀取USART_DR可清除RXNE,也可以直接對RXNE寫入0。RXNE一定要在"接收下一筆資料"這個動作結束前被清除,以免產生溢出錯誤


接收斷開符號
------------------------------------
 - USART在接收斷開符號後,該符號處理流程等同framing error。


接收空閒符號
------------------------------------
 - 當空閒符號被偵測到時,該符號處理流程等同一般資料,但如果USART_CR1的IDLEIE被設置時,還會產生一個中斷

接收器對時鐘誤差容忍度
-------------------

必須要使整個時脈系統的時鐘誤差處於USART接收器的容許範圍內,USART接收器才能夠正常運作。時脈系統的誤差來源有以下幾種: 
   - DTRA: 傳送器的誤差(Deviation due to TRAnsmitter error)。這誤差也包含了傳送器本身的時脈誤差。
   - DQUANT: 接收器的baud rate量化出錯(Devation due to baud rate QUANtization of the receiver)
   - DREC: 接收器的時脈誤差(Deviation due to RECeiver's local oscillator)
   - DTCL: 資料傳輸線的錯誤(Deviation due to Transmission Line)。通常起因於傳輸器,在傳輸資料時,從高電位轉至低電位、或從低電位轉至高電位,在電位轉換期間出現時間誤差。
* 必須要使整個時脈系統的時鐘誤差處於USART接收器的容許範圍內,USART接收器才能夠正常運作。時脈系統的誤差來源有以下幾種: 
    - DTRA: 傳送器的誤差(Deviation due to TRAnsmitter error)。這誤差也包含了傳送器本身的時脈誤差。
    - DQUANT: 接收器的baud rate量化出錯(Devation due to baud rate QUANtization of the receiver)
    - DREC: 接收器的時脈誤差(Deviation due to RECeiver's local oscillator)
    - DTCL: 資料傳輸線的錯誤(Deviation due to Transmission Line)。通常起因於傳輸器,在傳輸資料時,從高電位轉至低電位、或從低電位轉至高電位,在電位轉換期間出現時間誤差。

總體而言: DTRA + DQUANT + DREC + DTCL < USART接收器的容許上限
* 總體而言: DTRA + DQUANT + DREC + DTCL < USART接收器的容許上限

USART接收器的對於時脈誤差的容許上限,取決於下列選項: 
   - USART_CR1的M,可決定使用10/11資料位元。
   - USART_CR1的OVER8,可決定使用8/16 oversampling方法。
   - 是否有使用fractional baud rate
   - USART_CR3的ONEBIT,可決定使用單一採樣點或是三個採樣點。
* USART接收器的對於時脈誤差的容許上限,取決於下列選項: 
    - USART_CR1的M,可決定使用10/11資料位元。
    - USART_CR1的OVER8,可決定使用8/16 oversampling方法。
    - 是否有使用fractional baud rate
    - USART_CR3的ONEBIT,可決定使用單一採樣點或是三個採樣點。

4種錯誤檢測
==========

溢出錯誤(Overrun error)
------------------------------------
 - 在RXNE沒有重設為0的情況下,此時又接收到一筆新資料,則會發生溢出錯誤,如圖中的(i)。在RXNE沒有被清除時,資料將無法從Received shift register轉入RDR。
 - 在一般情況下,本身不產生中斷,在DMA情況下,則由EIE產生中斷,經檢驗USART_SR的ORE可得知溢出錯誤

當溢出錯誤產生時:

   1. USART_SR中的ORE將被設定為1,如圖中的(j)
   2. RDR中的內容不會被清除,因此讀取USART_DR仍可以得到之前的資料
   3. Received shift register中的資料將被覆蓋。覆蓋完之後,在接下來overrun錯誤發生的過程中,所有接收到的資料都會遺失。
   4. 如果RXNEIE被設為1,或是EIE(Error interrupt enable)和DMAR被為1,則會產生一個中斷,如圖中的(k)
   5. 依序讀取USART_SR和USART_DT暫存器,可清除ORE

**當ORE位被設置時,表示至少有一個資料已遺失,有以下兩種可能性: **

   1. 如果RXNE=1,表示之前的資料還在RDR中,且可被讀出
   2. 如果RXNE=0,表示之前的資料已被讀走,RDR已無資料可被讀取。若正在讀取RDR中的上一筆資料,而讀取時又接收到新的資料(這筆新的資料會遺失),就會發生這種情況。另一種情況是正在讀取USART_SR以及USART_DR的過程中,有新的資料被讀進來(但這筆資料會遺失),這也會導致相同結果。


噪音錯誤(Noise error)(select the proper oversampling method)
-----------------------------------------------------------

 - 接收器具備不同oversampling方法供使用者選擇(但在同步模式不可選擇),此方法可以區分有效資料以及噪音,並修復已接收到的資料。
 - 在一般情況下,本身不產生中斷,而由RXNE產生中斷,經檢驗USART_SR的NF得知錯誤
 - 在DMA情況下,則由EIE產生中斷,經檢驗USART_SR的NF得知錯誤

設定USART_CR1中的OVER8,即可選擇16個或8個baud clock的採樣,見Fig. 250和Fig. 251:
   - OVER8 = 1: 使用8次採樣可以達到更高速的資料傳輸(最高速為fPCLK/8),相對地接收器會沒辦法容許太多的時脈誤差。
   - OVER8 = 0: 使用16次採樣,則接收器可容許較多的時脈誤差,但傳輸速率會被限制於fPCLK/16
 - 設定USART_CR1中的OVER8,即可選擇16個或8個baud clock的採樣,見Fig. 250和Fig. 251:
    - OVER8 = 1: 使用8次採樣可以達到更高速的資料傳輸(最高速為fPCLK/8),相對地接收器會沒辦法容許太多的時脈誤差。
    - OVER8 = 0: 使用16次採樣,則接收器可容許較多的時脈誤差,但傳輸速率會被限制於fPCLK/16

設定USART_CR3中的ONEBIT,可選擇不同的噪音評估法:
   - ONEBIT = 0: 採樣資料中心的3個bits,若此3 bits不完全相等,則NF會被設定為1。適合用於容易產生噪音訊號的環境,如果偵測到有噪音(NF=1),會把該次收到的資料拋棄,因為NF=1代表採樣過程中可能有產生突波、干擾訊號等。
   - ONEBIT = 1: 只採樣資料中心的單一bit,此時NF就絕對不會被設定。適合用於沒有噪音訊號的環境,並且讓接收器容許更多的時脈誤差。
 - 設定USART_CR3中的ONEBIT,可選擇不同的噪音評估法:
    - ONEBIT = 0: 採樣資料中心的3個bits,若此3 bits不完全相等,則NF會被設定為1。適合用於容易產生噪音訊號的環境,如果偵測到有噪音(NF=1),會把該次收到的資料拋棄,因為NF=1代表採樣過程中可能有產生突波、干擾訊號等。
    - ONEBIT = 1: 只採樣資料中心的單一bit,此時NF就絕對不會被設定。適合用於沒有噪音訊號的環境,並且讓接收器容許更多的時脈誤差。

若在資料接收過程中檢測到噪音時:
   - NF會在RXNE升緣時被設定
   - 該次無效資料會從received shift register移入USART_DR
   - 在單一byte通訊模式不會直接產生中斷,而是在NF被設定為1時(此時RXNE會一併設定為1),由RXNE來產生中斷;使用多重緩衝器模式時,如果USART_CR3暫存器中的EIE被設定為1,則會產生一個中斷
 - 若在資料接收過程中檢測到噪音時:
    - NF會在RXNE升緣時被設定
    - 該次無效資料會從received shift register移入USART_DR
    - 在單一byte通訊模式不會直接產生中斷,而是在NF被設定為1時(此時RXNE會一併設定為1),由RXNE來產生中斷;使用多重緩衝器模式時,如果USART_CR3暫存器中的EIE被設定為1,則會產生一個中斷

.. image:: /oversampling16.png
![](/oversampling16.png)

.. image:: /oversampling8.png
![](/oversampling8.png)

.. image:: /noisedetection.png
![](/noisedetection.png)

.. image:: /noisedetectionsampledata.png
![](/noisedetectionsampledata.png)


Frame錯誤(Frame error)
------------------------------------

 - 起因於傳輸端/接收端沒有同步、或者傳輸線路上有大量的噪音,使得stop bit沒有在預期的時間內被識別出來。
 - 在一般情況下,本身不產生中斷,而由RXNE產生中斷,經檢驗USART_SR的FE可得知Frame錯誤
 - 在DMA情況下,則由EIE產生中斷,經檢驗USART_SR的FE得知錯誤


當Frame錯誤被檢測出時:

   1. FE位被硬體設定為1,如圖中的(l)
   2. 無效的資料從received shift register移入USART_DR中
   3. 在單一byte通訊模式不會直接產生中斷,而是在NF被設定為1時(此時RXNE會一併設定為1),由RXNE來產生中斷;使用多重緩衝器模式時,如果USART_CR3暫存器中的EIE被設定為1,則會產生一個中斷,如圖中的(k)

依序讀取USART_SR和USART_DR暫存器可恢復FE至0

奇偶檢測CONTROL(Parity error)
----------------------------
 - Parity control是用來確保傳輸資料的正確性。其原理是在傳輸端產生一個parity bit,然後在接收端可以重新計算parity bit以確保在傳輸過程沒有發生錯誤。
 - 在STM32,它可以透過設定USART_CR1 register的PCE bit來打開。STM32的frame長度是由M bit所決定,所以USART的frame有以下這些可能格式:

.. image:: /frame_formats.png
![](/frame_formats.png)

parity依算方式的不同分成兩種方式,even parity和odd parity

 - Even parity
    - 如果一個frame內1的數量是偶數,則在 even parity的情況下會把parity bit設為0。

    - E.g.: 假設 data=00110101; 因為有 4 bits被設為1,而且我們選擇的是 even parity(PS bit in USART_CR1 = 0),所以 parity bit被設為0。

 - Odd parity

    - 如果一個frame內1的數量是奇數,則在 odd parity的情況下會把parity bit設為0。

    - E.g.: 假設 data=00110101; 因為有 4 bits被設為1,而且我們選擇的是 odd parity(PS bit in USART_CR1 = 1),所以 parity bit被設為1。

 - 接收後會做 parity checking
    – 對接收的資料進行檢測(Checks parity of received data byte)

    - 如果 parity check 失敗了,USART_SR register的PE flag會被設立,然後如果USART_CR1 register的PEIE bit也有被設立的話,還會產生中斷。

    - PE flag最後在軟體執行(a read from the status register followed by a read or write access to the USART_DR data register)時被清除。


 - 傳送前會做 parity generation

    – 發送檢測位(Transmits parity bit)

    - 如果USART_CR1的PCE bit被設立,那麼MSB會被改成parity bit(PS=0 是even parity, PS=1 是odd parity)

       - MSB: Most Significant Bit,代表位數最大的那個bit
        - MSB: Most Significant Bit,代表位數最大的那個bit

       - LSB: Least Significant Bit,代表位數最小的那個bit
        - LSB: Least Significant Bit,代表位數最小的那個bit

鮑率的設定
=========

 - 接收器和傳送器的Baud rate分別由USART_BRR設置USARTDIV的整數部分(Mantissa)及小數部分(Fraction),計算方式如下所示:

.. image:: /baud.png
![](/baud.png)
Ref: [RM0090 Reference Manual P.959](http://www.st.com/web/en/resource/technical/document/reference_manual/DM00031020.pdf)

其中USARTDIV為一個無號的定點數(unsigned fixed point number),fCK為給周邊設備的時鐘。

   - 當OVER8 = 0 時,小數部分佔USART_BRR的DIV_Fraction[3:0],共 4 bits
   
   - 當OVER8 = 1 時,小數部分佔USART_BRR的DIV_Fraction[2:0],共 3 bits,其中DIV_Fraction[3]應該保持'0'

**USART_BRR被更新後,baud rate的計數器中的值也會同時被更新,因此在傳輸途中不應該更新USART_BRR中的值。
  另外,如果TE或RE被分別禁止,則baud rate的計數器也會停止計數**

使用stm32f407vgt6官方lib時,會透過檔案中設定的時脈和baud rate去換算出USART_BRR的值,包含整數與小數部分。.

   - BRR(USARTDIV) 的值 Mantissa = 0x088B ; Fraction = 0x08 =>計算方式 0x88B->0d2187 + 8/16 = 2187.5

if over8=0 計算baud rate的方式: baud rate = usart時脈/(8 * (2-over8) * DIV).
 
   - usart時脈42Mhz, baud rate = 42000000/(8 * 2 * 2187.5) = 1200

usart是接在APB BUS上方,stm32f407vgt6有兩組APB各對應不同usart。usart時脈要看APB供應的時脈,
APB時脈要透過RCC和PLL設定去看clock tree。.

   - 預設stm32f4-discovery這塊板子外部震盪器(HSE_VALUE)是8Mhz(官方lib好像設定成25Mhz)。.
   - 8Mhz透過pll_M(8)除頻輸入PLL =>8Mhz/8=1Mhz.
   - 1Mhz輸入PLL,透過pll_N(0x5400)倍頻再透過pll_P(2)除頻,作為sysclk => (1Mhz * 0x5400>>6)/2 = 168Mhz.
   - sysclk轉接HCLK都是168Mhz.
   - HCLK>>2轉給PCLK1 => 168Mhz>>2 = 42Mhz.

多處理機通訊
===========

 - 除了一對一通訊之外,也可以將許多USART串成一個小型網路(multiprocessor communications)。
 - 在這些USART中,可以選出一個USART作為master,其餘的就做為slave。而master的TX會連到所有slave的RX,所有slave的TX則會連接到邏輯AND後,再連接至master的RX。
 - USART的地址放在USART_CR2_ADD,因為只有4位元,所以最多支援到16個節點。


在多處理機通訊模式下,我們會希望只把訊息傳給該知道的機器就好,如此一來能夠減少不必要的傳輸動作(把資料也傳給其他機器)。
 - 在多處理機通訊模式下,我們會希望只把訊息傳給該知道的機器就好,如此一來能夠減少不必要的傳輸動作(把資料也傳給其他機器)。

沒接收到資料的機器,可以用mute功能使該機器進入mute模式,在mute模式下的機器行為: 
   - 無法變更接收器的任一個status bit
   - 與接收器相關的interrupt會停用
   - USART_CR1的RWU會被設定為1。RWU可被硬體自動控制,或是在某些限制條件下用軟體變更。
 - 沒接收到資料的機器,可以用mute功能使該機器進入mute模式,在mute模式下的機器行為: 
    - 無法變更接收器的任一個status bit
    - 與接收器相關的interrupt會停用
    - USART_CR1的RWU會被設定為1。RWU可被硬體自動控制,或是在某些限制條件下用軟體變更。

若要使機器離開mute模式,可以用下列兩種方式的其中一種,端看使用者如何設定USART_CR1的WAKE
   - 若WAKE被設定為0,機器進入idle line偵測
   - 若WAKE被設定為1,機器進入address mark偵測
 - 若要使機器離開mute模式,可以用下列兩種方式的其中一種,端看使用者如何設定USART_CR1的WAKE
    - 若WAKE被設定為0,機器進入idle line偵測
    - 若WAKE被設定為1,機器進入address mark偵測

Idle line detection(WAKE=0)
---------------------------

 - 在接收端處於靜默(mute mode)時,可透過發送空閒符號(即所有位均為'1'的資料),喚醒接收端。

 - 若RWU被設定為1,則USART進入mute模式。

 - 如果在mute模式時偵測到Idle frame,則機器會醒過來並進入一般USART模式。此時RWU會被硬體清除(=0),但是USART_SR的IDLE不會被設定為1。

 - RWU也可以用軟體設定成0。

.. image:: /embedded/USART_pic303.jpg
![](/embedded/USART_pic303.jpg)

Address mark detection(WAKE=1)
------------------------------
 
 - 在此模式下,如果接收到的資料位元,其MSB是1,就會被當成位址,若MSB為0,則當成一般資料。在位址資料(1 byte)中,最後4個LSB是放接收者的位址,而接收到這筆資料的機器會拿自己的USART_CR2的ADD(放該機器的位址)與這4個LSB做比較,若相同則清除RWU位,後面的資料將能正常接收。

 - 如果接收到的位址資料,比較之後與自己的位址不相符,該機器就會進入mute模式。此時RWU會被硬體設定為1,而RXNE不會被設定成1(即使有收到位址資料)、沒有interrupt產生、也沒有對DMA送出請求,因為機器已經進入mute模式。

 - 如果接收到的位址資料與自己的位址相符,該機器會回到一般USART模式。此時RWU會被清除,其餘的資料也會按順序被接收進來,而RXNE也會因為RWU被清除的關係,被設定為1(因為收到位址資料,而且是與自己的位址相符)。

 - 在接收器的緩衝區沒有資料時(USART_SR的RXNE為0),可以對RWU寫入0或1。有資料時,對RWU的寫入動作一律不承認。

.. image:: /embedded/USART_pic304.jpg
![](/embedded/USART_pic304.jpg)

USART 與 SPI之關係
=================

 - SPI:它是主從式的架構,通常一個主設備和多個從設備,由四條信號線組成:SCLK、MISO、MOSI、CS

    - MOSI:master output, slave input,主設備輸出

    - MISO:master input, slave output,主設備輸入

    - SCLK:serial clock,clock信號,由主設備產生

    - CS:chip select (optional)

 - USART在全雙工的模式(特別是同步模式)下,也有類似的訊號

    - TX:傳送訊號給周邊

    - RX:週邊設備傳送給主設備的訊號

    - SCLK:由主設備產生的clock訊號

以上是兩者有類似的地方




STM32 USART的MODE
.................
==========================


Synchronous mode
===================

若要使用此模式,要把USART_CR2的CLKEN設定為1。下列設定必須要設為0: 
   - USART_CR2的LINEN
   - USART_CR3的SCEN、HDSEL、IREN
 
 - USART_CR2的LINEN
 - USART_CR3的SCEN、HDSEL、IREN

USART允許使用者以master mode控制雙向同步串列傳輸。SCLK腳位會輸出傳送器的時脈,而在送出start bit以及stop bit時,SCLK不會輸出時脈。根據USART_CR2的LBCL設定,可以決定是否在最後一個資料bit(該bit代表位址)於SCLK輸出時脈。USART_CR2的CPOL允許使用者選擇時脈極性,而USART_CR2的CPHA允許使用者選擇外部時脈的相位。

在idle state、前同步碼(preamble)以及傳送break時,外部SCLK腳位不會被啟用。

在同步模式下,USART傳送器的行為與非同步模式一樣。但是因SCLK與TX同步(因CPOL與CPHA的設定),TX送出的資料會是同步的。

此模式下的USART接收器會與非同步模式的行為不同。如果RE=1(CR1的設定),則資料會在SCLK的rising或falling edge被採樣(看CPOL與CPHA的設定),並且不使用任何oversampling。Setup以及hold time必須要明確地保留(依據baud rate變化而有所不同: 1/16 bit time)。

SCLK與TX須一同使用,所以只有在傳送器啟用(TE=1,CR1的設定)而且正在傳送資料(USART_DR)的情況下,SCLK才會輸出時脈。意即不太可能只接收同步資料,卻不傳送資料。

當傳送器和接收器皆關閉時(TE=RE=0),LBCL、CPOL、CPHA必須要被設定,以確保SCLK正常運作。在傳送器或接收器打開時,這三個設定不可以去動。

建議同時設定TE和RE,以減少接收器的setup和hold time。

另外,USART只支援master mode,不論是接收或傳送資料,皆無法使用外部時脈(因SCLK是單向輸出)。



LIN(local interconnection network) mode
=========================================

 - LIN(local interconnect network),車載網路的一種,用於連接車內電子設備(電動車窗、座椅控制等簡單的設備)。原先已有為了車載網路而開發的CAN協定(Controller area network),但將其拿來控制低階設備,不符經濟效益(太貴),所以在1990年代五家車商(BMW、Benz、Volvo、VW & Audi)聯合開發了此協定。LIN可用單一master連接16個slave,傳輸速率最高為19200 baud。好處是能夠降低成本、不用授權費、易於使用、也易於開發衍生設備。

 - 在USART被硬體設定為LIN模式時,提供13bit break產生器以及10/11bit break偵測器。
  
若要啟用此模式,須設定USART_CR2的LINEN為1,而下列設定必須要設定為0: 
   - USART_CR2的STOP[1:0](有兩個位元)以及CLKEN
   - USART_CR3的SCEN、HDSEL、IREN
 - 若要啟用此模式,須設定USART_CR2的LINEN為1,而下列設定必須要設定為0: 
    - USART_CR2的STOP[1:0] (有兩個位元)以及CLKEN
    - USART_CR3的SCEN、HDSEL、IREN

LIN傳送器
----------

以master來說,與一般USART傳送器具有相同的流程(請參閱傳輸器章節)。只是要按照下列方法做設定:
   - USART_CR1的M要設定為8 bit資料長度
   - USART_CR3的LINEN要設為1。而USART_CR3的SBK要設定為13 bit。送出break之後要再送出一個1,才能讓接收器開始偵測start bit。
 - 以master來說,與一般USART傳送器具有相同的流程(請參閱傳輸器章節)。只是要按照下列方法做設定:
    - USART_CR1的M要設定為8 bit資料長度
    - USART_CR3的LINEN要設為1。而USART_CR3的SBK要設定為13 bit。送出break之後要再送出一個1,才能讓接收器開始偵測start bit。

LIN接收器
----------

 - 在USART接收器介面有特別設計一個break偵測電路,與一般資料的接收電路區隔開來。不管USART處於甚麼狀態(Idle或是正在接收資料frame),都能夠偵測到break。

 - 當USART_CR1的RE設定為1時(接收器開啟),接收器電路就會從RX查看是否有start bit進來,偵測break或是資料也是用這個方法。如果偵測到start bit,也用相同的採樣方式(針對第8, 9, 10採樣點做偵測)去偵測訊號是否有雜訊。如果第10個(USART_CR2的LBDL=0)或第11個(USART_CR2的LBDL=1)收到的bit為0,且隨後跟著一個分隔符號,USART_SR的LBD會被設立,此時如果LBDIE的設定為1,就會發出interrupt。在驗證一個break之前,會先確保有收到分隔符號(代表RX已經回到高電位狀態)。

 - 偵測break時,若在收到足量的0之前卻收到1,則偵測電路就會取消break偵測,並去偵測start bit。

 - 如果LINEN設定為0,接收器會變成一般的USART接收器,也就是不去偵測break符號。

 - 若開啟了LIN模式,當framing錯誤發生時(收stop bit時卻收到0,有可能是收到break了),接收器會停止,直到break偵測迴路收到1(確認不是收到break),或是收到break後也收到分隔符號(確認收到break)。

.. image:: /embedded/USART_pic305.png
![](/embedded/USART_pic305.png)


單線半雙工模式
==============

若要啟用單線半雙工模式(Single-wire half-duplex communication),可以設定USART_CR3的HDSEL為1。而下列設定必須要設定為0:
   - USART_CR2的LINEN、CLKEN
   - USART_CR3的SCEN、IREN

 - USART_CR2的LINEN、CLKEN
 - USART_CR3的SCEN、IREN

USART可以設定成遵循單線半雙工協定,而TX和RX在內部結構來看是相連在一起的。USART_CR3的HDSEL可以選擇是要全雙工還是半雙工。

當HDSEL被設定為1的那刻起:
   - TX和RX在內部結構會變成相連的
   - RX腳位不會被使用
   - 只要沒有資料傳送,TX腳位都是處於釋放狀態,所以會變成一般的標準I/O腳位,處於Idle狀態或是等待接收。當TX腳位沒有被USART使用時,此腳位應該要設定為I/O使得TX成為floating input,或是成為高電位輸出的open-drain。

 - TX和RX在內部結構會變成相連的
 - RX腳位不會被使用
 - 只要沒有資料傳送,TX腳位都是處於釋放狀態,所以會變成一般的標準I/O腳位,處於Idle狀態或是等待接收。當TX腳位沒有被USART使用時,此腳位應該要設定為I/O使得TX成為floating input,或是成為高電位輸出的open-drain。

除了以上的敘述之外,此模式的通訊過程都與一般的USART沒甚麼不同,只是這條線的使用權必須要由軟體決定(mutex之類的)。
另外,傳輸的觸發絕對不會被硬體擋住,而且只要有資料被寫入data register(USART_DR)且TE=1時,就會立刻觸發傳輸,並將資料送出。



智慧卡模式
=========

 - Smartcard mode在ISO7816-3標準中,Smartcard介面可支援非同步傳輸。

.. image:: /smart_card.jpg
![](/smart_card.jpg)

.. image:: /embedded/USART_SmartCardPin.jpg
![](/embedded/USART_SmartCardPin.jpg)

若要啟用,須設定USART_CR3的SCEN。另外,下列暫存器一定要清空: 
   - USART_CR2的LINEN
   - USART_CR3的HDSEL以及IREN
 - 若要啟用,須設定USART_CR3的SCEN。另外,下列暫存器一定要清空: 
    - USART_CR2的LINEN
    - USART_CR3的HDSEL以及IREN

使用此模式時,也可考慮設定CLKEN以提供時脈給smartcard。
 - 使用此模式時,也可考慮設定CLKEN以提供時脈給smartcard。

若要使用Smartcard模式,USART應設定為: 
   - 8 bit以上檢測位元: 在USART_CR1中,M以及PCE應設定為1。
   - 1.5 stop bits: 傳輸/接收時會需要。在USART_CR2中,STOP應設為11。
 - 若要使用Smartcard模式,USART應設定為: 
    - 8 bit以上檢測位元: 在USART_CR1中,M以及PCE應設定為1。
    - 1.5 stop bits: 傳輸/接收時會需要。在USART_CR2中,STOP應設為11。

不過,也可以設定為0.5 stop bit,但建議是1.5,避免在使用smartcard模式時,額外對此設定做轉換。
 - 不過,也可以設定為0.5 stop bit,但建議是1.5,避免在使用smartcard模式時,額外對此設定做轉換。

.. image:: /parity_smartcard.png
![](/parity_smartcard.png)

當連接到Smartcard時,USART的TX被使用為雙向溝通,並與Smartcard共用。TX腳位一定要設定為open-drain。
 - 當連接到Smartcard時,USART的TX被使用為雙向溝通,並與Smartcard共用。TX腳位一定要設定為open-drain。

 - Smartcard是單線半雙工的通訊協定: 
    - Smartcard是單線半雙工的通訊協定: 

    - 從transmit shift暫存器傳輸資料時,會被延遲至少1/2 baud clock。在一般模式(USART),一個裝滿資料的transmit shift暫存器,會在遇到下一個baud clock邊緣時開始動作(shift)。但是在Smartcard模式,遇到baud clock邊緣時,還會再延遲一些時間(1/2 baud clock)才開始傳送。
        - 從transmit shift暫存器傳輸資料時,會被延遲至少1/2 baud clock。在一般模式(USART),一個裝滿資料的transmit shift暫存器,會在遇到下一個baud clock邊緣時開始動作(shift)。但是在Smartcard模式,遇到baud clock邊緣時,還會再延遲一些時間(1/2 baud clock)才開始傳送。

    - 使用0.5或1.5 stop bits時,若在接收資料frame時遇到檢測錯誤(parity error),接收端RX完成接收時,TX那條線會拉低電位長達一個baud clock,然後才開始下一次的資料傳送。這個動作是為了告知Smartcard資料在傳送給USART的過程中,資料沒有正確地被接收。這種訊號稱作NACK,並且產生此訊號時會讓TX端產生framing error(使用1.5 stop bits時)。此種應用可以依據通訊協定的規則進行資料重送。另外,當NACK control bit被設定為1時,RX端偵測出檢測錯誤時會送出NACK訊號,否則就不傳送。
        - 使用0.5或1.5 stop bits時,若在接收資料frame時遇到檢測錯誤(parity error),接收端RX完成接收時,TX那條線會拉低電位長達一個baud clock,然後才開始下一次的資料傳送。這個動作是為了告知Smartcard資料在傳送給USART的過程中,資料沒有正確地被接收。這種訊號稱作NACK,並且產生此訊號時會讓TX端產生framing error(使用1.5 stop bits時)。此種應用可以依據通訊協定的規則進行資料重送。另外,當NACK control bit被設定為1時,RX端偵測出檢測錯誤時會送出NACK訊號,否則就不傳送。

    - TC旗標的設立,可藉由設定Guard Time暫存器來延遲設立的時間。在一般模式(USART)下,若transmit shift暫存器是空的,而且沒有額外的傳送要求時,TC旗標會立即被設立。但在Smartcard模式,在transmit shift暫存器是空的時候,此暫存器會先觸發Guard time counter,並且在Guard time暫存器中計數到一定數值後(由使用者設定),TC旗標才會被設立。在計數的過程中,TC旗標維持低電位,而TC旗標的取消動作與一般模式相同。
        - TC旗標的設立,可藉由設定Guard Time暫存器來延遲設立的時間。在一般模式(USART)下,若transmit shift暫存器是空的,而且沒有額外的傳送要求時,TC旗標會立即被設立。但在Smartcard模式,在transmit shift暫存器是空的時候,此暫存器會先觸發Guard time counter,並且在Guard time暫存器中計數到一定數值後(由使用者設定),TC旗標才會被設立。在計數的過程中,TC旗標維持低電位,而TC旗標的取消動作與一般模式相同。

    - 若在TX端偵測到framing error(因RX傳送NACK),此NACK訊號不會被TX端的接收區偵測為start bit。依據ISO協定,此NACK訊號長度可為1 or 2個baud clock。
    - 如果在RX端偵測到檢測錯誤(parity error)並且NACK訊號已經送出,則NACK的接收者(TX)不會把此訊號當成start bit。
        - 若在TX端偵測到framing error(因RX傳送NACK),此NACK訊號不會被TX端的接收區偵測為start bit。依據ISO協定,此NACK訊號長度可為1 or 2個baud clock。

    - break符號在Smartcard模式中其實不重要。一個0x00相連一個framing error,會被當作一個資料而不是一個break。在觸發TE bit時,不會傳輸Idle frame。雖然Idle frame在其他種設定中有被定義、使用,但在ISO協定中沒有被定義。
        - 如果在RX端偵測到檢測錯誤(parity error)並且NACK訊號已經送出,則NACK的接收者(TX)不會把此訊號當成start bit。

        - break符號在Smartcard模式中其實不重要。一個0x00相連一個framing error,會被當作一個資料而不是一個break。在觸發TE bit時,不會傳輸Idle frame。雖然Idle frame在其他種設定中有被定義、使用,但在ISO協定中沒有被定義。


紅外線編碼模式
=============

Ref: [RM0090 Reference Manual P.979](http://www.st.com/web/en/resource/technical/document/reference_manual/DM00031020.pdf)

若要使用此模式,則必須設定USART_CR3的IREN為1,而下列設定必須要設定為0: 
   - USART_CR2的LINEN、STOP、CLKEN
   - USART_CR3的SCEN、HDSEL
   
 - USART_CR2的LINEN、STOP、CLKEN
 - USART_CR3的SCEN、HDSEL

IrDA SIR實體層使用Return to Zero, Inverted調變法(RZI modulation),將邏輯0表示成紅外線脈衝訊號。

SIR(slow Infrared)編碼器(傳輸端)會從USART將資料調變成non return to zero(NRZ)資料流,並將此資料流送至紅外線LED以及LED驅動器。雖然IrDA可以支援多種傳輸速率,但是USART-IrDA最快速率只有支援至115.2Kbps(因STM32f429使用SIR ENDEC,而SIR支援速率為9.6-115.2Kbps,亦可稱為9600-115200 baud rate)。在一般USART模式下,傳輸的脈衝訊號寬度為3/16 bit period。

SIR解碼器(接收端)會從紅外線接收器收取return to zero訊號,並將之解調變成non return to zero(NRZ)資料流,接著送到USART做處理。解碼器在Idle state時通常為高電位,而編碼器與解碼器的極性通常是相反的。在解碼器收到低電位訊號時,代表已經收到了start bit了。

.. image:: /irda.PNG
![](/irda.PNG)

   - IrDA是個半雙工通訊協定。若傳送器TX正在忙碌(USART傳送資料給IrDA編碼器),在IrDA接收端上的所有資料會被解碼器忽略。反之,若接收器正在忙碌(IrDA解碼器傳送已解碼的資料給USART),在USART_TX上要傳給IrDA編碼器的資料,不會被IrDA編碼器處理。所以接收資料時,盡量避免有任何傳輸的動作,因資料可能會毀損。
   - 邏輯0會被傳輸成高電位訊號,而邏輯1會被當成0來傳輸(見下圖)。在一般模式下,脈衝訊號寬度由3/16 bit period決定。

.. image:: /normal_mode.PNG
![](/normal_mode.PNG)

   - SIR解碼器會將IrDA相容訊號轉換成USART資料流。編碼器則是相反行為。
   - SIR接收器會將高電位轉換成邏輯1,低電位轉換成邏輯0。傳送器則是相反的。
   - 解碼器的輸出值,會與接收器的輸入值擁有相反極性(理由同上)。SIR輸出端處於Idle state時,輸出低電位。
   - IrDA規定可接收的脈衝週期必須要大於1.41us,不過這週期可以由使用者設定。在接收端會有一個判斷邏輯glitch detection,若該次脈衝週期小於2個PSC,則把該次脈衝過濾掉。(PSC: prescaler value,分頻器的值,定義於IrDA低功率baud暫存器,USART_GTPR)。不過,若脈衝週期小於1個PSC,一定過濾掉。至於脈衝週期介於1-2個PSC之間的,可以選擇是否要過濾。大於2個PSC的脈衝週期就會接收。若PSC設定為0(手冊有說不可以設定這個值),則編碼器和解碼器都不會啟用。
   - 接收器可與低功率傳送器溝通。
   - 在IrDA模式下,USART_CR2的STOP一定要設定為1。


IrDA 低功率模式
----------------

傳送器:
   - 使用低功率模式時,脈衝的發送並非在3/16 bit period,而是低功率baud rate*3,至少為1.42MHz。通常此值為1.8432MHz(1.42MHz < PSC < 2.12MHz)。為了要達到此值,低功率模式下的除法器會把系統時脈強制降到這個值or區間。
 - 傳送器:
    - 使用低功率模式時,脈衝的發送並非在3/16 bit period,而是低功率baud rate*3,至少為1.42MHz。通常此值為1.8432MHz(1.42MHz < PSC < 2.12MHz)。為了要達到此值,低功率模式下的除法器會把系統時脈強制降到這個值or區間。

接收器:
   - 低功率模式的接收與一般模式相去不遠。此模式的glitch detection會把小於1個PSC的脈衝過濾掉。有效脈衝的判別,是當脈衝週期大於2個PSC時才會被接收(2 * IrDA低功率baud clock,USART_GTPR的PSC)
 - 接收器:
    - 低功率模式的接收與一般模式相去不遠。此模式的glitch detection會把小於1個PSC的脈衝過濾掉。有效脈衝的判別,是當脈衝週期大於2個PSC時才會被接收(2 * IrDA低功率baud clock,USART_GTPR的PSC)

接收器的開機時間應該由軟體決定。另外,在接收與傳輸的動作之間,應該要加入至少10ms的延遲,因為IrDA是半雙工協定。
 - 接收器的開機時間應該由軟體決定。另外,在接收與傳輸的動作之間,應該要加入至少10ms的延遲,因為IrDA是半雙工協定。


直接記憶體存取(DMA)模式
===================================

Ref: [Using The DMA controller on STM32](http://www.mind-dump.net/using-the-dma-controller-on-stm32f4)

USART可以使用DMA達到連續通訊的效果,不過DMA會個別對於RX和TX緩衝器送出請求。

Transmission using DMA
------------------------

.. image:: /tx_uart_dma.png
![](/tx_uart_dma.png)

若要啟用DMA模式,要在USART_CR3把DMAT啟用。在TXE bit被設立時,資料會先從SRAM(要先由DMA周邊設定,請參考DMA說明手冊)載入到USART_DR暫存器。在系統保留的SRAM,TX/RX的資料緩衝使用集中型DMA。

如果要把DMA通道對應給USART傳送器,請使用下列流程:

   1. 把USART_DR暫存器的位址寫到DMA控制暫存器中,以設定待傳資料的終端地點。在每次TXE被觸發的時候,資料都會從記憶體中搬到這個位址。
   2. 把記憶體位址寫到DMA控制暫存器裡面,以設定待傳資料的來源。在每次TXE被觸發的時候,資料都會從這個記憶體區段搬到USART_DR。
   3. 在DMA控制暫存器中,設定要傳的資料總量(bytes)。
   4. 在DMA暫存器設定通道的優先順序。
   5. 按照程式需求,設定在傳輸一半/全部資料後,是否產生DMA interrupt。
   6. 清除SR暫存器中的TC(寫入0)。
   7. 啟動DMA暫存器中的通道。

如果傳輸的資料總量,已經達到DMA控制暫存器內設定的上限時,DMA控制器會在DMA通道interrupt vector上產生interrupt。

在傳輸模式下,只要DMA把所有該傳的資料都傳完時(此時在DMA_ISR的TCIF旗標會設立),TC旗標可以用於監控USART是否已經完成通訊。這步驟是為了避免在最後一次資料尚未傳完時,把USART關掉或是進入Stop模式。程式一定要等到TC=1才可以進行後續的動作。在傳輸資料時,TC旗標會一直維持清除狀態(=0),只有在最後一次資料frame傳輸結束時,TC旗標才會被硬體設立。


Reception using DMA
----------------------

.. image:: /rx_usart_dma.png
![](/rx_usart_dma.png)

DMA模式也可以用於接收資料,須設定USART_CR3的DMAR。只要收到任何一個byte時,該次資料會從USART_DR載入至SRAM(要先由DMA周邊設定,請參考DMA說明手冊)。如果要把DMA通道對應給USART接收器,請使用下列流程:

   1. 把USART_DR暫存器的位址寫到DMA控制暫存器中,以設定待傳資料的來源。在每次RXNE被觸發的時候,資料都會從這個位址搬到記憶體中。
   2. 把記憶體位址寫到DMA控制暫存器裡面,以設定待傳資料的終端地點。在每次RXNE被觸發的時候,資料都會從USART_DR搬到這個記憶體區段。
   3. 在DMA控制暫存器中,設定要傳的資料總量(bytes)。
   4. 在DMA暫存器設定通道的優先順序。
   5. 按照程式需求,設定在傳輸一半/全部資料後,是否產生DMA interrupt。
   6. 啟動DMA暫存器中的通道。

如果接收的資料總量,已經達到DMA控制暫存器內設定的上限時,DMA控制器會在DMA通道interrupt vector上產生interrupt。在interrupt subroutine時,USART_CR3的DMAR應該要由軟體去清除。

另外,如果要把DMA用於接收,就不可以啟用RXNEIE。


多重緩衝區中的Error flagging and interrupt 
---------------------------------------------

若在多重緩衝區的情況下,在傳輸/接收過程中發生了任何錯誤,在該次byte傳完後會立即設立error旗標。另外,如果有任何interrupt enable旗標被設立,error設立完之後還會再產生interrupt。以framing error、overrun error和噪音旗標(另外與RXNE搭配使用,因為可能有單一byte接收的情況)來說,每個都有各自獨立的interrupt enable旗標(USART_CR3的EIE)。如果發生任何一種錯誤,在傳完該次byte之後會立即產生interrupt。在interrupt章節會提到這些interrupt enable之間的關係。

HARDWARE FLOW CONTROL(modem modes)
===================================

USART亦可模擬RS-232通訊。RS-232原本的設計用意,是讓電腦能對數據機、印表機、資料儲存裝置等電腦周邊設備做資料交換。但是RS-232的缺點較多(接孔過大、設備能源消耗太快、資料傳輸速率低),目前的電腦漸漸都淘汰掉這種接孔,並用USB-RS232轉換器做為替代。現今RS232介面則廣泛使用於工業設備、科學儀器及網路設備。

USART使用modem modes時,會變成雙線半雙工通訊(UART)。通訊流控制則由RTS-CTS負責,也因此同時間點只能有一方傳送資料。

利用nCTS跟nRTS控制TX、RX是否再傳送或接收data。
可個別設定USART_CR3的RTSE以及CTSE為1,藉此允許RTS或CTS flow control。

.. image:: /hardware_control_2usarts.png
![](/hardware_control_2usarts.png)

RTS Flow Control
-------------------------

 - 如果開啟RTS flow control(要把RTSE設為1),nRTS會被拉至低電位,直到USART接收器準備好要接收下一筆資料才會拉高。如果接收器的暫存器滿了,會先把nRTS拉至高電位,告知另外一端的傳送器在傳完這個資料frame之後,應該要停止傳送資料。

.. image:: /rst_flow_control.png
![](/rst_flow_control.png)

CTS Flow Control
-----------------------

如果開啟CTS flow control(要把CTSE設為1),在傳送器要傳送下一筆資料frame之前,會先去檢查nCTS是否有值輸入。如果nCTS被拉至低電位,那麼下一筆資料會立即被送出(假設資料已經先在Transmit Data Register準備好了,也可說成TXE=0),否則不會進行傳送。如果在傳送資料的過程中,nCTS被拉至高電位,那麼會先把剩下該傳的資料先傳完,再停止傳送。

如果CTSE被設定為1,那麼在nCTS有值輸入時,CTSIF狀態會自動地被硬體設立,表示該時間點接收器是否已準備好下一次的通訊。若有開啟USART_CR3的CTSIE(=1),則會產生interrupt。

另外,在開啟CTS flow的情況下,傳送器在送出break時不會去檢查nCTS的狀態。

.. image:: /cst_flow_control.png
![](/cst_flow_control.png)


RS-232收發器-MAX232
...................
==========================
 - MAX232晶片是美信(MAXIM)公司專為RS-232標準串口設計的介面電路,屬於+3.0V to +5.5V RS-232 收發器,收發器採用專有的低壓差發送器輸出級,利用雙電荷泵在3.0至5.5V單電源供電時能夠實現真正的RS-232功能,MAX232是一個雙RS-232驅動器/接收器且可以從單一的+5V電源產生RS-232電位(voltage level)(充電泵可轉換+5V為 ±10V),假設我們要用RS232來進行PC(serial port) 與微處理器間的溝通,就要用MAX232來處理訊號電位轉換的功能,方便微處理器處理轉換後的訊號。
 - 其包含兩個驅動器和兩個接收器,功耗僅40mW 且傳輸速率可以達120Kbps。

.. image:: /MAX232_pin.png
![](/MAX232_pin.png)

MAX232 內部結構
===============
雙電荷泵轉換器電路 (DUAL CHARGE PUMP CONVERTERS)

    - 由1、2、3、4、5、6腳和4個電容構成。功能是產生+10V和-10V兩個電源,提供給RS-232串口電位。
 - 由1、2、3、4、5、6腳和4個電容構成。功能是產生+10V和-10V兩個電源,提供給RS-232串口電位。

    - 第一階段,電容 C1的電壓提昇兩倍到 +10V並儲存在電容器 C3和V+ output。
 - 第一階段,電容 C1的電壓提昇兩倍到 +10V並儲存在電容器 C3和V+ output。

    - 第二階段,電容 C2將 +10 V的反向變成 -10V並儲存在電容器 C4和V- output。
 - 第二階段,電容 C2將 +10 V的反向變成 -10V並儲存在電容器 C4和V- output。

    - MAX232運作與的電荷泵電容可低至 0.1μF,若使用更大的電容(最多10μF)可以用來降低電源紋波(voltage ripple)。
 - MAX232運作與的電荷泵電容可低至 0.1μF,若使用更大的電容(最多10μF)可以用來降低電源紋波(voltage ripple)。

電源紋波(voltage ripple)

成因是因為一個直流電壓大多時是通過交流電壓整流、濾波而來,濾波若不乾淨則會使交流成分疊加在直流穩定分量上,另外電池的直供電也會因負載的波動而產生波紋。

.. image:: /MAX232_ripple2.jpg
![](/MAX232_ripple2.jpg)

MAX232工作原理
================
 - 由7、8、9、10、11、12、13、14腳構成兩個數據通道。

 - 13腳(R1IN)、12腳(R1OUT)、11腳(T1IN)、14腳(T1OUT)為第一數據通道。

 - 8腳(R2IN)、9腳(R2OUT)、10腳(T2IN)、7腳(T2OUT)為第二數據通道。

 - TTL/CMOS訊號從11引腳(T1IN)、10引腳(T2IN)輸入轉換成RS-232數據從14腳(T1OUT)、7腳(T2OUT)送到電腦DB9插頭;

 - DB9插頭的RS-232數據從13引腳(R1IN)、8引腳(R2IN)輸入轉換成TTL/CMOS訊號後從12引腳(R1OUT)、9引腳(R2OUT)輸出。

 - 內有的兩組RS232驅動器/接收器和電荷泵可以產生RS232電位,內部各有一個400 KΩ的pull up電阻,可以將未使用的驅動器拉至高電位,因有雙極性的特點,所以輸出邏輯電位會是low,若是在shutdown/power-off模式下驅動器/接收器無法上拉電壓,但是會進入高阻抗狀態,如此可以降低漏電流(最大25μA),避免過載(overload)情形發生。

上拉電阻(Pull-up resistors):在驅動電路時,當輸入過低,可以用一個上拉電阻透過接到較高的電位將電壓訊號拉至高電位,對輸入端而言,看起來就是高阻抗,如果成功驅動,則取消上拉電阻的使用。通過這樣,上拉電阻可以使pin腳在未連接外部組件時也能保持正確的邏輯電位。
 - 上拉電阻(Pull-up resistors):在驅動電路時,當輸入過低,可以用一個上拉電阻透過接到較高的電位將電壓訊號拉至高電位,對輸入端而言,看起來就是高阻抗,如果成功驅動,則取消上拉電阻的使用。通過這樣,上拉電阻可以使pin腳在未連接外部組件時也能保持正確的邏輯電位。

舉例來說:當TTL電路驅動CMOS電路時,如果TTL電路輸出的高電平低於CMOS電路的最低高電平(一般為3.5V),這時就需要在TTL的輸出端接上拉電阻,以提高輸出高電位的值。
 - 舉例來說:當TTL電路驅動CMOS電路時,如果TTL電路輸出的高電平低於CMOS電路的最低高電平(一般為3.5V),這時就需要在TTL的輸出端接上拉電阻,以提高輸出高電位的值。

下拉電阻(Pull-down resistors):原理相同於上拉電阻,但其是與GND連接,故可以使邏輯訊號保持在接近0V的狀態。
 - 下拉電阻(Pull-down resistors):原理相同於上拉電阻,但其是與GND連接,故可以使邏輯訊號保持在接近0V的狀態。

.. image:: /MAX232_waveform2.png
![](/MAX232_waveform2.png)

供電
 - 15腳GND、16腳VCC(+5V)。
 - 供電
    - 15腳GND、16腳VCC(+5V)。

等校電路說明
 - 等效電路說明

.. image:: /embedded/MAX232_circuit.jpg
![](/embedded/MAX232_circuit.jpg)

TXD為TTL輸入端,RXD為TTL輸出端,由於二極體與電容的作用使二極體D1與電容C7交接處的電壓保持在-3V~-15V。
 - TXD為TTL輸入端,RXD為TTL輸出端,由於二極體與電容的作用使二極體D1與電容C7交接處的電壓保持在-3V~-15V。

TTL轉RS232:
 - TTL轉RS232:

 - 當TXD為"邏輯1"時(TTL),Q3(PNP電晶體)為截止狀態,PCRXD上電壓與PCTXD電壓相等,也是-3~-15V,為"邏輯1"(RS232)
    - 當TXD為"邏輯1"時(TTL),Q3(PNP電晶體)為截止狀態,PCRXD上電壓與PCTXD電壓相等,也是-3~-15V,為"邏輯1"(RS232)

 - 當TXD為"邏輯0"時(TTL),Q3(PNP電晶體)為導通狀態,PCRXD上電壓約為+5V,此電壓位於+3~+15V之間,也就是"邏輯0"(RS232)
    - 當TXD為"邏輯0"時(TTL),Q3(PNP電晶體)為導通狀態,PCRXD上電壓約為+5V,此電壓位於+3~+15V之間,也就是"邏輯0"(RS232)

RS232轉TTL:
 - RS232轉TTL:

 - 當PCTXD為"邏輯1"時(RS232),Q4(NPN電晶體)為截止狀態,RXD電壓約為+5V,為"邏輯1"(TTL)
    - 當PCTXD為"邏輯1"時(RS232),Q4(NPN電晶體)為截止狀態,RXD電壓約為+5V,為"邏輯1"(TTL)

 - 當PCTXD為"邏輯0"時(TS232),Q4(NPN電晶體)為導通狀態,RXD電壓為0V,為"邏輯0"(TTL)
    - 當PCTXD為"邏輯0"時(TS232),Q4(NPN電晶體)為導通狀態,RXD電壓為0V,為"邏輯0"(TTL)

其中D2二極體的功能是為了防止Q4的逆向偏壓過高而導致的崩潰現象發生。 
 - 其中D2二極體的功能是為了防止Q4的逆向偏壓過高而導致的崩潰現象發生。 

USB to UART 橋接器-CP2102 
.........................
==========================

CP2102是一個十分完整的USB轉UART橋接器,運用了最小化元件和最少的PCB空間,其中包含了USB2.0的全速電路、USB收發器、振盪器、EEPROM(電子抹除式可複寫唯讀記憶體)、非同步串列資料匯流排。

.. image:: /CP2102.png
![](/CP2102.png)

 - EEPROM是用來儲存USB供應商ID、產品ID、產品說明、電源參數、裝置版本號、裝置序號,寫入次數壽命為10萬次。

 - UART接口包括TXD、RXD、RTS、CTS、DSR、DTR、DCD和RI控制信號。

 - UART支持RTS/CTS、DSR/DTR和X-On/X-Off作hand-shaking。

.. image:: /CP2102_table.png
![](/CP2102_table.png)

handshaking:早期不同的終端設備或電腦以RS232作資訊通訊時,為了確認已建立通訊連結作先作hand shaking,確認後才會開始作資料傳輸。

 - X-ON/X-OFF:是一種用於流量控制的非同步通信協議,舉例來說,電腦傳送資料到印表機的速率明顯大於印表機的列印速度,所以印表機內會有一個buffer用來儲存來不及印的資料,若是在列印結束之前,buffer滿了的話,列表機將會發送一個XOFF的控制字元符號來告訴電腦暫停傳輸,等到buffer空的時候再發出一個XON控制字符到電腦繼續傳輸資料,所以方向皆是接收端傳到傳送端

供電結構
=======
CP2102內部有一個5 to 3V的電壓調節器,如此才能配置成匯流排供電或是自行供電,以下介紹兩種供電配置。

匯流排供電

 - 裝置可以是由「匯流排供電」(Bus-powered),也就是從USB連接的介面取電。

.. image:: /CP2102_buspowered.png
![](/CP2102_buspowered.png)

 - 匯流排供電情況:會將VBUS與REGIN接通,Vin由VBUS輸入。

自行供電

 - 裝置由USB電源線提供電源,也就是「自行供電」(Self-powered)、或是由電池或外接電源供電。

.. image:: /CP2102_selfpowered.png
![](/CP2102_selfpowered.png)

 - 自行供電情況(功能由軟體的Boolean flag啟動,True代表使用self-powered):Vin由5V Power net輸入,REGIN和VBUS並不接通。

.. image:: /CP2102_selfpowered_bypassed.png
![](/CP2102_selfpowered_bypassed.png)

 - 另外一種self-powered(選擇功能)是若將3V的POWER NET電壓給VDD且將VDD和REGIN接在一起,則可以關掉電壓調節器,不通過其而產生輸出。


最理想的USB 供電方式之一是由匯流排供電,如此一來就不需要再外接電源,但其缺點是在暫停狀態(suspend)下電流最多耗費500μA,若支援遠端喚醒功能則會耗費2.5mA的大電流,所以可攜式裝置大多採用Self-powered。

USB功能控制器/發送器
==================
USB功能控制器負責管理所有UART及USB間的資料傳輸,和處理來自主機端控制器(host)和UART的控制命令,暫停(Suspend)和恢復(Resume)狀態是用外部電路的方式實現,若是在匯流排上檢測到Suspend訊號,CP2102會進入暫停狀態並送出SUSPEND和SUSPEND*訊號,若是Reset CP2102也會進入暫停狀態,直到USB設定完成。

另外離開暫停狀態的方法有三種:離開完成後SUSPEND和SUSPEND'訊號會被清除

 - 檢測到恢復訊號
 - 收到USB Reset訊號
 - 裝置Reset

注意當Reset時,SUSPEND和SUSPEND'會有暫時的突波電壓,可放置一個10kΩ的下拉電阻在11腳位以保持重啟時低電位。

.. image:: /CP2102_elec.png
![](/CP2102_elec.png)

工作流程

.. image:: /embedded/CP2102_MAX232.jpg
![](/embedded/CP2102_MAX232.jpg)

 - 大多時候CP2102會搭配MAX232作使用,在RS232與CP2102之間還會接一個Max232來達到穩壓的效果及轉換訊號的功能,資料從RS232的pin2傳出去,MAX232的R2IN收到,接著從R2OUT輸出一個TTL/CMOS訊號到CP2102裡面,因為CP2102裡面有兩條數據傳輸通道以及緩衝區,振盪器和USB function controller會去控制資料的緩衝和傳遞​,由USB傳送端從usb port傳出去。

STM32 USART Register 總表
................................
==========================

Status register(USART_SR)

.. image:: /embedded/USART_SR.jpg
![](/embedded/USART_SR.jpg)

Data register(USART_DR)

Baud rate register(USART_BRR)

Control Register 1(USART_CR1)

.. image:: /embedded/USART_CR1.jpg
![](/embedded/USART_CR1.jpg)

Control Register 2(USART_CR2)

.. image:: /embedded/USART_CR2.jpg
![](/embedded/USART_CR2.jpg)

Control Register 3(USART_CR3)

.. image:: /embedded/USART_CR3.jpg
![](/embedded/USART_CR3.jpg)

Guard time and prescaler register(USART_GTPR)

.. image:: /USART_register.png
![](/USART_register.png)


STM32F429-USART程式碼 & 示波器圖解
..................................
==========================


Download sample code : 


 - 測試用code: http://wiki.csie.ncku.edu.tw/embedded/stm32F429-usart.zip
 - 從PC端接收stm32f429-USART的資料,並紀錄到檔案。 http://codepad.org/0yvz8jk4
 - 環境設定: https://stm32f429.hackpad.com/NOTE-WbiooOfkaoR
 - 測試用code: [http://wiki.csie.ncku.edu.tw/embedded/stm32F429-usart.zip](http://wiki.csie.ncku.edu.tw/embedded/stm32F429-usart.zip)
 - 從PC端接收stm32f429-USART的資料,並紀錄到檔案。 [http://codepad.org/0yvz8jk4](http://codepad.org/0yvz8jk4)
 - 環境設定: [https://stm32f429.hackpad.com/NOTE-WbiooOfkaoR](https://stm32f429.hackpad.com/NOTE-WbiooOfkaoR)
 - 本程式碼在ubuntu-12.04測試,並對stm32f429燒錄成功。


.. code-block:: c

    void RCC_Configuration(void)
    {
          /* --------------------------- System Clocks Configuration -----------------*/
          /* USART1 clock enable */
          RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
          /* GPIOA clock enable */
          RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
    }
```c
void RCC_Configuration(void)
{
    /* --------------------------- System Clocks Configuration -----------------*/
    /* USART1 clock enable */
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
    /* GPIOA clock enable */
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
}

    void GPIO_Configuration(void)
    {
        GPIO_InitTypeDef GPIO_InitStructure;
void GPIO_Configuration(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;

        /*-------------------------- GPIO Configuration ----------------------------*/
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
        GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
        GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(GPIOA, &GPIO_InitStructure);
    /*-------------------------- GPIO Configuration ----------------------------*/
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

        /* Connect USART pins to AF */
        GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_USART1);   // USART1_TX
        GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_USART1);  // USART1_RX
    }
    /* Connect USART pins to AF */
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_USART1);   // USART1_TX
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_USART1);  // USART1_RX
}

    void USART1_Configuration(void)
    {
        USART_InitTypeDef USART_InitStructure;
void USART1_Configuration(void)
{
    USART_InitTypeDef USART_InitStructure;

        /* USARTx configuration ------------------------------------------------------*/
        /* USARTx configured as follow:
         *  - BaudRate = 9600 baud
         *  - Word Length = 8 Bits
         *  - One Stop Bit
         *  - No parity
         *  - Hardware flow control disabled (RTS and CTS signals)
         *  - Receive and transmit enabled
         */
        USART_InitStructure.USART_BaudRate = 9600;
        USART_InitStructure.USART_WordLength = USART_WordLength_8b;
        USART_InitStructure.USART_StopBits = USART_StopBits_1;
        USART_InitStructure.USART_Parity = USART_Parity_No;
        USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
        USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
        USART_Init(USART1, &USART_InitStructure);
    /* USARTx configuration ------------------------------------------------------*/
    /* USARTx configured as follow:
     *  - BaudRate = 9600 baud
     *  - Word Length = 8 Bits
     *  - One Stop Bit
     *  - No parity
     *  - Hardware flow control disabled (RTS and CTS signals)
     *  - Receive and transmit enabled
     */
    USART_InitStructure.USART_BaudRate = 9600;
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;
    USART_InitStructure.USART_StopBits = USART_StopBits_1;
    USART_InitStructure.USART_Parity = USART_Parity_No;
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
    USART_Init(USART1, &USART_InitStructure);


        USART_Cmd(USART1, ENABLE);
    }
    USART_Cmd(USART1, ENABLE);
}

    void USART1_puts(char* s)
    {
        while(*s) {
            while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
            USART_SendData(USART1, *s);
            s++;
        }
void USART1_puts(char* s)
{
    while(*s) {
        while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
        USART_SendData(USART1, *s);
        s++;
    }

.. code-block:: c
}
```

    int main(void)
    {
        RCC_Configuration();
        GPIO_Configuration();
        USART1_Configuration();
```c
int main(void)
{   
    RCC_Configuration();
    GPIO_Configuration();
    USART1_Configuration();

        USART1_puts("USART");
        char t = 'a';
        char rs[50] = {'\0'};
        char* prs = rs;
    USART1_puts("USART");
    char t = 'a';
    char rs[50] = {'\0'};
    char* prs = rs; 

        while(t != 'b')
    	{
    		while(USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == RESET);
    		t = USART_ReceiveData(USART1);
    		*prs++ = t;
    	}
    	USART1_puts("\r\nThis is the string typed by user:\r\n");
    	USART1_puts(rs);
    while(t != 'b')
    {   
        while(USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == RESET);
        t = USART_ReceiveData(USART1);
        *prs++ = t;
    }   
    USART1_puts("\r\nThis is the string typed by user:\r\n");
    USART1_puts(rs);

        while(1)
        {
            while(USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == RESET);
            t = USART_ReceiveData(USART1);
            if ((t == '\r')) {
                while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
                USART_SendData(USART1, t);
                t = '\n';
         	}
    while(1)
    {   
        while(USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == RESET);
        t = USART_ReceiveData(USART1);
        if ((t == '\r')) {
            while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
            USART_SendData(USART1, t);
        }

        while(1);	// Don't want to exit
            USART_SendData(USART1, t); 
            t = '\n';
        }   
        while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
        USART_SendData(USART1, t); 
    }   

.. image:: /embedded/USART_pin.jpg
    while(1);   // Don't want to exit
}   
```

![](/embedded/USART_pin.jpg)

.. code-block:: c

    如果是使用圖中轉接板,要將紅色板子的TX接到stm32f429的PA9(RX)、RX接到PA10(TX)。
    若是使用USB-TTL轉接線,要將綠色線(TX)接到PA9、白色線(RX)接到PA10
    接地線要記得插上板子

```
如果是使用圖中轉接板,要將紅色板子的TX接到stm32f429的PA10(RX)、RX接到PA9(TX)。
若是使用USB-TTL轉接線,要將綠色線(TX)接到PA9、白色線(RX)接到PA10
接地線要記得插上板子
```


.. image:: /embedded/USART_Osc_PC.jpg
![](/embedded/USART_Osc_PC.jpg)


.. code-block:: c

    使用putty連線,設定如圖中所示。
    開始連線後,板子會傳送USART字串。一直按板子的reset,會如圖中下方所示。

```
使用putty連線,設定如圖中所示。
開始連線後,板子會傳送USART字串。一直按板子的reset,會如圖中下方所示。
```

.. image:: /embedded/USART_Osc_brief.jpg
![](/embedded/USART_Osc_brief.jpg)


.. code-block:: c

    使用示波器量測stm32f429的RX收到的訊號,從PC對其送出字元b。。
    先按autoset,再調整紅色圈圈的兩個設定。建議將時間區間(x軸)調成4ms、電壓區間(y軸)調成1V,不然會抓到不完整的訊號。
    注意綠色圈圈,要把量測棒的夾到板子上(接地),否則會出現雜訊。
    **時間區間沒調好,波形會變成下圖這樣**

```
使用示波器量測stm32f429的RX收到的訊號,從PC對其送出字元b。。
先按autoset,再調整紅色圈圈的兩個設定。建議將時間區間(x軸)調成4ms、電壓區間(y軸)調成1V,不然會抓到不完整的訊號。
注意綠色圈圈,要把量測棒的夾到板子上(接地),否則會出現雜訊。
**時間區間沒調好,波形會變成下圖這樣**
```

.. image:: /embedded/USART_Oscilloscope.jpg
![](/embedded/USART_Oscilloscope.jpg)


.. image:: /embedded/USART_Oscilloscope_char_b.jpg
![](/embedded/USART_Oscilloscope_char_b.jpg)


.. code-block:: c

    在沒接地時,量測STM32F429從PC接收字元b。    

    整體波形變得不平整,但還是看得到USART輸出的波形。

```
在沒接地時,量測STM32F429從PC接收字元b。    
整體波形變得不平整,但還是看得到USART輸出的波形。
```

.. image:: /embedded/USART_Osc_IDLE_USART.jpg
![](/embedded/USART_Osc_IDLE_USART.jpg)


.. code-block:: c

    使用測試程式燒錄到板子上,並透過示波器量測stm32f429的TX送出的訊號。
    綠色圈圈代表板子正在開機,USART並未開啟。
    IDLE在圖中已標示成紅色字體。
    紫色點代表start bit,橘色點代表stop bit,並依序在圖上標示USART字樣。
    注意字元的傳送都是從LSB開始。U的二進位表示為:01010101,但是在傳送時會送出此序列:10101010

```
使用測試程式燒錄到板子上,並透過示波器量測stm32f429的TX送出的訊號。
綠色圈圈代表板子正在開機,USART並未開啟。
IDLE在圖中已標示成紅色字體。
紫色點代表start bit,橘色點代表stop bit,並依序在圖上標示USART字樣。
注意字元的傳送都是從LSB開始。U的二進位表示為:01010101,但是在傳送時會送出此序列:10101010
```



   
REFERENCE
..................
==========================
- [[1]Universal asynchronous receiver/transmitter wikipedia.](http://en.wikipedia.org/wiki/Universal_asynchronous_receiver/transmitter#Special_receiver_conditions)

- [[2]STM32F407xx Reference Manual P.946 ~ P.997](http://www.st.com/web/en/resource/technical/document/reference_manual/DM00031020.pdf)


- [[3]IrDA and RS-232](http://china.maximintegrated.com/app-notes/index.mvp/id/3024)

- [[4]Using The DMA controller on STM32](http://www.mind-dump.net/using-the-dma-controller-on-stm32f4)

- [[5]ISO 7816-3](http://www.cardwerk.com/smartcards/smartcard_standard_ISO7816-3.aspx)

Q&A
...................
==========================

***1.baud rate為何不是2的倍數?幾個baud rate數字的關聯?為何設定會有小數點?***

baud rate 是單位時間內傳輸資訊的個數,單位是bits/sec

最早的發明是用來測量電報傳輸速率,現在用來作為網路兩節點的傳輸速率

常用的有300、1200、2400、9600、115200、19200等bits/sec

這些規格是來自歷史因素,最早的baud rate用在電傳,是75baud

後來每次擴充都是兩倍,75->150->300->600->1200....

而我們為了要得到這個值,必須從系統的clock做分頻,因此要設定USARTDIV

這也是USARTDIV會是小數的原因

***2.為什麼USART可以選擇8 bit/9 bit***

由於歷史因素,所以usart可以選擇8,9bit的傳送

最一開始的ASCII code是使用7 bit來做編碼,而第8個位元常會被拿來做各種應用

像是加上parity bit來驗證資料的正確性

但是當以8為單位的電腦系統興起後,開始用8bit來做傳輸

所以一開始7 bit ASCII code也被擴展為8 bit

***3.為何stop bit有0.5 bit、1.5 bit的設計?***

stop bit其實不算是bit,他是傳輸結束後的一段時間(period),區隔每個傳輸的資料

它的功用是在非同步傳輸的時候可以告訴receiver資料傳輸已經結束

stop bit有0.5, 1, 1.5, 2bits,共四種

一些比較老的teletype machine可能需要不只一個stop bit

如果stop bit越長,可以增加多一點點的處理時間

另一個原因是長一點的stop bit可以提供長一點的同步時間

若是在環境比較不好的情況下(例如,長距離傳輸),較長的同步時間會可以有效減少錯誤的發生

不過缺點是會導致throughput的降低

***4.為何取樣是看8,9,10這幾個bit?***

因為8,9,10是在整個start bit的正中間

由於接收端和傳送端的取樣頻率可能會有些微誤差

如果我們在中間取樣,可以容許一定程度的取樣頻率誤差

![Image](/unmatched)clocks.png
![](/unmatched clocks.png)

[圖片來源](http://electronics.stackexchange.com/questions/42236/uart-receiver-clock-speed)