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`_ - 可調整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`_ 此通訊界面以三個腳位與其他設備連接。任何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`_ 傳送器 ============================ 傳送器依據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)。每個資料再傳送前都會有一個低電位的起始位;之後跟著的停止位元數目,則可由使用者決定0.5, 1, 1.5或2 - 1 bit的stop bit: 預設的默認停止位位元數 - 2 bits的stop bit: normal USART, single-wire 和 modem modes - 0.5 bits的stop bit: Smartcard mode接收數據用 - 1.5 bits的stop bit: Smartcard mode發送數據用 **stop bits其實不算是個bit,他是傳輸結束後的一段時間(period),用以區隔每個傳輸的資料,其功用是在非同步傳輸的時候可以告訴接收器,資料傳輸已經結束。透過增加stop bits的長度,可讓接收器能有足夠的時間可以處理該資料** **另外,由於資料搬移到transmit shift register中最少需要1/2 baud clock,因此在Smartcard mode的接收中,最少必須設定0.5 bit的stop bits** .. image:: /usart_fig298.jpg Ref: `RM0090 Reference Manual P.952`_ 傳送器的設定 ------------------------------------ .. image:: /usart_transmiter.png 1. 設定USART_CR1暫存器的UE位來啟動傳輸,如圖中的(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位,在第一筆資料傳送前,傳送一個空閒的frame,如圖中的(f) 7. 將欲發送的資料放入USART_DR中,如圖中的(g) 8. 若有多筆資料要傳送,則重複步驟7.,如圖中的(l) 當資料放入USART_DR會由硬體清除TXE位,如圖中的(h),則表示: 1. 資料已從TDR中進入transmit shift register,資料的發送已開始 2. TDR暫存器已被清空 3. 下一筆資料可放入USART_DR中 若TXEIE位的設置,則會產生一個中斷,如圖中的(i): - 如果USART正在發送資料,對USART_DR的寫入會把資料移到TDR暫存器中,並在目前的資料傳送結束後把該筆資料移進transmit shift register中 - 如果USART沒有在發送資料,則對USART_DR的寫入會把資料直接放入transmit shift register中,並啟動傳送,當傳送開始時,硬體會立即設定TXE位 一個frame的資料發送完畢後,TC位會被設定,如圖中的(j),如果USART_CR1中的TCIE有被設定,則會產生一個中斷,如圖中的(k),先讀取USART_SR暫存器,再寫入USART_DR暫存器,則可清除TC位 傳送斷開符號 ------------------------------------ 透過設定USART_CR1的SBK位,可以發送一個斷開符號,斷開符號的長度取決於M位。 如果SBK=1,則在目前的資料發送後,會再TX線上發送一個斷開符號,當傳送完成後,會由硬體恢復SBK位。 USART會由硬體在最後一個斷開符號的結束處插入一個'1',確保能辨識下一個資料的起始位。 傳送空閒符號 ------------------------------------ 設置USART_CR1的TE位會使得USART在發送第一筆資料前,發送一個空閒符號,喚醒接收端。 接收器 ==================================== 接收器依據USART_CR1 M位的狀態來決定接收8或9位元的資料。 起始位偵測 ------------------------------------ .. image:: /usart_fig300.jpg Ref: `RM0090 Reference Manual P.954`_ 在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`_ 假設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`_ 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`_ 其中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. Modes ............................ SmartCard Mode ==================== 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`_ 若要使用此模式,則必須設定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`_ 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 SYNCHRONOUS MODE ========================= Ref: `RM0090 Reference Manual P.974`_ 若要使用此模式,要把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 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`_ 利用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 PARITY CONTROL .............. Parity control是用來確保傳輸資料的正確性。其原理是在傳輸端產生一個parity bit,然後在接收端可以重新計算parity bit以確保在傳輸過程沒有發生錯誤。在STM32,它可以透過設定USART_CR1 register的PCE bit來打開。STM32的frame長度是由M bit所決定,所以USART的frame有以下這些可能格式: .. image:: /frame_formats.png Even/Odd parity ================================= 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 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.`_ - `[2]STM32F407xx Reference Manual P.946 ~ P.997`_ - `[3]IrDA and RS-232`_ - `[4]Using The DMA controller on STM32`_ - `[5]ISO 7816-3`_ 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 `圖片來源`_