S3C2440 UART串口驅(qū)動
1.1UART串口
通用異步接收器和發(fā)送器(Universal Asynchronous Receiver and Transmitter)簡稱UART。通常是嵌入式設(shè)備中默認(rèn)都會配置的通信接口。這是因為,很多嵌入式設(shè)備沒有顯示屏,無法獲得嵌入式設(shè)備實時數(shù)據(jù)信息,通過UART串口和超級終端相連,打印嵌入式設(shè)備輸出信息。并且在對嵌入式系統(tǒng)進行跟蹤和調(diào)試時,UART串口了是必要的通信手段。比如:網(wǎng)絡(luò)路由器,交換機等都要通過串口來進行配置。UART串口還是許多硬件數(shù)據(jù)輸出的主要接口,如GPS接收器就是通過UART串口輸出GPS接收數(shù)據(jù)的。1.1.1異步通信和同步通信
圖2-56同步信號與異步信號
同步通信技術(shù)
在發(fā)送數(shù)據(jù)信號的時候,會同時送出一根同步時鐘信號,用來同步發(fā)送方和接收方的數(shù)據(jù)采樣頻率。如圖2-56所示,同步通信時,信號線1是一根同步時鐘信號線,以固定的頻率進行電平的切換,其頻率周期為t,在每個電平的上升沿之后進行對同步送出的數(shù)據(jù)信號線2進行采樣(高電平代表1,低電平代表0),根據(jù)采樣數(shù)據(jù)電平高低取得輸出數(shù)據(jù)信息。如果雙方?jīng)]有同步時鐘的話,那么接收方就不知道采樣周期,也就不能正常的取得數(shù)據(jù)信息。
異步通信技術(shù)
在異步通信技術(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ù))。
1.1.2數(shù)據(jù)的串行和并行通信方式
串行通信好比是一列縱隊,每個數(shù)據(jù)元素依次縱向排列。如圖2-57所示,傳輸時一個比特一個比特的串行傳輸,每個時鐘周期傳輸一個比特,這種傳輸方式相對比較簡單,速度較慢,但是使用總線數(shù)較少,通常一根接收線,一根發(fā)送線即可實現(xiàn)串行通信。它的缺點是要增加額外的數(shù)據(jù)來控制一個數(shù)據(jù)幀的開始和結(jié)束。并行通信好比一排橫隊,齊頭并進同時傳輸。這種通信方式每個時鐘周期傳輸?shù)臄?shù)據(jù)量和其總線寬度成正比,但是實現(xiàn)較為復(fù)雜。UART通信采用的是串行方式進行通信的。
圖2-57串行數(shù)據(jù)通信與并行數(shù)據(jù)通信
1.1.3數(shù)據(jù)通信傳輸模式
在數(shù)據(jù)通信過程中,發(fā)送方和接收方為了實現(xiàn)數(shù)據(jù)的正確發(fā)送和接收,通常會有一個狀態(tài)寄存器來描述當(dāng)前數(shù)據(jù)接收和發(fā)送狀態(tài),當(dāng)發(fā)送方有數(shù)據(jù)發(fā)送時,會查看發(fā)送狀態(tài)寄存器,看是否允許發(fā)送數(shù)據(jù)(如果上一次數(shù)據(jù)還沒有發(fā)送完畢,不允許繼續(xù)數(shù)據(jù)發(fā)送),在發(fā)送允許情況下再送出新數(shù)據(jù)。同樣,接收端通過查看接收狀態(tài)寄存器,確定是否有新數(shù)據(jù)到達,如果有數(shù)據(jù)到達,將去接收數(shù)據(jù)緩沖區(qū)讀取數(shù)據(jù)。(1)輪詢模式
通過程序執(zhí)行流,不停的檢測狀態(tài)寄存器的結(jié)果,如果當(dāng)前可發(fā)送或接收,則發(fā)送或接收數(shù)據(jù)。其過程可以用下面?zhèn)未a來表示。
;輪詢方式實現(xiàn)數(shù)據(jù)發(fā)送偽代碼
Send(){
While(1){
if(發(fā)送狀態(tài)==可發(fā)送)
執(zhí)行數(shù)據(jù)發(fā)送操作;
}
}
;輪詢方式實現(xiàn)數(shù)據(jù)接收偽代碼
Receive(){
While(1){
if(接收狀態(tài)==有數(shù)據(jù)到達)
執(zhí)行數(shù)據(jù)接收操作;
}
}
由程序可知,這種方式實現(xiàn)簡單,但在進行數(shù)據(jù)接收和發(fā)送時都要進入循環(huán)檢查狀態(tài)寄存器的值,當(dāng)沒有數(shù)據(jù)到達或數(shù)據(jù)不可發(fā)送時,CPU會一直空轉(zhuǎn),其它程序又得不到CPU的執(zhí)行權(quán),很影響系統(tǒng)的效率。Send(){
While(1){
if(發(fā)送狀態(tài)==可發(fā)送)
執(zhí)行數(shù)據(jù)發(fā)送操作;
}
}
;輪詢方式實現(xiàn)數(shù)據(jù)接收偽代碼
Receive(){
While(1){
if(接收狀態(tài)==有數(shù)據(jù)到達)
執(zhí)行數(shù)據(jù)接收操作;
}
}
(2)中斷模式
中斷方式是指,當(dāng)數(shù)據(jù)到達或數(shù)據(jù)可發(fā)送時,產(chǎn)生中斷,通知CPU去發(fā)送或接收數(shù)據(jù),這種方式將通信硬件和CPU獨立出來,通信硬件只有在發(fā)送或接收條件準(zhǔn)備好之后中,才通知CPU去處理數(shù)據(jù),在通信條件沒有準(zhǔn)備好的時候,CPU去處理其它程序,顯然這種方式更合理,這種方式要求通信硬件要求比較高,需要支持產(chǎn)生中斷信號。
(3)DMA模式
通常實現(xiàn)數(shù)據(jù)的轉(zhuǎn)移或拷貝時,CPU將從源地址處復(fù)制數(shù)據(jù)到寄存器,然后將寄存器數(shù)據(jù)再寫入目的地址處,該復(fù)制過程需要CPU來執(zhí)行。S3C2440支持DMA傳輸模式,DMA傳輸是指在CPU不干涉的情況下,DMA硬件自動實現(xiàn)數(shù)據(jù)的轉(zhuǎn)移和復(fù)制,在DMA傳輸過程中,CPU幾乎不用干涉,這樣可以讓CPU安心的去做自己的事情。雖然如此,但是DMA在傳輸數(shù)據(jù)過程中要占用總線,在大批數(shù)據(jù)傳輸時,系統(tǒng)總線會被DMA通道占用,也會影響系統(tǒng)的效率。S3C2440 UART控制器支持DMA方式傳輸串口通信數(shù)據(jù)。
1.1.4S3C2440 UART控制器
S3C2440 UART控制器,提供了三個獨立的異步串行I/O端口,每個端口都可以在中斷模式或DMA模式下工作,換而言之,UART可以生成中斷或DMA請求用于CPU和UART之間的數(shù)據(jù)傳輸。UART串口掛接在APB總線上,APB總線最高可以達到50MHz工作頻率,在使用APB時鐘頻率時可以達到最高115.2Kbps波特率的通信速度。如果UART串口接收外部設(shè)備提供UEXTCLK(外部時鐘),UART可以在更高的速度下工作。每個UART串口在接收裝置和發(fā)送裝置里分別包含一個64Byte的FIFO緩沖區(qū),用于緩存發(fā)送數(shù)據(jù)和接收數(shù)據(jù)。由于UART是串行異步通信方式,因此在UART通信過程中每次只能傳輸1位(bit),若干位組成一個數(shù)據(jù)幀(frame),幀是UART通信中最基本單元,它主要包含:開始位,數(shù)據(jù)位,校驗位(如果開啟了數(shù)據(jù)校驗,要包含校驗位),和停止位,幀結(jié)構(gòu)如圖2-58所示。
圖2-58 UART數(shù)據(jù)幀結(jié)構(gòu)
UART在通信之前要在發(fā)送端和接收端約定好幀結(jié)構(gòu),也就是約定好傳輸數(shù)據(jù)幀格式。
l開始位:必須包含在數(shù)據(jù)幀中,表示一個幀的開始。
l數(shù)據(jù)位:可選5,6,7,8位,該位長度可由編程人員指定。
l校驗位:如果在開啟了數(shù)據(jù)校驗時,該位必須指定。
l停止位:可選1,2位,該位長度可由編程人員指定。
通信雙方約定好幀格式后,指定同一波特率,以保證雙方數(shù)據(jù)傳輸?shù)耐健?br />
1.1.5S3C2440 UART串口工作原理
每個UART包含一個波特率產(chǎn)生器,發(fā)送器,接收器和一個控制單元,如下圖所示:圖2-59 UART硬件結(jié)構(gòu)
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ù)幀組成。在當(dāng)前發(fā)送數(shù)據(jù)被完全傳輸完以后,該模塊發(fā)送一個終止信號。在終止信號發(fā)送后,它可以繼續(xù)通過FIFO(FIFO)或發(fā)送保持寄存器(NON-FIFO)發(fā)送數(shù)據(jù)。
(2)數(shù)據(jù)接收
同樣接收端的數(shù)據(jù)也是可編程的,接收器可以偵測到溢出錯誤奇偶校驗錯誤,幀錯誤和終止條件,每個錯誤都可以設(shè)置一個錯誤標(biāo)志。
l溢出錯誤是指在舊數(shù)據(jù)被讀取到之前,新數(shù)據(jù)覆蓋了舊數(shù)據(jù)
l奇偶校驗錯誤是指接收器偵測到了接收數(shù)據(jù)校驗結(jié)果失敗,接收數(shù)據(jù)無效
l幀錯誤是指接收到的數(shù)據(jù)沒有一個有效的停止位,無法判定數(shù)據(jù)幀結(jié)束
l終止條件是指RxDn接收到保持邏輯0狀態(tài)持續(xù)長于一個數(shù)據(jù)幀的傳輸時間
(3)自動流控AFC(Auto Float Control)
UART0和UART1支持有nRTS和nCTS的自動流控,UART2不支持流控。在AFC情況下,通信雙方nRTS和nCTS管腳分別連接對方的nCTS和nRTS管腳。通過軟件控制數(shù)據(jù)幀的發(fā)送和接收。
在開啟AFC時,發(fā)送端接收發(fā)送前要判斷nCTS信號狀態(tài),當(dāng)接收到nCTS激活信號時,發(fā)送數(shù)據(jù)幀。該nCTS管腳連接對方nRTS管腳。接收端在準(zhǔn)備接收數(shù)據(jù)幀前,其接收器FIFO有大于32個字節(jié)的空閑空間,nRTS管腳會發(fā)送激活信號,當(dāng)其接收FIFO小于32個字節(jié)的空閑空間,nRTS必須置非激活狀態(tài)。如圖2-60所示。
圖2-60自動流控數(shù)據(jù)傳輸
(4)波特率
在UART中波特率發(fā)生器為發(fā)送器和接收器提供工作時鐘。波特率發(fā)生器的時鐘源可以選擇S3C2440A的內(nèi)部系統(tǒng)時鐘(PCLK,F(xiàn)CLK/n)或UEXTCLK(外部時鐘源),可以通過設(shè)置UCONn寄存器來設(shè)置波特率發(fā)生器的輸入時鐘源。通常我們選擇使用PCLK作為UART工作時鐘。
UART控制器中沒有對波特率進行設(shè)置的寄存器,而是通過設(shè)置一個除數(shù)因子,來決定其波特率。其計算公式如下:
UART除數(shù)(UBRDIVn)= (int)(CLK/(buad rate * 16 )) - 1
其中:UBRDIVn的取值范圍應(yīng)該為1~2^16-1。例如:波特率為115200bps,PCLK時鐘為其工作頻率,采用50MHz,UBRDIVn為:UBRDIVn = (int)(50M / (115200 x 16)) - 1 = 26
在系統(tǒng)時鐘未初始化時,PCLK = 12MHz,如果波特率采用57600bps,那么UBRDIVn為:UBRDIVn = (int)(12M / (57600 x 16)) - 1 = 12
當(dāng)使用外部時鐘源時,如果外部時鐘小于PCLK時鐘,則UEXTCLK應(yīng)該設(shè)置為0。(5)波特率的錯誤容忍率(Baud-Rate Error Torlerance)
數(shù)據(jù)信號在傳輸過程中由于外界電磁干擾,信號減弱等原因,當(dāng)時鐘頻率較低,傳輸速率較高時會產(chǎn)生誤差,當(dāng)誤差達到一定值時,會出現(xiàn)數(shù)據(jù)信號不能正常識別,造成通信異常。好比如,在普通列車軌道上試圖行駛高速列車一樣,由于高速列車對軌道要求很高,當(dāng)速度達到一定程度,很可能造成事故。業(yè)界的波特率的錯誤容忍率為1.86%(3 / 160),如果大于該值則應(yīng)該選擇較低的波特率或提高輸入時鐘頻率。
錯誤容忍率計算公式為:
UART Error = (tUPCLK - tUEXACT)/ tUEXACT * 100%
注:tUPCLK為UART的真實工作時鐘頻率:tUPCLK = (UBRDIVn + 1) * 16 * 1Frame / PCLKtUEXACT為UART理想工作時鐘頻率:tUEXACT = 1Frame / baud-rate
其中:1Frame為數(shù)據(jù)幀的長度=開始位+數(shù)據(jù)位+可選校驗位+停止位
假如,波特率采用115200bps,PCLK時鐘為50MHz,波特率除數(shù)因子UBRDIVn為26(通過前面UBRDIVn計算公式算出),采用1個停止位,8個數(shù)據(jù)位,無校驗的8N1方式通信時,其錯誤容忍率為:
tUPCLK = 27 * 16 * 10 / 50M = 0.0000864
tUEXACT = 10 / 115200 = 0.0000868
UART Error= | 0.0000864 - 0.0000868 | / 0.0000868 = 0.46%
在開發(fā)板沒有初始化系統(tǒng)時鐘前,開發(fā)板工作在12MHz下,假如我們將波特率設(shè)置為115200bps,采用PCLK為系統(tǒng)默認(rèn)時鐘12MHz,8N1數(shù)據(jù)幀格式通信,那么:tUEXACT = 10 / 115200 = 0.0000868
UART Error= | 0.0000864 - 0.0000868 | / 0.0000868 = 0.46%
UBRDIVn = (int)(12M / (115200 * 16)) - 1 = 6
其錯誤容忍率:
tUPCLK = 7 * 16 * 10 / 12M = 0.0000933
tUEXACT = 10 / 115200 = 0.0000868
UART Error = | 0.0000933 - 0.0000868 | / 0.0000868 = 7.5%
其錯誤容忍率大于1.86%,因此在12MHz頻率下,波特率不能設(shè)置為115200,現(xiàn)在將波特率設(shè)置為56700bps,采用8N1數(shù)據(jù)幀格式通信,那么:tUEXACT = 10 / 115200 = 0.0000868
UART Error = | 0.0000933 - 0.0000868 | / 0.0000868 = 7.5%
UBRDIVn = (int)(12M / (57600 * 16)) - 1 = 12
tUPCLK = 13 * 16 * 10 / 12M = 0.000173
tUEXACT = 10 / 57600 = 0.0001736
UART Error = | 0. 000173 - 0. 0001736 | / 0. 0001736 = 0.345%
采用波特率為56700bps,8N1數(shù)據(jù)幀格式通信時,其錯誤容忍率小于標(biāo)準(zhǔn)的1.86%,因此可以正常工作。tUPCLK = 13 * 16 * 10 / 12M = 0.000173
tUEXACT = 10 / 57600 = 0.0001736
UART Error = | 0. 000173 - 0. 0001736 | / 0. 0001736 = 0.345%
圖2-61 MINI2440開發(fā)板串口硬件圖
UART的接口
圖2-61為MINI2440開發(fā)板引出UART串口接線圖,它采用DB9接口公頭(有接線柱的端口,只有接線孔的為母頭),其有9根信號線,UART通信過程中用到了信號線2 RSTXD0(數(shù)據(jù)發(fā)送管腳)它和串口線母頭TXDx信號線相接(x代表0號,1號,2號串口),信號3 RSRXD0(數(shù)據(jù)接收管腳)和串口線母頭RXDx相接(x代表0號,1號,2號串口),信號線5(接地管腳),信號線7 RSCTS0(數(shù)據(jù)發(fā)送流控制管腳)和串口線母頭nCTSx相接,信號線8 RSRTS0(數(shù)據(jù)接收流控制管腳)和串口線母頭nRTSx相接。如果UART中沒有開啟AFC流控的話,只要用到信號線2,信號線3和信號線5。
圖2-62 MINI2440串口管腳接線
通過MINI2440硬件CPU管腳圖可以看出,RSTXD0和RSRXD0連接到CPU的GPH2和GPH3管腳上的,而GPH2和GPH3是CPU復(fù)用管腳,因此我們要對GPH2和GPH3對應(yīng)寄存器進行設(shè)置,其對應(yīng)寄存器為GPHCON。
表2-23 GPIO端口H設(shè)置寄存器(GPHCON)
寄存器名 | 地址 | 是否讀寫 | 描述 | 復(fù)位默認(rèn)值 |
GPHCON | 0x56000070 | R/W | GPIO端口H配置寄存器 | 0x0 |
GPHDAT | 0x56000074 | R/W | GPIO端口H數(shù)據(jù)寄存器 | 未定義 |
GPHUP | 0x56000078 | R/W | GPIO端口H上拉無效寄存器 | 0x000 |
GPHCON | 位 | 描述 | 初始值 |
… | … | … | … |
GPH3 | [7:6] | 設(shè)置當(dāng)前管腳功能: 00 =輸入端口01 =輸出端口 10 = RXD[0]配置為串口0的接收數(shù)據(jù)管腳 11 =保留 | 0 |
GPH2 | [5:4] | 設(shè)置當(dāng)前管腳功能: 00 =輸入端口01 =輸出端口 10 = RXD[0]配置為串口0的接收數(shù)據(jù)管腳 11 =保留 | 0 |
… | … | … | … |
GPHCON | = 0xa0;
表2-24 GPIO端口H上拉電阻設(shè)置寄存器(GPHUP)GPHUP | 位 | 描述 | 初始值 |
GPH[10:0] | [10:0] | 設(shè)置對應(yīng)管腳GPHn的是否啟用上拉功能 0 =啟用上拉功能 1 =禁用上拉功能 | 0 |
GPHUP = 0x0;
表2-25 UART0串行控制寄存器(ULCON0)寄存器名 | 地址 | 是否讀寫 | 描述 | 復(fù)位默認(rèn)值 |
ULCON0 | 0x50000000 | R/W | 串口0串行控制寄存器 | 0x00 |
ULCON0 | 位 | 描述 | 初始值 |
保留 | [7] | 0 | |
紅外模式 | [6] | 選擇串口0是否使用紅外模式: 0 =正常通信模式 1 =紅外通信模式 | 0 |
校驗?zāi)J?/td> | [5:3] | 設(shè)置串口0在數(shù)據(jù)接收和發(fā)送時采用的校驗方式: 0xx =無校驗 100 =奇校驗 101 =偶校驗 110 =強制校驗/檢測是否為1 111 =強制校驗/檢測是否為0 | 000 |
停止位 | [2] | 設(shè)置串口0停止位數(shù): 0 =每個數(shù)據(jù)幀一個停止位 1 =每個數(shù)據(jù)幀二個停止位 | 0 |
數(shù)據(jù)位 | [1:0] | 設(shè)置串口0數(shù)據(jù)位數(shù): 00 = 5個數(shù)據(jù)位01 = 6個數(shù)據(jù)位 10 = 7個數(shù)據(jù)位11 = 8個數(shù)據(jù)位 | 00 |
我們選擇一般通信模式,無校驗位,1個停止位,8個數(shù)據(jù)位的數(shù)據(jù)通信方式。因此:
ULCON0 = 0x03;
表2-26 UART0串口控制寄存器(UCON0)寄存器名 | 地址 | 是否讀寫 | 描述 | 復(fù)位默認(rèn)值 |
UCON0 | 0x50000004 | R/W | 串口0控制寄存器 | 0x00 |
UCON0 | 位 | 描述 | 初始值 |
FCLK分頻因子 | [15:12] | 當(dāng)UART0選擇FCLK作為時鐘源時,設(shè)置其FCLK的分頻因子 UART0工作時鐘頻率= FCLK/ FCLK分頻因子+ 6 | 0000 |
UART時鐘源選擇 | [11:10] | 選擇UART0的工作時鐘PCLK,UEXTCLK,F(xiàn)CLK/n: 00,10 = PCLK 01 = UEXTCLK 11 = FCLK/n 當(dāng)選擇FCLK/n作為UART0工作時鐘時還要做其它設(shè)置,具體請讀者自行查看硬件手冊 | 00 |
發(fā)送數(shù)據(jù)中斷 產(chǎn)生類型 | [9] | 設(shè)置UART0中斷請求類型,在非FIFO傳輸模式下,一旦發(fā)送數(shù)據(jù)緩沖區(qū)為空,立即產(chǎn)生中斷信號,在FIFO傳輸模式下達到發(fā)送數(shù)據(jù)觸發(fā)條件時立即產(chǎn)生中斷信號: 0 =脈沖觸發(fā) 1 =電平觸發(fā) | 0 |
接收數(shù)據(jù)中斷 產(chǎn)生類型 | [8] | 設(shè)置UART0中斷請求類型,在非FIFO傳輸模式下,一旦接收到數(shù)據(jù),立即產(chǎn)生中斷信號,在FIFO傳輸模式下達到接收數(shù)據(jù)觸發(fā)條件時立即產(chǎn)生中斷信號: 0 =脈沖觸發(fā) 1 =電平觸發(fā) | 0 |
接收數(shù)據(jù)超時 | [7] | 設(shè)置當(dāng)接收數(shù)據(jù)時,如果數(shù)據(jù)超時,是否產(chǎn)生接收中斷: 0 =不開啟超時中斷1 =開啟超時中斷 10 = 7個數(shù)據(jù)位11 = 8個數(shù)據(jù)位 | 0 |
接收數(shù)據(jù)錯誤中斷 | [6] | 設(shè)置當(dāng)接收數(shù)據(jù)時,如果產(chǎn)生異常,如傳輸中止,幀錯誤,校驗錯誤時,是否產(chǎn)生接收狀態(tài)中斷信號: 0 =不產(chǎn)生錯誤狀態(tài)中斷1 =產(chǎn)生錯誤狀態(tài)中斷 | 0 |
回送模式 | [5] | 設(shè)置該位時UART會進入回送模式,該模式僅用于測試 0 =正常模式1 =回送模式 | 0 |
發(fā)送終止信號 | [4] | 設(shè)置該位時,UART會發(fā)送一個幀長度的終止信號,發(fā)送完畢后,該位自動恢復(fù)為0 0 =正常傳輸1 =發(fā)送終止信號 | 0 |
發(fā)送模式 | [3:2] | 設(shè)置采用哪個方式執(zhí)行數(shù)據(jù)寫入發(fā)送緩沖區(qū) 00 =無效 01 =中斷請求或查詢模式 10 = DMA0請求 | 00 |
接收模式 | [1:0] | 設(shè)置采用哪個方式執(zhí)行數(shù)據(jù)寫入接收緩沖區(qū) 00 =無效 01 =中斷請求或查詢模式 10 = DMA0請求 | 00 |
UCON0 = 0x05;
表2-27 UART FIFO控制寄存器(UFCON0)寄存器名 | 地址 | 是否讀寫 | 描述 | 復(fù)位默認(rèn)值 |
UFCON0 | 0x50000008 | R/W | 串口0 FIFO控制寄存器 | 0x00 |
UFCON0 | 位 | 描述 | 初始值 |
發(fā)送數(shù)據(jù) 觸發(fā)級別 | [7:6] | 設(shè)置FIFO發(fā)送模式的觸發(fā)級別: 00 = FIFO為空觸發(fā)01 = 16字節(jié)觸發(fā) 10 = 32字節(jié)觸發(fā)11 = 48字節(jié)觸發(fā) | 00 |
接收數(shù)據(jù) 觸發(fā)級別 | [5:4] | 設(shè)置FIFO接收模式的觸發(fā)級別: 00 = FIFO為空觸發(fā)01 = 16字節(jié)觸發(fā) 10 = 32字節(jié)觸發(fā)11 = 48字節(jié)觸發(fā) | 00 |
保留 | [3] | 0 | |
發(fā)送FIFO重置 | [2] | 在重置FIFO后自動清除發(fā)送緩沖區(qū) 0 =正常模式1 =自動清除 | 0 |
接收FIFO重置 | [1] | 在重置FIFO后自動清除接收緩沖區(qū) 0 =正常模式1 =自動清除 | 0 |
啟用FIFO | [0] | 0 =不啟用FIFO1 =啟用FIFO | 0 |
寄存器名 | 地址 | 是否讀寫 | 描述 | 復(fù)位默認(rèn)值 |
UMCON0 | 0x5000000C | R/W | 串口0MODEM控制寄存器 | 0x00 |
UMCON0 | 位 | 描述 | 初始值 |
保留 | [7:5] | 必須全部置0 | 000 |
AFC自動流控 | [4] | 0 =不開啟流控1 =開啟流控 | 0 |
保留 | [3:1] | 必須全部置0 | 000 |
請求發(fā)送 | [0] | 如果啟用AFC,該位無效,S3C2440會自動控制nRTS,如果不啟用AFC,nRTS必須由軟件控制 0 =高電平激活nRTS1 =低電平激活nRTS | 0 |
表2-29 UART發(fā)送/接收狀態(tài)寄存器(UTRSTAT0)
寄存器名 | 地址 | 是否讀寫 | 描述 | 復(fù)位默認(rèn)值 |
UTRSTAT0 | 0x50000010 | R/W | 串口0發(fā)送/接收狀態(tài)寄存器 | 0x06 |
UTRSTAT0 | 位 | 描述 | 初始值 |
發(fā)送器為空 | [2] | 當(dāng)發(fā)送緩存寄存器中沒有數(shù)據(jù)要發(fā)送且發(fā)送移位寄存器為空時,自動置1 0 =非空 1 =發(fā)送器為空(發(fā)送緩存和移位寄存器) | 1 |
發(fā)送緩存寄存器為空 | [1] | 當(dāng)發(fā)送緩存寄存器為空時,自動置1 0 =發(fā)送緩存寄存器非空 1 =發(fā)送緩存寄存器為空 | 1 |
接收緩存寄存器為空 | [0] | 當(dāng)接收緩存寄存器有數(shù)據(jù)到達時,自動置1 0 =接收緩存寄存器為空 1 =緩存寄存器接收數(shù)據(jù) | 0 |
表2-30 UART發(fā)送緩存寄存器(UTXH0)
寄存器名 | 地址 | 是否讀寫 | 描述 | 復(fù)位默認(rèn)值 |
UTXH0 | 0x50000020(L) 0x50000023(B) | W | 串口0發(fā)送緩存寄存器 | - |
表2-31 UART接收緩存寄存器(URXH0)
寄存器名 | 地址 | 是否讀寫 | 描述 | 復(fù)位默認(rèn)值 |
URXH0 | 0x50000024(L) 0x50000027(B) | R | 串口0接收緩存寄存器 | - |
寄存器名 | 地址 | 是否讀寫 | 描述 | 復(fù)位默認(rèn)值 |
UBRDIV0 | 0x50000028 | R/W | 串口0波特率除數(shù)寄存器 | - |
UBRDIV0 | 位 | 描述 | 初始值 |
波特率除數(shù) | [15:0] | 設(shè)置波特率除數(shù)(大于0)使用外部輸入時鐘時可以置0 | - |
UFCON0 = 0x00;//不使用FIFO
UMCON0 = 0x00;//不使用流控
UBRDIV0 = 26;//波特率為115200,PCLK=50Mhz
UBRDIV0 = 53;//波特率為57600,PCLK=50Mhz
UBRDIV0 = 12;//波特率為57600,PCLK=12Mhz
UTXH0和URXH0分別是數(shù)據(jù)發(fā)送和接收寄存器,發(fā)送數(shù)據(jù)時通過輪詢方式判斷發(fā)送狀態(tài)寄存器的狀態(tài),當(dāng)可以發(fā)送數(shù)據(jù)時,執(zhí)行UTXH0寄存器寫入操作,接收數(shù)據(jù)時,以輪詢方式檢測接收狀態(tài)寄存器狀態(tài),當(dāng)有數(shù)據(jù)到達時,讀取URXH0寄存器里的數(shù)據(jù)即可取得串口數(shù)據(jù)。UMCON0 = 0x00;//不使用流控
UBRDIV0 = 26;//波特率為115200,PCLK=50Mhz
UBRDIV0 = 53;//波特率為57600,PCLK=50Mhz
UBRDIV0 = 12;//波特率為57600,PCLK=12Mhz
#defineTXD0READY(1<<2)//發(fā)送數(shù)據(jù)狀態(tài)OK
#defineRXD0READY(1)//接收數(shù)據(jù)狀態(tài)OK
/* UART串口單個字符打印函數(shù)*/
extern void putc(unsigned char c)
{
while( ! (UTRSTAT0 & TXD0READY) );
UTXH0 = c;
}
/* UART串口接受單個字符函數(shù)*/
extern unsigned char getc(void)
{
while( ! (UTRSTAT0 & RXD0READY) );
return URXH0;
}
#defineRXD0READY(1)//接收數(shù)據(jù)狀態(tài)OK
/* UART串口單個字符打印函數(shù)*/
extern void putc(unsigned char c)
{
while( ! (UTRSTAT0 & TXD0READY) );
UTXH0 = c;
}
/* UART串口接受單個字符函數(shù)*/
extern unsigned char getc(void)
{
while( ! (UTRSTAT0 & RXD0READY) );
return URXH0;
}
1.1.6UART串口驅(qū)動實驗
init.s:本程序文件對看門狗,內(nèi)存等基本硬件做初始化,然后跳入到xmain.c中的xmain函數(shù)執(zhí)行。;
; UART串口實驗
;
GPBCONEQU0x56000010
GPBDATEQU0x56000014
AREA Init, CODE, READONLY
ENTRY
start
; close watchdog
ldr r0, = 0x53000000;將看門狗控制寄存器地址放入r0
mov r1, #0
str r1, [r0];設(shè)置看門狗控制寄存器的值為0
bl initmem;跳轉(zhuǎn)到initmem代碼段,初始化內(nèi)存
IMPORT xmain;引入main.c中的xmain函數(shù)
ldr sp, =0x34000000;調(diào)用C程序之前先初始化棧指針
ldr lr, =loop;設(shè)置xmain函數(shù)的返回地址
ldr pc, =xmain;跳轉(zhuǎn)到C程序中的xmain函數(shù)的入口處執(zhí)行
loop
b loop;死循環(huán)
initmem;內(nèi)存初始化
ldr r0, =0x48000000;加載內(nèi)存相關(guān)寄存器首地址r0
ldr r1, =0x48000034;加載內(nèi)存相關(guān)寄存器尾地址到r1
adr r2, memdata;將寄存器配置數(shù)據(jù)地址段首地址加載到r2
initmemloop
ldr r3, [r2], #4;循環(huán)設(shè)置存寄存器
str r3, [r0], #4
teq r0, r1
bne initmemloop;循環(huán)到最后一個寄存器時退出函數(shù)
mov pc,lr
memdata
DCD0x22000000;BWSCON
DCD0x00000700;BANKCON0
DCD0x00000700;BANKCON1
DCD0x00000700;BANKCON2
DCD0x00000700;BANKCON3
DCD0x00000700;BANKCON4
DCD0x00000700;BANKCON5
DCD0x00018005;BANKCON6
DCD0x00018005;BANKCON7
DCD0x008e07a3;REFRESH
DCD0x000000b1;BANKSIZE
DCD0x00000030;MRSRB6
DCD0x00000030;MRSRB7
END
xmain.c:uart_init函數(shù)對UART0進行初始化,然后進入死循環(huán)內(nèi),不停打印字符串“Uart串口打印試驗”。; UART串口實驗
;
GPBCONEQU0x56000010
GPBDATEQU0x56000014
AREA Init, CODE, READONLY
ENTRY
start
; close watchdog
ldr r0, = 0x53000000;將看門狗控制寄存器地址放入r0
mov r1, #0
str r1, [r0];設(shè)置看門狗控制寄存器的值為0
bl initmem;跳轉(zhuǎn)到initmem代碼段,初始化內(nèi)存
IMPORT xmain;引入main.c中的xmain函數(shù)
ldr sp, =0x34000000;調(diào)用C程序之前先初始化棧指針
ldr lr, =loop;設(shè)置xmain函數(shù)的返回地址
ldr pc, =xmain;跳轉(zhuǎn)到C程序中的xmain函數(shù)的入口處執(zhí)行
loop
b loop;死循環(huán)
initmem;內(nèi)存初始化
ldr r0, =0x48000000;加載內(nèi)存相關(guān)寄存器首地址r0
ldr r1, =0x48000034;加載內(nèi)存相關(guān)寄存器尾地址到r1
adr r2, memdata;將寄存器配置數(shù)據(jù)地址段首地址加載到r2
initmemloop
ldr r3, [r2], #4;循環(huán)設(shè)置存寄存器
str r3, [r0], #4
teq r0, r1
bne initmemloop;循環(huán)到最后一個寄存器時退出函數(shù)
mov pc,lr
memdata
DCD0x22000000;BWSCON
DCD0x00000700;BANKCON0
DCD0x00000700;BANKCON1
DCD0x00000700;BANKCON2
DCD0x00000700;BANKCON3
DCD0x00000700;BANKCON4
DCD0x00000700;BANKCON5
DCD0x00018005;BANKCON6
DCD0x00018005;BANKCON7
DCD0x008e07a3;REFRESH
DCD0x000000b1;BANKSIZE
DCD0x00000030;MRSRB6
DCD0x00000030;MRSRB7
END
/* xmain.c */
/* GPIO registers */
#defineGPHCON(*(volatile unsigned long *)0x56000070)
#defineGPHDAT(*(volatile unsigned long *)0x56000074)
#defineGPHUP(*(volatile unsigned long *)0x56000078)
/*UART registers*/
#defineULCON0(*(volatile unsigned long *)0x50000000)
#defineUCON0(*(volatile unsigned long *)0x50000004)
#defineUFCON0(*(volatile unsigned long *)0x50000008)
#defineUMCON0(*(volatile unsigned long *)0x5000000c)
#defineUTRSTAT0(*(volatile unsigned long *)0x50000010)
#defineUTXH0(*(volatile unsigned char *)0x50000020)
#defineURXH0(*(volatile unsigned char *)0x50000024)
#defineUBRDIV0(*(volatile unsigned long *)0x50000028)
#defineTXD0READY(1<<2)//發(fā)送數(shù)據(jù)狀態(tài)OK
#defineRXD0READY(1)//接收數(shù)據(jù)狀態(tài)OK
/* UART串口初始化*/
void uart_init( )
{
GPHCON |= 0xa0;//GPH2,GPH3 used as TXD0,RXD0
GPHUP= 0x0;//GPH2,GPH3內(nèi)部上拉
ULCON0= 0x03;//8N1
UCON0= 0x05;//查詢方式為輪詢或中斷;時鐘選擇為PCLK
UFCON0 = 0x00;//不使用FIFO
UMCON0 = 0x00;//不使用流控
UBRDIV0 = 12;//波特率為57600,PCLK=12Mhz
}
/* UART串口單個字符打印函數(shù)*/
extern void putc(unsigned char c)
{
while( ! (UTRSTAT0 & TXD0READY) );
UTXH0 = c;
}
/* UART串口接受單個字符函數(shù)*/
extern unsigned char getc(void)
{
while( ! (UTRSTAT0 & RXD0READY) );
return URXH0;
}
/* UART串口字符串打印函數(shù)*/
extern int printk(const char* str)
{
int i = 0;
while( str[i] ){
putc( (unsigned char) str[i++] );
}
return i;
}
__inline void delay(int msec)
{
int i, j;
for(i = 1000; i > 0; i--)
for(j = msec*10; j > 0; j--)
/* do nothing */;
}
/* xmain通過UART串口打印字符串*/
int xmain()
{
uart_init();
while(1) {
delay(10);
printk("Uart串口打印試驗/r/n");
}
return 0;
}
當(dāng)編譯并將生成Norflash,在->所有程序->通訊mini2440,在之后彈出的COM波特率1個停止位,PC串口(筆記本通常沒有串口,可以買一個Uart串口打印試驗”字符串。/* GPIO registers */
#defineGPHCON(*(volatile unsigned long *)0x56000070)
#defineGPHDAT(*(volatile unsigned long *)0x56000074)
#defineGPHUP(*(volatile unsigned long *)0x56000078)
/*UART registers*/
#defineULCON0(*(volatile unsigned long *)0x50000000)
#defineUCON0(*(volatile unsigned long *)0x50000004)
#defineUFCON0(*(volatile unsigned long *)0x50000008)
#defineUMCON0(*(volatile unsigned long *)0x5000000c)
#defineUTRSTAT0(*(volatile unsigned long *)0x50000010)
#defineUTXH0(*(volatile unsigned char *)0x50000020)
#defineURXH0(*(volatile unsigned char *)0x50000024)
#defineUBRDIV0(*(volatile unsigned long *)0x50000028)
#defineTXD0READY(1<<2)//發(fā)送數(shù)據(jù)狀態(tài)OK
#defineRXD0READY(1)//接收數(shù)據(jù)狀態(tài)OK
/* UART串口初始化*/
void uart_init( )
{
GPHCON |= 0xa0;//GPH2,GPH3 used as TXD0,RXD0
GPHUP= 0x0;//GPH2,GPH3內(nèi)部上拉
ULCON0= 0x03;//8N1
UCON0= 0x05;//查詢方式為輪詢或中斷;時鐘選擇為PCLK
UFCON0 = 0x00;//不使用FIFO
UMCON0 = 0x00;//不使用流控
UBRDIV0 = 12;//波特率為57600,PCLK=12Mhz
}
/* UART串口單個字符打印函數(shù)*/
extern void putc(unsigned char c)
{
while( ! (UTRSTAT0 & TXD0READY) );
UTXH0 = c;
}
/* UART串口接受單個字符函數(shù)*/
extern unsigned char getc(void)
{
while( ! (UTRSTAT0 & RXD0READY) );
return URXH0;
}
/* UART串口字符串打印函數(shù)*/
extern int printk(const char* str)
{
int i = 0;
while( str[i] ){
putc( (unsigned char) str[i++] );
}
return i;
}
__inline void delay(int msec)
{
int i, j;
for(i = 1000; i > 0; i--)
for(j = msec*10; j > 0; j--)
/* do nothing */;
}
/* xmain通過UART串口打印字符串*/
int xmain()
{
uart_init();
while(1) {
delay(10);
printk("Uart串口打印試驗/r/n");
}
return 0;
}
評論