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

版本 28dcbb9e40cdd0e224ee6c8f5642099a39fef1cc

embedded/USART

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

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

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

USART主要特性 ……………….

  • 全雙工、非同步通訊

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

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

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

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

.. image:: /NRZcode.png

圖片來源:wikipedia<http://zh.wikipedia.org/wiki/%E4%B8%8D%E6%AD%B8%E9%9B%B6>_

  • 可調整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傳輸/偵測達到此目的。

    在USART被硬體設定為LIN模式時,提供13bit break產生器以及10/11bit break偵測器。

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

  • IrDA SIR 編解碼器

    標準模式可支援3/16 bits區間。

  • 可做為Smartcard模擬器

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

    可為Smardcard傳輸模式設定0.5/1.5 stop bits。

  • 支援單線半雙工通訊

  • 可用DMA(Direct Memory Access)設定多重緩衝區並進行資料交換。

    在系統保留的SRAM,TX/RX的資料緩衝使用集中型DMA。

  • TX/RX都有各自獨立的Enable Bit(TE、RE)

  • 傳輸檢測標誌

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

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

– 傳輸結束(TC, Transmission complete)

  • 檢測控制

– 發送檢測位(Transmits parity bit)

– 對接收的資料進行檢測(Checks parity of received data byte)

  • 4個錯誤檢測標誌

– 溢出錯誤(Overrun error)

– 噪音檢測(Noise detection)

– Frame錯誤(Frame error)

– 奇偶檢測錯誤(Parity error)

  • 支援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)

在一般情況下,本身不產生中斷,在DMA情況下,則由EIE產生中斷,經檢驗USART_CR1的FE位可得知溢出錯誤

– Frame錯誤(Framing error)

在一般情況下,本身不產生中斷,而由RXNE產生中斷,經檢驗USART_CR1的FE位可得知Frame錯誤

在DMA情況下下,則由EIE產生中斷,經檢驗USART_CR1的FE位得知錯誤

– 噪音錯誤(Noise error)

在一般情況下,本身不產生中斷,而由RXNE產生中斷,經檢驗USART_CR1的NF位得知錯誤

在DMA情況下下,則由EIE產生中斷,經檢驗USART_CR1的NF位得知錯誤

– 檢驗錯誤(Parity error, PEIE)

  • 多處理器通訊,如果資料中的地址沒有配對成功,則進入mute mode。

  • 2種喚醒接收器的方式

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

  • Address bit MSB為’1’的資料被認為是地址,否則為一般資料。

    在這資料中,接收端會將最後4bits與USART_CR2暫存器中的ADD位比較,若相同則清除RWU位,後面的資料將能正常接收。

USART功能介紹 ……………………………

USART Block Diagram

.. image:: /usart_block_diagram.png 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傳輸資料時,串列資料由下列frames組成:
- 傳輸或接收資料之前,由Idle Line表示。 - 一個start bit - 一個資料word,可為8/9 bits,用least significant bit做資料排序。 - 一組0.5, 1, 1.5, 2 stop bits,用以表示該次frame傳輸完畢。

  • ???????根據USART_CR1暫存器中的M位選擇8或9位元決定資料長度(見圖)

另外包含以下數種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: 阻擋發送資料。若在高電位,則當目前資料傳送結束後,中斷下一次的資料傳送

  • nRTS: 請求發送資料。若在低電位,則表示USART已經準備好接收資料

USART 特性描述

資料長度根據USART_CR1暫存器中的M位選擇8或9位元

.. image:: /usart_M_byte.jpg

  • 在起始位(start bit)期間,TX處於低電位,如圖中的(a),在停止位期間,TX處於高電位,如圖中的(b)。

.. image:: /usart_M_idle.jpg

  • 另外空閒符號則全由’1’組成,包含資料的停止位元位數也是’1’,如圖中的(c),後面接著下一個資料的開始位;

.. image:: /usart_M_break.jpg

  • 中斷符號則全由’0’所組成,包含資料的停止位也是’0’,如圖中的(d),

在中斷時,發送器會再插入1或2個停止位(‘1’)以區分下一筆資料的起始位,如圖中的(e)

Ref: RM0090 Reference Manual P.950<http://www.st.com/web/en/resource/technical/document/reference_manual/DM00031020.pdf>_

傳送器

傳送器依據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

.. image:: /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,則要先讀取USART_SR暫存器,再對USART_DR暫存器做寫入動作。如果是使用多重緩衝區模式,可以直接對TC寫入0。

//這邊要放fig.299

傳送斷開符號

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

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

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

傳送空閒符號

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

接收器

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

起始位偵測

.. image:: /usart_fig300.jpg

Ref: RM0090 Reference Manual P.954<http://www.st.com/web/en/resource/technical/document/reference_manual/DM00031020.pdf>_

在USART中,如果辨認出一個特殊的採樣序列( 1 1 1 0 X 0 X 0 X 0 0 0 0 ),則認定偵測到一個起始位。

如果該序列不完整,則接收端退回起始位偵測並回到空閒狀態,等待下一次的電壓下降。

如果三個採樣點上有僅有兩個是0(第3、5、7採樣點或8、9、10採樣點),則依然判定為偵測到一個起始位,但NE(噪音標誌)會被設定

採樣的時間間隔

.. image:: /usart_sampling.png Ref: UART receiver clock speed<http://electronics.stackexchange.com/questions/42236/uart-receiver-clock-speed>_

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

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

資料的接收

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

接收器的設定

.. image:: /usart_recevier.png

  1. 設定USART_CR1暫存器的UE位來啟動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. 藉由讀取USART_DR可清除RXNE位,RXNE位必須要在下一資料接收前被清除,以免產生溢出錯誤 5. 在DMA接收時,RXNE在每個字元接收後被設置,並因DMA讀取RDR而被清除

接收斷開符號

USART在接收斷開符號後,可像處理frame錯誤一樣處理

接收空閒符號

當空閒符號被偵測到時,USART處理步驟如同一般資料一樣處理,但如果USART_CR1的IDLEIE被設置時,將會產生一個中斷

溢出錯誤

若RXNE沒有被覆位,此時又接收到一個新資料,則會發生溢出錯誤,如圖中的(i)

當溢出錯誤產生時: 1. USART_SR中的ORE位將被設置,如圖中的(j) 2. RDR中的內容將不會被清除,因此讀取USART_DR仍可以得到之前的資料 3. 若USART持續在接收中,則Received shift register中的資料將被覆蓋 4. 如果RXNEIE被設置,或是EIE(Error interrupt enable)和DMAR位被設定,則會產生一個中斷,如圖中的(k) 5. 依序讀取USART_SR和USART_DT暫存器,可清除ORE位

當ORE位被設置時,表示至少有一個資料已遺失,有以下兩種可能性: 1. 如果RXNE=1,表示之前的資料還在RDR中,且可被讀出 2. 如果RXNE=0,表示之前的資料已被讀走,RDR已無資料可被讀取,此種情況發生在讀取RDR中上一筆資料時,又接收到新的資料時發生。

噪音錯誤

透過不同的採樣技術,可以區分有效的輸入資料和噪音,並進行資料恢復。

透過設定USART_CR1中的OVER8位可選16或8次的採樣,見Fig. 250和Fig. 251: - OVER8 = 1: 採用8次採樣,採樣的頻率較快(最高頻率為fPCLK/8) - OVER8 = 0: 採用16次採樣,採樣的頻率最高為fPCLK/16

設定USART_CR3中的ONEBIT位可選則不同的採樣技術: - ONEBIT = 0: 採樣資料中心的 3 bits,若此3 bits不相等,則NF位會被設定 - ONEBIT = 1: 只採樣中心的單一bit,此時NF的檢測將會被取消

當在資料接收中檢測到噪音時: - NE會在RXNE位的升緣時被設定 - 無效的資料會從received shift register移入USART_DR暫存器中 - 在單一資料的接收下,不會有中斷產生,但透過NE和RXNE位的設置,由後者來產生中斷;

 在多緩衝器的接收中,如果USART_CR3暫存器中的EIE位被設定,則會產生一個中斷

.. image:: /oversampling16.png

.. image:: /oversampling8.png

.. image:: /noisedetection.png

.. image:: /noisedetectionsampledata.png

Ref: RM0090 Reference Manual P.957~958<http://www.st.com/web/en/resource/technical/document/reference_manual/DM00031020.pdf>_

Frame錯誤

由於沒有同步上或線路上大量的噪音,使得停止位沒有在預期的時間上接收和識別出來,則發生Frame錯誤

當Frame錯誤被檢測出時: 1. FE位被設定,如圖中的(l) 2. 無效的資料從received shift register移入USART_DR暫存器中 3. 在一般資料的接收下,不會有中斷產生,可藉由RXNEIE位的設置,在中斷中檢測FE位得知發生錯誤;

  在DMA的接收中,如果USART_CR3暫存器中的EIE位被設定,則會產生一個中斷,如圖中的(k)

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

Fractional baud rate generation的設定

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

.. image:: /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/(822187.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.

Modes ……………………….

PARITY CONTROL

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

.. image:: /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

如果 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

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

小知識:

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

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

LIN(local interconnection network) mode

USART SYNCHRONOUS MODE

Ref: RM0090 Reference Manual P.974<http://www.st.com/web/en/resource/technical/document/reference_manual/DM00031020.pdf>_

若要使用此模式,要把USART_CR2的CLKEN設定為1。下列設定必須要設為0: - 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是單向輸出)。

.. image:: /synchronous_transmission.png

.. image:: /usart_syn.png

Single-wire half-duplex communication

若要啟用單線半雙工模式,可以設定USART_CR3的HDSEL為1。而下列設定必須要設定為0: - 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。

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

SmartCard Mode

.. image:: /smart_card.jpg

SmartCard

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

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

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

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

.. image:: /parity_smartcard.png

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

Smartcard是單線半雙工的通訊協定: - 從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訊號,否則就不傳送。 - TC旗標的設立,可藉由設定Guard Time暫存器來延遲設立的時間。在一般模式(USART)下,若transmit shift暫存器是空的,而且沒有額外的傳送要求時,TC旗標會立即被設立。但在Smartcard模式,在transmit shift暫存器是空的時候,此暫存器會先觸發Guard time counter,並且在Guard time暫存器中計數到一定數值後(由使用者設定),TC旗標才會被設立。在計數的過程中,TC旗標維持低電位。 - 即使是使用Smartcard模式,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。

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

IrDA SIR ENDEC mode

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

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

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

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

Continuous communication using 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

若要啟用DMA模式,要在USART_CR3把DMAT啟用。在TXE bit被設立時,資料會先從SRAM(要先由DMA周邊設定,請參考DMA說明手冊)載入到USART_DR暫存器。如果要把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

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 generation in multibuffer communication

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

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訊號

以上是兩者有類似的地方

HARDWARE FLOW CONTROL

Ref: RM0090 Reference Manual P.983<http://www.st.com/web/en/resource/technical/document/reference_manual/DM00031020.pdf>_

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

.. image:: /hardware_control_2usarts.png

RTS Flow Control

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

.. image:: /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

USART Register 總表 ………………………….. Status register(USART_SR)

Data register(USART_DR)

Baud rate register(USART_BRR)

Control Register 1(USART_CR1)

Control Register 2(USART_CR2)

Control Register 3(USART_CR3)

Guard time and prescaler register(USART_GTPR)

.. image:: /USART_register.png

CODE SECTION …………………….

發送器測試

Download sample code :

.. code-block:: c

git clone https://github.com/wujiheng/stm32f407.git
cd stm32f407/USART

To compile code

.. code-block:: c

make make flash <– 記得把USB連上去

這裡採用minicom 超級終端機來接收USART字串

.. code-block:: c

ls /dev <– 找device,見圖,這裡找到/dev/ttyUSB0

.. image:: /usart-ls-dev.png

.. code-block:: c

sudo apt-get install minicom sudo minicom -s <– 不一定要用root,不過使用者必須要device node 讀寫的權限,-s表進入setup

.. image:: /usart-minicom-setup.png .. image:: /usart-minicom-device.png .. code-block:: c

選擇第三個“Serial port setup”,設定接收的模式及port
先按’A’選擇device,並輸入/dev/ttyUSB0(由剛剛的ls /dev)決定

.. image:: /usart-minicom-parameter.png

再來按’E’設定接收的參數,選擇 .. code-block:: c

‘C’ –> Baud rate 9600

‘L’ –> None parity check

‘V’ –> 資料長度 8 bits

‘W’ –> 停止位元數 1 bit

輸入完後按Enter離開

.. image:: /usart-minicom-save.png

.. code-block:: c

回到原本的畫面,選擇 ‘Save setup as default’ ,然後選擇 ‘Exit from Minicom’ 離開

.. image:: /usart-minicom.png

.. code-block:: c 回到Terminal,重新輸入sudo minicom進入Minicom的畫面

.. image:: /usart-minicom.png

.. image:: /usart-pin.jpg

.. code-block:: c

按照圖上的接法,白色線接PA2、綠色線接PA3 ** 白色線為USB的RX所以要接上板子的TX(PA2) ** ** 綠色線為USB的TX所以要接上板子的RX(PA3) ** ** 線材部分使用usb轉ttl轉接線(內部有轉接晶片,將PC usb訊號轉成GPIO腳位的電氣訊號) 另外有usb轉rs232 cable線,使用時從stm32板子接出的gpio輸出電訊號0~5V之間,不符合rs232接腳的電氣訊號(+-5V),須再透過轉接晶片才能正確寫入,否則會出現亂碼 **

此時畫面中的Minicom會顯示出結果,不斷的印出“Init complete! Hello World!”

.. image:: /usart_minicom_results.png

按Ctrl+a,再按x可離開Minicom

實驗波形圖,採用USBee AX作訊號分析

.. image:: /usart_wave.jpg

接收器測試

To compile code

.. code-block:: c

// 切換到branch USART_Receive git checkout USART_Receive

// 編譯並上傳程式 make; make flash

.. image:: /usart_minicom_receive.png

.. code-block:: c

打開Minicom只會看到一行字串

.. image:: /usart_sendfile.png

.. code-block:: c

接著按下 Ctrl+a 然後按 s 出現Upload選項,選擇最後一項 ‘ascii’

.. image:: /usart_selectfile.png

.. code-block:: c

找到要發送過去的檔案,按空白鍵選取,按Enter開始傳送

.. image:: /usart_sendsuccess.png

.. code-block:: c

傳送成功後如圖所示,程式會在接收到資料後,回傳相同的資料

.. image:: /usart_receive_result.png

.. code-block:: c

印出來的資料應如同檔案中的字串

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

圖片來源<http://electronics.stackexchange.com/questions/42236/uart-receiver-clock-speed>_