串口編程(UART0)之中斷方式編程
---------------------------------------------------------app
Author :tiger-john
WebSite :blog.csdn.net/tigerjb函數
Email :jibo.tiger@gmail.com測試
Update-Time : 2011年1月23日星期日ui
Tiger聲明:本人鄙視直接複製本人文章而不加出處的我的或團體,但不排斥別人轉載tiger-john的文章,只是請您註明出處並和本人聯繫或留言給我。3Qspa
---------------------------------------------------------.net
三. 中斷方式的串口編程指針
1.用中斷方式編寫串口程序由那幾部分組成orm
2.硬件上的支持blog
1>UART0 發送FIFO緩衝區
A. UART0含有1個16字節的發送FIFO緩衝區
B. U0THR是UART0發送FIFO的最高字節
C. UART的發送FIFO是一直使能的
2>UART0接收FIFO緩衝區
A. UART0含有一個16字節的接收FIFO緩衝區。
B. 軟件設置接收FIFO緩衝區的觸發字節。
3> 中斷接口:UART0的中斷接口包含中斷使能寄存器(U0IER)和中斷標識寄存器(U0IIR)。
l U0IIR:提供狀態碼用於指示一個掛起中斷的中斷源和優先級。
l U0IER能夠控制UART0的4箇中斷源。
4> UART0有4箇中斷源:
A. RLS(接收線狀態)中斷:
(1) 優先級最高
(2) 它在如下條件發生時產生錯誤
l 幀錯誤(FE)
l 溢出錯誤(OE)
l 奇偶錯誤(PE)
l 間隔中斷(BI)
注:
Ø 能夠經過查看U0LSR[4:1]中的值看到產生該中斷的錯誤條件
Ø 讀取U0LSR寄存器時清除該中斷。
B. RDA(接收數據可用)中斷:
(1)與CTI中斷並列第二優先級。
(2)在如下狀況觸發中斷:
l 當接收的有效數據到達接收FIFO設置寄存器(U0FCR)中設置的觸發點時,RDA被激活。當接收FIFO中的有效數據少於觸發點時,RDA復位。
l 中斷過程:
1> 移位寄存器(U0RSR)從RxD引腳接收串行數據後,送入接收FIFO中
2> 當接收FIFO中的有效數據數量達到預約的觸發點時,置位RDA中斷。
3> 從U0RBR寄存器中讀取FIFO中最先到達的數據,當FIFO中的有效數據小於觸發點時,清零RDA中斷。
C. CTI(字符超時指示)中斷
(1) 優先級爲2.
(2) 在如下狀況發生中斷:
l 當接收FIFO中的有效數據少於預約的觸發點數量時,若是在必定時間內仍沒有接收到新的數據,那將觸發該中斷。
(3) 上面的時間指的是:3.5~4.5個字節所須要的時間。
(4) 對接收FIFO的任何操做都會清零該中斷標誌。
(5) 中斷過程:
l 移位寄存器(U0RSR)從RxD0引腳接收串行數據後,送入接收FIFO中。
l 當接收FIFO中的有效數據少於觸發個數,但若是長時間沒有數據到達,則觸發CTI中斷。
l 從U0RBR中讀取接收FIFO中的數據,或者有新的數據送入接收FIFO,都將清零CTI中斷。
注:
Ø 3.5~4.5個字節的時間:指在串口當前的波特率下,發送3.5~4.5個字節所須要的時間。
Ø 當接收FIFO中存放多個數據,從U0RBR讀取數據,可是沒有讀完全部數據,那麼在通過3.5~4.5個字節的時間後觸發CTI中斷。
D. THRE(發送)中斷
(1) 優先級爲第三級優先級。
(2) 當FIFO爲空而且在如下狀況觸發中斷:
l 系統啓動時,雖然發送FIFO爲空,但不會產生THRE中斷。
l 在上一次發生THRE中斷後,向發送FIFO中寫入1個字節數據,將在一個字節加上一個中止位後發生THRE中斷
(because:若是發送移位寄存器爲空,那麼寫入發送FIFO的數據將直接進入發送移位寄存器。此時發送FIFO仍然爲空,若是當即產生THRE中斷,就會影響緊接着寫入發送FIFO的數據。
因此在發送完該一個字節以及一箇中止位後,才產生THRE中斷。
l 若是在發送FIFO中有過兩個字節以上的數據,可是如今發送FIFO爲空時,將當即觸發THRE中斷。
l 當THRE中斷爲當前有效的最高優先級中斷時,往U0THR寫數或者對U0IIR的讀操做,將使THRE中斷復位
咱們來看看這些中斷源與存儲器之間的關係:
注:
Ø 由上圖可知:UART0有4箇中斷源:分別是RLS(線狀態)中斷,RDA(接收數據)中斷,CTI(字符超時)中斷,THRE(發送數據)中斷。
Ø 4箇中斷源的優先級以下圖所示:
3.串口中斷接收初始化
1>串口中斷接收初始化流程
l 設置I/O引腳鏈接到UART0
l 置位除數鎖存位,配置UART0幀數據格式
l 根據波特率計算分頻值
l 設置波特率
l 清除除數鎖存位,並設置工做模式
l 使能FIFO,並設置觸發點
l 容許RBR中斷
注:咱們能夠發現與輪訓方式相比,中斷方式只是增長了使能 FIFO, 並設置中斷觸發點和容許 RBR 中斷兩步。
2>中斷串口初始化須要配置的寄存器
(與輪循方式配置方法相同的寄存器在此處不在涉及)
l U0FCR(FIFO控制寄存器):U0FCR控制UART0 Rx和Tx FIFO的操做。
l U0IER(中斷使能寄存器):U0IER用於使能4個UART0中斷源。
3>具體寄存器的配置
(1) U0FCR
A做用:控制UART0 Rx和Tx的操做。
B長度:8位寄存器。
C:每一位的含義:
l 第位:表示FIFO使能
置1:表示使能對UART0 Rx和Tx 的FIFO以及U0FCR[7:1]的訪問。
置:表示不能使用Rx和Tx的FIFO以及步能對U0FCR[7:1]的訪問。
注:該位的任何變化都將使UART0 FIFO清空。
l 第1位:表示Rx FIFO的復位。
置1:會清零UART0 RxFIFO中的全部字節並復位指針邏輯。該位自動清零。
l 第2位:表示Tx FIFO的復位。
置1:會清零UART0 TxFIFO中的全部字節並復位指針邏輯。改位自動清零。
l 第[5:3]位:保留位,用戶不能對其進行操做。從保留位讀出的值未被定義。
l 第[7:6]位:表示Rx 觸發選擇
00:觸發點爲0(默認爲1字節)
01:觸發點爲1(默認爲4字節)
10:觸發點爲2(默認爲8字節)
11: 觸發點爲3(默認爲14字節)
注:這兩個位決定在激活中斷以前,接收UART0 FIFO必須寫入個字符。
(2) U0IER(中斷使能寄存器)
A 做用:U0IER用於使能4個UART0中斷源
B 長度:8位寄存器
C每一位的含義:
l 第位:表示RBR中斷使能
置1:使能RDA中斷
置:禁止RDA中斷
注:U0IEER 第零位使能UART0接收數據可用中斷。它還控制(CTI)字符接收超時中斷。
l 第1位:表示THRE中斷使能
置1:使能THRE中斷
置:禁止THRE中斷
l 第2位:表示Rx線狀態中斷使能
置1:使能Rx線狀態中斷
置:禁止RX線狀態中斷
注:U0IER第二位使能UART0 Rx線狀態中斷。該中斷的狀態可從U0LSR[4:1]讀出
l 第[7:3]位:是保留位
注:用戶不能向其寫入1.
4>串口初始化程序:
***********************************************************
* 做者: tiger-john
* 時間: 2011年1月18日
* 名稱: UART0_Init
* 功能: UART0初始化 通信波特率115200,8位數據位, 1位中止位,無奇偶校驗
* 接收FIFO觸發點爲8字節,使能RDR(接收數據)中斷
* 入口參數: bps 串口波特率
* 出口參數: 無
****************************************************************************/
void UART0_Init(uint32 bps)
{
uint16 Fdiv;
PINSEL0 = (PINSEL0 & ~(0xf) | 0x05) ; //設置UART0的引腳
U0LCR = 0x83; //置爲除數鎖存位,進行配置
Fdiv = (Fpclk>>4)/bps;
U0DLM = Fdiv>>8;
U0DLL = Fdiv%256;
U0LCR = 0x03; //清除除數鎖存位,並設置工做模式
U0FCR = 0x81; // 使能FIFO,並設置觸發點爲8字節
U0IER = 0x01; // 容許RBR中斷,即接收中斷
}
5. 中斷初始化
先來看一下UART0和VIC之間的關係:
1>中斷初始化流程:
l 選擇中斷爲向量中斷或快速中斷
l 分配中斷通道
l 設置UART0向量地址
l 使能UART0中斷
2>關於ARM中斷編程方法和寄存器的使用在此不作涉及(若是想知道的話,能夠看這篇文章http://blog.csdn.net/tigerjb/archive/2010/11/30/6045409.aspx
3>中斷初始化程序:
/**********************************************************
* 做者: tiger-john
* 時間: 2011年1月18日
* 名稱: Interrupt_Init
* 功能: 初始化串口中斷,給串口中斷選擇爲向量中斷, 分配向量通道號1給串口
* 入口參數: 無
* 出口參數: 無
**********************************************************/
void Interrupt_Init (void)
{
VICIntSelect = 0x00000000; // 設置全部通道爲IRQ中斷
VICVectCntl1 = (0x20 | 6); // UART0中斷通道分配到IRQ slot 1
VICVectAddr1 = (uint32)UART0_Exception; // 設置UART0向量地址
VICIntEnable = 1 << 6; //使能串口中斷
}
6. 用中斷編寫接收函數
1> 中斷服務函數流程
l 清除串口中斷標識寄存器(U0IIR)
l 清除中斷標誌
l 讀取接收FIFO中的數據
2> 中斷函數服務函數中須要配置的寄存器
(1) U0IIR中斷標識寄存器。
l 第位:表示中斷掛起
置1:表示沒有掛起的中斷
置:表示至少有一箇中斷掛起
l 第[3:1]位:中斷標識,這三位表示了對應UART0 Rx FIFO的中斷。
001:表示發送中斷(THRE)
010: 表示接收數據可用中斷(RDA)
011: 表示接收線狀態中斷(RLS)
110: 表示字符超時中斷(CTI)
l 第[7:4]:是保留位
注:
1. U0IIR提供的狀態碼可用於指示一個掛起中斷的中斷源和優先級。
2. 在訪問U0IIR過程當中,中斷被凍結
3. 若是在訪問U0IIR時,產生了中斷,該中斷被記錄。在下次訪問U0IIR時能夠讀出,避免中斷的丟失。
3> 中斷服務函數程序:
/****************************************************** * * 名 稱:IRQ_UART0()
* 功 能:串口UART0中斷接收8個字節的數據
* 入口參數:無
* 出口參數:無
**********************************************************/
uint8 rcv_buf[8]; // UART0數據接收緩衝區
void __irq IRQ_UART0(void)
{ uint8 i;
uint32 data;
data = U0IIR; //清除中斷表示寄存器標誌
VICVectAddr = 0; //清除中斷
for(i=0; i<8; i++)
{
rcv_buf[i] = U0RBR; // 讀取FIFO的數據
}
}
7. 看一個總程序:
四.用中斷編寫發送函數
1.中斷初始化
同上和用中斷接收函數時的中斷初始化是同樣的
2.串口初始化
1>串口初始化流程:
l 設置I/O引腳鏈接到UART0
l 置位除數鎖存位,配置UART0幀格式
l 根據波特率計算分頻值
l 設置波特率
l 清除除數鎖存位,並設置工做模式
l 使能FIFO,並使TxFIFO復位
l 使能THRE中斷
2>串口初始化函數:
/**********************************************************
* 名稱: UART0_Init
* 功能: UART0初始化 通信波特率115200,8位數據位,1位中止位,無奇偶校驗
* 使能TxFIFO,和THRE中斷
* 入口參數: bps 串口波特率
* 出口參數: 無
**********************************************************/
void UART0_Init(uint32 bps)
{
uint16 Fdiv;
PINSEL0 = (PINSEL0 & ~(0xf) | 0x05) ; //設置UART0的引腳
U0LCR = 0x83; //置位除數鎖存位,配置UART0幀格式
Fdiv = (Fpclk>>4)/bps; //根據波特率計算分頻值
U0DLM = Fdiv>>8; //設置波特率
U0DLL = Fdiv%256;
U0LCR = 0x03; // 清除除數鎖存位,並設置工做模式
U0FCR = 0x05; // 使能TxFIFO,並使TxFIFO復位
U0IER = 0x02; // 使能THRE中斷
}
3中斷服務函數:
1>中斷服務函數流程:
l 清除串口中斷標識寄存器
l 清除中斷控制標識寄存器
2>中斷髮送服務函數程序:
/**********************************************************
* 名 稱: UART0_Exception
* 功 能: 串口發送中斷
* 入口參數: 無
* 出口參數: data 發送的數據
**********************************************************/
void __irq IRQ_UART0(void)
{
uint32 data;
data = U0IIR; //清除中斷表示寄存器標誌
VICVectAddr = 0; //清除中斷
}
4. 用串口中斷髮送函數的總程序: