前言
Uart在一個嵌入式系統(tǒng)中是一個非常重要的模塊,他承擔了CPU與用戶交互的橋梁。用戶輸入信息給程序、CPU要打印一些信息給終端都要依賴UART。
本文將以Exynos4412的UART控制器為基礎(chǔ),講解UART的原理以及驅(qū)動程序如何編寫。
UART是什么
UART是通用異步收發(fā)傳輸器(Universal Asynchronous Receiver/Transmitter),通常稱作UART,是一種異步收發(fā)傳輸器,是設(shè)備間進行異步通信的關(guān)鍵模塊。UART負責處理數(shù)據(jù)總線和串行口之間的串/并、并/串轉(zhuǎn)換,并規(guī)定了幀格式;通信雙方只要采用相同的幀格式和波特率,就能在未共享時鐘信號的情況下,僅用兩根信號線(Rx 和Tx)就可以完成通信過程,因此也稱為異步串行通信。UART總線雙向通信,可以實現(xiàn)全雙工傳輸和接收。在嵌入式設(shè)計中,UART用于主機與輔助設(shè)備通信,如汽車音響與外接AP之間的通信,與PC機通信包括與監(jiān)控調(diào)試器和其它器件,如EEPROM通信。
通常需要加入一個合適的電平轉(zhuǎn)換器,如SP3232E、SP3485,UART還能用于RS-232、RS-485 通信,或與計算機的端口連接。UART 應用非常廣泛,手機、工業(yè)控制、PC 等應用中都要用到UART。
UART通信方式
UART使用的是 異步,串行通信方式。
串行通信
串行通信是指利用一條傳輸線將資料一位位地順序傳送。好比是一列縱隊,每個數(shù)據(jù)元素依次縱向排列。如下圖所示,傳輸時一個比特一個比特的串行傳輸,每個時鐘周期傳輸一個比特,這種傳輸方式相對比較簡單,速度較慢,但是使用總線數(shù)較少,通常一根接收線,一根發(fā)送線即可實現(xiàn)串行通信。
它的缺點是要增加額外的數(shù)據(jù)來控制一個數(shù)據(jù)幀的開始和結(jié)束。特點是通信線路簡單,利用簡單的線纜就可實現(xiàn)通信,降低成本,適用于遠距離通信,但傳輸速度慢的應用場合。
并行通信
并行通信好比一排橫隊,齊頭并進同時傳輸。這種通信方式每個時鐘周期傳輸?shù)臄?shù)據(jù)量和其總線寬度成正比,但是實現(xiàn)較為復雜。
異步通信
異步通信以一個字符為傳輸單位,通信中兩個字符間的時間間隔多少是不固定的,然而在同一個字符中的兩個相鄰位間的時間間隔是固定的。
在異步通信技術(shù)中,數(shù)據(jù)發(fā)送方和數(shù)據(jù)接收方?jīng)]有同步時鐘,只有數(shù)據(jù)信號線,只不過發(fā)送端和接收端會按照協(xié)商好的協(xié)議(固定頻率)來進行數(shù)據(jù)采樣。數(shù)據(jù)發(fā)送方以每秒鐘57600bits的速度發(fā)送數(shù)據(jù),接收方也以57600bits的速度去接收數(shù)據(jù),這樣就可以保證數(shù)據(jù)的有效和正確。通常異步通信中使用波特率(Baud-Rate)來規(guī)定雙方傳輸速度,其單位為bps(bits per second每秒傳輸位數(shù))。
同步通信
在發(fā)送數(shù)據(jù)信號的時候,會同時送出一根同步時鐘信號, 用來同步發(fā)送方和接收方的數(shù)據(jù)采樣頻率。如下圖所示,同步通信時,信號線1是一根同步時鐘信號線,以固定的頻率進行電平的切換,其頻率周期為t,在每個電平的上升沿之后進行對同步送出的數(shù)據(jù)信號線2進行采樣(高電平代表1,低電平代表0),根據(jù)采樣數(shù)據(jù)電平高低取得輸出數(shù)據(jù)信息。如果雙方?jīng)]有同步時鐘的話,那么接收方就不知道采樣周期,也就不能正常的取得數(shù)據(jù)信息。
幀格式
數(shù)據(jù)傳送速率用波特率來表示,即每秒鐘傳送的二進制位數(shù)。例如數(shù)據(jù)傳送速率為120字符/秒,而每一個字符為10位(1個起始位,7個數(shù)據(jù)位,1個校驗位,1個結(jié)束位),則其傳送的波特率為10×120=1200字符/秒=1200波特。數(shù)據(jù)通信格式如下圖:
其中各位的意義如下:
起始位:先發(fā)出一個邏輯”0”信號,表示傳輸字符的開始。*數(shù)據(jù)位:可以是5~8位邏輯”0”或”1”。如ASCII碼(7位),擴展BCD碼(8位)。小端傳輸 *校驗位:數(shù)據(jù)位加上這一位后,使得“1”的位數(shù)應為偶數(shù)(偶校驗)或奇數(shù)(奇校驗) *停止位:它是一個字符數(shù)據(jù)的結(jié)束標志。可以是1位、1.5位、2位的高電平。*空閑位:處于邏輯“1”狀態(tài),表示當前線路上沒有資料傳送。
注:異步通信是按字符傳輸?shù)模邮赵O(shè)備在收到起始信號之后只要在一個字符的傳輸時間內(nèi)能和發(fā)送設(shè)備保持同步就能正確接收。下一個字符起始位的到來又使同步重新校準(依靠檢測起始位來實現(xiàn)發(fā)送與接收方的時鐘自同步的)
關(guān)于RS-232、RS-422、RS-485等標準,大家可以參考文章《一篇文章了解什么是串口,UART、RS-232、RS-422、RS-485 》
Exynos4412 Uart
本文討論UART 是基于Cortex-A9架構(gòu)的Exynos4412 為例。
特性
Exynos4412 中UART,有4 個獨立的通道,每個通道都可以工作于中斷模式或DMA 模式,即UART 可以發(fā)出中斷或 DMA 請求以便在UART 、CPU 間傳輸數(shù)據(jù)。使用系統(tǒng)時鐘時,Exynos4412 的 UART 波特率可以達到 4Mbps 。每個UART通道包含兩個FIFO用來接收和發(fā)送:
通道 0有 256 字節(jié)的發(fā)送 FIFO 和 256 字節(jié)的接收FIFO
通道 1、4有 64 字節(jié)的發(fā)送 FIFO 和 64 字節(jié)的接收FIFO
通道 2、3有 16 字節(jié)的發(fā)送FIFO 和 16 字節(jié) 的接收 FIFO 。
UART include:
波特率可以通過編程進行 。
紅外接收/發(fā)送
每個通道支持停止位有 1位、 2位
數(shù)據(jù)位有 5、6、7或 8位
每個UART還包括
波特率發(fā)生器、發(fā)送器、接收器、控制邏輯組成。
Uart控制器
功能模塊
每個UART包含一個波特率產(chǎn)生器,發(fā)送器,接收器和一個控制單元,如上圖所示:
發(fā)送數(shù)據(jù) CPU 先將數(shù)據(jù)寫入發(fā)送FIFO 中,然后 UART 會自動將FIFO 中的數(shù)據(jù)復制到“發(fā)送移位器” (Transmit Shifter )中,發(fā)送移位器將數(shù)據(jù)一位一位地發(fā)送到 TxDn 數(shù)據(jù)線上 (根據(jù)設(shè)定的格式,插入開始位 、較驗和停止)。
接收數(shù)據(jù) “移位器” (Receive Shifter )將 RxDn 數(shù)據(jù)線上的數(shù)據(jù)一位一位的接收進來,然后復制到FIFO 中, CPU即可從中讀取數(shù)據(jù)。
UART是以異步方式實現(xiàn)通信的,其采樣速度由波特率決定,波特率產(chǎn)生器的工作頻率可以由PCLK(外圍設(shè)備頻率),F(xiàn)CLK/n(CPU工作頻率的分頻),UEXTCLK(外部輸入時鐘)三個時鐘作為輸入頻率,波特率設(shè)置寄存器是可編程的,用戶可以設(shè)置其波特率決定發(fā)送和接收的頻率。發(fā)送器和接收器包含了64Byte的FIFO和數(shù)據(jù)移位器。UART通信是面向字節(jié)流的,待發(fā)送數(shù)據(jù)寫到FIFO之后,被拷貝到數(shù)據(jù)移位器(1字節(jié)大小)里,數(shù)據(jù)通過發(fā)送數(shù)據(jù)管腳TXDn發(fā)出。同樣道理,接收數(shù)據(jù)通過RXDn管腳來接收數(shù)據(jù)(1字節(jié)大小)到接收移位器,然后將其拷貝到FIFO接收緩沖區(qū)里。(1)數(shù)據(jù)發(fā)送 發(fā)送的數(shù)據(jù)幀可編程的,它的一個幀長度是用戶指定的,它包括一個開始位,5~8個數(shù)據(jù)位,一個可選的奇偶校驗位和1~2個停止位,數(shù)據(jù)幀格式可以通過設(shè)置ULCONn寄存器來設(shè)置。發(fā)送器也可以產(chǎn)生一個終止信號,它是由一個全部為0的數(shù)據(jù)幀組成。在當前發(fā)送數(shù)據(jù)被完全傳輸完以后,該模塊發(fā)送一個終止信號。在終止信號發(fā)送后,它可以繼續(xù)通過FIFO(FIFO)或發(fā)送保持寄存器(NON-FIFO)發(fā)送數(shù)據(jù)。(2)數(shù)據(jù)接收 同樣接收端的數(shù)據(jù)也是可編程的,接收器可以偵測到溢出錯誤奇偶校驗錯誤,幀錯誤和終止條件,每個錯誤都可以設(shè)置一個錯誤標志。? 溢出錯誤 :在舊數(shù)據(jù)被讀取到之前,新數(shù)據(jù)覆蓋了舊數(shù)據(jù) ? 奇偶校驗錯誤:接收器偵測到了接收數(shù)據(jù)校驗結(jié)果失敗,接收數(shù)據(jù)無效 ? 幀錯誤 :接收到的數(shù)據(jù)沒有一個有效的停止位,無法判定數(shù)據(jù)幀結(jié)束 ? 終止條件 :RxDn接收到保持邏輯0狀態(tài)持續(xù)長于一個數(shù)據(jù)幀的傳輸時間
(3)自動流控AFC(Auto Float Control) UART0和UART1支持有nRTS和nCTS的自動流控。在AFC情況下,通信雙方nRTS和nCTS管腳分別連接對方的nCTS和nRTS管腳。通過軟件控制數(shù)據(jù)幀的發(fā)送和接收。在開啟AFC時,發(fā)送端接收發(fā)送前要判斷nCTS信號狀態(tài),當接收到nCTS激活信號時,發(fā)送數(shù)據(jù)幀。該nCTS管腳連接對方nRTS管腳。接收端在準備接收數(shù)據(jù)幀前,其接收器FIFO有大于32個字節(jié)的空閑空間,nRTS管腳會發(fā)送激活信號,當其接收FIFO小于32個字節(jié)的空閑空間,nRTS必須置非激活狀態(tài)。
選擇時鐘源
Exynos4412 UART的時鐘源有八種選擇:XXTI 、XusbXTI 、SCLK_HDMI24M 、SCLK_USBPHY0 、 SCLK_HDMIPHY 、SCLKMPLL_USER_T 、SCLKEPLL 、SCLKVPLL ,由 CLK_SRC_PERIL0 寄存器控制。選擇好時鐘源后,還可以通過 DIVUART0 ~4設(shè)置分頻系數(shù),由 CLK_DIV_PERIL0 寄存器控制。從分頻器得到的時鐘被稱為SCLK UART 。SCLK UART 經(jīng)過上圖中的“ UCLK Generator”后,得到UCLK ,它的頻率就是UART 的波特率。“ Generator UCLK Generator ”通過這 2個寄存器來設(shè)置:UBRDIVn(UART BAUD RATE DIVISOR) 、UFRACVALn 。
UART配置寄存器
ULCONn
bite [6] 紅外模式 選擇串口0是否使用紅外模式:0 = 正常通信模式 1 = 紅外通信模式
bite [5:3] 校驗模式 設(shè)置串口0在數(shù)據(jù)接收和發(fā)送時采用的校驗方式:0xx = 無校驗 100 = 奇校驗 101 = 偶校驗 110 = 強制校驗/檢測是否為1 111 = 強制校驗/檢測是否為0
[2] 停止位 設(shè)置串口0停止位數(shù):0 = 每個數(shù)據(jù)幀一個停止位 1 = 每個數(shù)據(jù)幀二個停止位
[1:0] 數(shù)據(jù)位 設(shè)置串口0數(shù)據(jù)位數(shù):00 = 5個數(shù)據(jù)位 01 = 6個數(shù)據(jù)位 10 = 7個數(shù)據(jù)位 11 = 8個數(shù)據(jù)位
該寄存器我們通用的配置是:
ULCON2=0x3;//Normalmode,Noparity,Onestopbit,8databits
UCONn
[15:12]FCLK分頻因子當UART0選擇FCLK作為時鐘源時,設(shè)置其FCLK的分頻因子 UART0 工作時鐘頻率 = FCLK/ FCLK分頻因子 + 6
[11:10] UART時鐘源選擇 選擇UART0的工作時鐘PCLK,UEXTCLK,F(xiàn)CLK/n:00,10 = PCLK 01 = UEXTCLK 11 = FCLK/n 當選擇FCLK/n作為UART0工作時鐘時還要做其它設(shè)置,具體請讀者自行查看硬件手冊
[9] 發(fā)送數(shù)據(jù)中斷產(chǎn)生類型 設(shè)置UART0中斷請求類型,在非FIFO傳輸模式下,一旦發(fā)送數(shù)據(jù)緩沖區(qū)為空,立即產(chǎn)生中斷信號,在FIFO傳輸模式下達到發(fā)送數(shù)據(jù)觸發(fā)條件時立即產(chǎn)生中斷信號:0 = 脈沖觸發(fā) 1 = 電平觸發(fā)
[8] 接收數(shù)據(jù)中斷產(chǎn)生類型 設(shè)置UART0中斷請求類型,在非FIFO傳輸模式下,一旦接收到數(shù)據(jù),立即產(chǎn)生中斷信號,在FIFO傳輸模式下達到接收數(shù)據(jù)觸發(fā)條件時立即產(chǎn)生中斷信號:0 = 脈沖觸發(fā) 1 = 電平觸發(fā)
[7] 接收數(shù)據(jù)超時 設(shè)置當接收數(shù)據(jù)時,如果數(shù)據(jù)超時,是否產(chǎn)生接收中斷:0 = 不開啟超時中斷 1 = 開啟超時中斷 10 = 7個數(shù)據(jù)位 11 = 8個數(shù)據(jù)位
[6] 接收數(shù)據(jù)錯誤中斷 設(shè)置當接收數(shù)據(jù)時,如果產(chǎn)生異常,如傳輸中止,幀錯誤,校驗錯誤時,是否產(chǎn)生接收狀態(tài)中斷信號:0 = 不產(chǎn)生錯誤狀態(tài)中斷 1 = 產(chǎn)生錯誤狀態(tài)中斷
[5] 回送模式 設(shè)置該位時UART會進入回送模式,該模式僅用于測試 0 = 正常模式 1 = 回送模式
[4] 發(fā)送終止信號 設(shè)置該位時,UART會發(fā)送一個幀長度的終止信號,發(fā)送完畢后,該位自動恢復為0 0 = 正常傳輸 1 = 發(fā)送終止信號
[3:2] 發(fā)送模式 設(shè)置采用哪個方式執(zhí)行數(shù)據(jù)寫入發(fā)送緩沖區(qū) 00 = 無效 01 = 中斷請求或查詢模式 10 = DMA0請求
[1:0] 接收模式 設(shè)置采用哪個方式執(zhí)行數(shù)據(jù)寫入接收緩沖區(qū) 00 = 無效 01 = 中斷請求或查詢模式 10 = DMA0請求
該寄存器通用配置為:
UCON2=0x5;//Interruptrequestorpollingmode
一般裸機情況下,采用輪詢模式。
UTRSTATn
UTRSTAT n寄存器用來表明數(shù)據(jù)是否已經(jīng)發(fā)送完畢、是否已經(jīng)接收到數(shù)據(jù),格式如下圖所示,上面說的“緩沖區(qū)”,其實就是下圖中的 FIFO ,不使用 FIFO 功能時可以認為其深度為 1。當我們讀取數(shù)據(jù)時,就輪詢檢查bit[0]置1之后,然后再從URXHn寄存器讀取數(shù)據(jù);當我們讀取數(shù)據(jù)時,就輪詢檢查bit[1]置1之后,然后再向UTXHn寄存器寫入數(shù)據(jù)來發(fā)送數(shù)據(jù);
UTXHn寄存器(UART TRANSMIT BUFFER REGISTER)
CPU 將數(shù)據(jù)寫入這個寄存器, UART即會將它保存到緩沖區(qū)中,并自動發(fā)送出去。
URXHn寄存器(UART RECEIVE BUFFER REGISTER)
當 UART 接收到數(shù)據(jù)時,讀取這個寄存器,即可獲得數(shù)據(jù)。
UFRACVALn 計算波特率
根據(jù)給定的波特率、所選擇時鐘源頻率,可以通過以下公式計算 UBRDIVn 寄存器 (n 為 0~4,對應 5個 UART 通道 )的值。
UBRDIVn=(int)(UARTclock/(buadratex16))–1
上式計算出來的 UBRDIVn 寄存器值不一定是整數(shù), UBRDIVn 寄存器取其整數(shù)部分,小部分由 UFRACVALn 寄存器設(shè)置, UFRACVALn 寄存器的引入,使產(chǎn)生波特率更加精確。【舉例】當UART clock為100MHz時,要求波特率為115200 bps,則:
100000000/(115200x16)–1=54.25–1=53.25 UBRDIVn=整數(shù)部分=53 UFRACVALn/16=小數(shù)部分=0.25 UFRACVALn=4
電路圖
外設(shè)電路圖:
SP3232EEA 用來將TTL電平轉(zhuǎn)換成RS232電平。我們使用的是COM2。
外設(shè)與核心板連接電路圖
可見UART的收發(fā)引腳連接到了GPA上,打開exynos4412芯片手冊:
我們只需要將GPA1 的低8位設(shè)置為0x22。
實例代碼
裸機代碼,主要實現(xiàn)uart_init()、putc()、getc()這三個函數(shù)。
uart_init()
該函數(shù)主要配置UART的,波特率115200,數(shù)據(jù)位:8,奇偶校驗位:0,終止位:1,不設(shè)置流控。如下圖:是運行在windows下常用的串口工具配置信息,配置信息必須完全一致。
putc()
該函數(shù)是向串口發(fā)送一個數(shù)據(jù)data,他的實現(xiàn)邏輯就是輪詢檢查寄存器UART2.UTRSTAT2 ,判斷其bite【1】是否置1,如果置1,則向UART2.UTXH2存入要發(fā)送的數(shù)據(jù)即可。
getc()
該函數(shù)是從串口接收一個數(shù)據(jù)data,他的實現(xiàn)邏輯就是輪詢檢查寄存器UART2.UTRSTAT2 ,判斷其bite【0】是否置1,如果置1,說明數(shù)據(jù)準備好,則可以從寄存器UART2.URXH2取出數(shù)據(jù)。
/* *UART2 */ typedefstruct{ unsignedintULCON2; unsignedintUCON2; unsignedintUFCON2; unsignedintUMCON2; unsignedintUTRSTAT2; unsignedintUERSTAT2; unsignedintUFSTAT2; unsignedintUMSTAT2; unsignedintUTXH2; unsignedintURXH2; unsignedintUBRDIV2; unsignedintUFRACVAL2; unsignedintUINTP2; unsignedintUINTSP2; unsignedintUINTM2; }uart2; #defineUART2(*(volatileuart2*)0x13820000) /*GPA1*/ typedefstruct{ unsignedintCON; unsignedintDAT; unsignedintPUD; unsignedintDRV; unsignedintCONPDN; unsignedintPUDPDN; }gpa1; #defineGPA1(*(volatilegpa1*)0x11400020) voiduart_init() {/*UART2initialize*/ GPA1.CON=(GPA1.CON&~0xFF)|(0x22);//GPA1_0:RX;GPA1_1:TX UART2.ULCON2=0x3;//Normalmode,Noparity,Onestopbit,8databits UART2.UCON2=0x5;//Interruptrequestorpollingmode //Baud-rate:src_clock:100Mhz UART2.UBRDIV2=0x35; UART2.UFRACVAL2=0x4; } voidputc(constchardata) {while(!(UART2.UTRSTAT2&0X2)); UART2.UTXH2=data; if(data==) putc(); } chargetc(void) {chardata; while(!(UART2.UTRSTAT2&0x1)); data=UART2.URXH2; if((data==)||(data==)) { putc(); putc(); }else putc(data); returndata; } voidputs(constchar*pstr) {while(*pstr!=') putc(*pstr++); } voidgets(char*p) {chardata; while((data=getc())!=) {if(data==') {p--; } *p++=data; } if(data==) *p++=; *p='; }
責任編輯:lq
-
轉(zhuǎn)換器
+關(guān)注
關(guān)注
27文章
8745瀏覽量
148063 -
ARM
+關(guān)注
關(guān)注
134文章
9169瀏覽量
369247 -
uart
+關(guān)注
關(guān)注
22文章
1243瀏覽量
101775
原文標題:基于ARM UART裸機驅(qū)動詳解
文章出處:【微信號:mcu168,微信公眾號:硬件攻城獅】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關(guān)推薦
AN3761-KSZ DSA驅(qū)動程序的使用
![AN3761-KSZ DSA<b class='flag-5'>驅(qū)動程序</b>的使用](https://file.elecfans.com/web1/M00/D9/4E/pIYBAF_1ac2Ac0EEAABDkS1IP1s689.png)
ub933驅(qū)動程序是基于I2c編寫的,請問驅(qū)動程序應該放在內(nèi)核drivers目錄下的哪個子目錄里?
pcie設(shè)備驅(qū)動程序安裝步驟
硬盤電機怎么驅(qū)動程序?它有什么典型特征?
LSP 2.10 DaVinci Linux驅(qū)動程序
![LSP 2.10 DaVinci Linux<b class='flag-5'>驅(qū)動程序</b>](https://file.elecfans.com/web1/M00/D9/4E/pIYBAF_1ac2Ac0EEAABDkS1IP1s689.png)
Linux設(shè)備驅(qū)動程序分類有哪些
linux驅(qū)動程序如何加載進內(nèi)核
linux驅(qū)動程序主要有哪些功能
linux驅(qū)動程序的編譯方法是什么
linux驅(qū)動程序運行在什么空間
虹科技術(shù) Linux環(huán)境再升級:PLIN驅(qū)動程序正式發(fā)布
![虹科技術(shù) Linux環(huán)境再升級:PLIN<b class='flag-5'>驅(qū)動程序</b>正式發(fā)布](https://file1.elecfans.com/web2/M00/F5/F5/wKgaomZ-S0OAG_HXAFo15SJaG1U235.png)
Framebuffer 驅(qū)動程序框架
![Framebuffer <b class='flag-5'>驅(qū)動程序</b>框架](https://file1.elecfans.com//web2/M00/E5/25/wKgaomY_EYWALQiBAAFocwCI-0c762.png)
怎么編寫Framebuffer驅(qū)動程序
![怎么<b class='flag-5'>編寫</b>Framebuffer<b class='flag-5'>驅(qū)動程序</b>](https://file1.elecfans.com/web2/M00/C6/45/wKgaomX829SAfIacAAAbtdy6Rus988.png)
評論