新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > ARM中斷方式串口編程

        ARM中斷方式串口編程

        作者: 時間:2016-11-09 來源:網絡 收藏
        串口編程(UART0)之中斷方式

        ---------------------------------------------------------

        本文引用地址:http://www.104case.com/article/201611/317903.htm

        from:blog.csdn.net/tigerjb

        Email:jibo.tiger@gmail.com

        ---------------------------------------------------------

        三.中斷方式的串口編程

        1.用中斷方式編寫串口程序由那幾部分組成

        2.硬件上的支持

        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)。

        lU0IIR:提供狀態碼用于指示一個掛起中斷的中斷源和優先級。

        lU0IER可以控制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>中斷串口初始化需要配置的寄存器

        (與輪循方式配置方法相同的寄存器在此處不在涉及)

        lU0FCR(FIFO控制寄存器):U0FCR控制UART0 Rx和Tx FIFO的操作。

        lU0IER(中斷使能寄存器):U0IER用于使能4個UART0中斷源。

        3>具體寄存器的配置

        (1)U0FCR

        A作用:控制UART0 Rx和Tx的操作。

        B長度:8位寄存器。

        C:每一位的含義:

        l第0位:表示FIFO使能

        置1:表示使能對UART0 Rx和Tx的FIFO以及U0FCR[7:1]的訪問。

        置0:表示不能使用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第0位:表示RBR中斷使能

        置1:使能RDA中斷

        置0:禁止RDA中斷

        注:U0IEER第零位使能UART0接收數據可用中斷。它還控制(CTI)字符接收超時中斷。

        l第1位:表示THRE中斷使能

        置1:使能THRE中斷

        置0:禁止THRE中斷

        l第2位:表示Rx線狀態中斷使能

        置1:使能Rx線狀態中斷

        置0:禁止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串口波特率

        *出口參數:無

        /

        voidUART0_Init(uint32 bps)

        {

        uint16Fdiv;

        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第0位:表示中斷掛起

        置1:表示沒有掛起的中斷

        置0:表示至少有一個中斷掛起

        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個字節的數據

        *入口參數:無

        *出口參數:無

        /

        uint8rcv_buf[8];// UART0數據接收緩沖區

        void__irq IRQ_UART0(void)

        {uint8i;

        uint32 data;

        data = U0IIR;//清除中斷表示寄存器標志

        VICVectAddr = 0;//清除中斷

        for(i=0; i<8; i++)

        {

        rcv_buf[i] = U0RBR;//讀取FIFO的數據

        }

        }

        7.看一個總程序:

        view plaincopy to clipboardprint?
        1. /Copyright(c)
        2. 西安郵電學院
        3. graduateschool
        4. XNMS實驗室
        5. Author:冀博
        6. Time:2011年1月20日
        7. http://blog.csdn.net/tigerjb
        8. --------------FileInfo-------------------------------------------------------------------------------
        9. Filename:UART0_while
        10. LastmodifiedDate:2011-01-20
        11. LastVersion:1.0
        12. Descriptions:通過上位機給串口發送8字節數據,ARM2200接收到串口數據后,把數據又發送回上位機
        13. ------------------------------------------------------------------------------------------------------*/
        14. /
        15. Modifiedby:TIGER0-JOHN
        16. Modifieddate:2011-1-21
        17. Version:2.0
        18. Descriptions:測試成功
        19. 在用中斷的時候在Startup.S文件中的InitStack子程序中,修改設置
        20. 系統模式堆棧處的代碼為"MSRCPSR_c,#0x5f"
        21. 測試成功,在上面上發送16進制數時,每個之間用空格隔開
        22. 不加前綴
        23. /
        24. #include"config.h"
        25. uint8recver_buffer[8];
        26. uint8rcv_new;
        27. /
        28. *名稱:UART0_Init()
        29. *功能:UART0初始化(通訊波特率115200,8位數據位,
        30. 1位停止位,無奇偶校驗)
        31. *入口參數:bps串口波特率
        32. *出口參數:無
        33. /
        34. voidUART0_Init(uint32bps)
        35. {
        36. uint16Fdiv;
        37. PINSEL0=0x00000005;//設置串口引腳
        38. U0LCR=0x83;//置為除數鎖存位,進行配置
        39. Fdiv=(Fpclk>>4)/bps;//設置波特率
        40. U0DLM=Fdiv>>8;
        41. U0DLL=Fdiv&0xff;
        42. U0LCR=0x03;//清除除數鎖存位,并設置工作模式模式
        43. U0FCR=0x81;//使能FIFO,并設置觸發點為8字節
        44. U0IER=0x01;//允許RBR中斷,即接收中斷
        45. }
        46. /*
        47. *名稱:IRQ_UART0
        48. *功能:串口UART0中斷接收8個字節的數據
        49. *入口參數:無
        50. *出口參數:無
        51. /
        52. void__irqIRQ_UART0(void)
        53. {uint8i;
        54. if(0x04==(U0IIR&0x0F))
        55. {
        56. rcv_new=1;//設置接收到新的數據標志,并清除中斷標志位
        57. for(i=0;i<8;i++)
        58. {
        59. recver_buffer[i]=U0RBR;//讀取FIFO的數據
        60. }
        61. VICVectAddr=0;
        62. }//清除中斷
        63. }
        64. /
        65. *名稱:Interrupt_Init
        66. *功能:初始化串口中斷,給串口中斷選擇為向量中斷,
        67. *分配向量通道號1給串口
        68. *入口參數:無
        69. *出口參數:無
        70. /
        71. voidInterrupt_Init(void)
        72. {
        73. VICIntSelect=0x00000000;//設置所有通道為IRQ中斷
        74. VICVectCntl0=0x26;//UART0中斷通道分配到IRQslot0,即優先級最高
        75. VICVectAddr0=(int)IRQ_UART0;//設置UART0向量地址
        76. VICIntEnable=0x00000040;//使能UART0中斷
        77. }
        78. /
        79. *名稱:UART0_SendByte
        80. *功能:向串口發送字節數據,并等待發送完畢。
        81. *入口參數:data要發送的數據
        82. *出口參數:無
        83. /
        84. voidUART0_SendByte(uint8data)
        85. {
        86. U0THR=data;
        87. while(0==(U0LSR&0x40));
        88. }
        89. /
        90. *名稱:UART0_SendBuf()
        91. *功能:通過串口發送一幀數據
        92. *入口參數:*buffer存放一幀數據
        93. *出口參數:無
        94. /
        95. voidUART0_SendBuf(uint8*buffer)
        96. {
        97. uint8*pbuffer;
        98. uint8i;
        99. for(pbuffer=buffer,i=0;i<8;i++)
        100. UART0_SendByte(*(pbuffer++));
        101. }
        102. /
        103. *名稱:main()函數
        104. *功能:上位機接收的數據開頭兩個字符為0x10,0x11,
        105. *則原樣輸出,否次輸出0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27
        106. *入口參數:*buffer存放一幀數據
        107. *出口參數:無
        108. /
        109. intmain(void)
        110. {
        111. uint8send_buffer[8]={0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27};//定義發送幀緩沖區
        112. UART0_Init(115200);
        113. Interrupt_Init();
        114. while(1)
        115. {
        116. if(1==rcv_new)//是否已經接收到8Bytes的數據
        117. {
        118. rcv_new=0;//清除標志
        119. if(0x10==recver_buffer[0]&&0x11==recver_buffer[1])
        120. {
        121. UART0_SendBuf(send_buffer);
        122. }
        123. else
        124. {
        125. UART0_SendBuf(recver_buffer);
        126. }
        127. }
        128. }
        129. return0;
        130. }
        131. /*
        132. EndOfFile
        133. /

        四.用中斷編寫發送函數

        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串口波特率

        *出口參數:無

        /

        voidUART0_Init(uint32 bps)

        {

        uint16Fdiv;

        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.用串口中斷發送函數的總程序:

        view plaincopy to clipboardprint?
        1. /Copyright(c)
        2. 西安郵電學院
        3. graduateschool
        4. XNMS實驗室
        5. Author:冀博
        6. Time:2011年1月20日
        7. http://blog.csdn.net/tigerjb
        8. --------------FileInfo-------------------------------------------------------------------------------
        9. Filename:UART0_while
        10. LastmodifiedDate:2011-01-20
        11. LastVersion:1.0
        12. Descriptions:通過上位機給串口發送8字節數據,ARM2200接收到串口數據后,用中斷方式把數據又發送回上位機
        13. ------------------------------------------------------------------------------------------------------*/
        14. /
        15. Modifiedby:TIGER0-JOHN
        16. Modifieddate:2011-1-21
        17. Version:2.0
        18. Descriptions:測試成功
        19. 在用中斷的時候在Startup.S文件中的InitStack子程序中,修改設置
        20. 系統模式堆棧處的代碼為"MSRCPSR_c,#0x5f"
        21. 測試成功,在上面上發送16進制數時,每個之間用空格隔開
        22. 不加前綴
        23. /
        24. #include"config.h"
        25. uint8recver_buffer[8];
        26. uint8rcv_new;
        27. /
        28. *名稱:UART0_Init
        29. *功能:UART0初始化通訊波特率115200,8位數據位,1位停止位,無奇偶校驗
        30. *使能TxFIFO,和THRE中斷
        31. *入口參數:bps串口波特率
        32. *出口參數:無
        33. /
        34. voidUART0_Init(uint32bps)
        35. {
        36. uint16Fdiv;
        37. PINSEL0=(PINSEL0&~(0xf)|0x05);//設置UART0的引腳
        38. U0LCR=0x83;//置位除數鎖存位,配置UART0幀格式
        39. Fdiv=(Fpclk>>4)/bps;//根據波特率計算分頻值
        40. U0DLM=Fdiv>>8;//設置波特率
        41. U0DLL=Fdiv%256;
        42. U0LCR=0x03;//清除除數鎖存位,并設置工作模式
        43. U0FCR=0x05;//使能TxFIFO,并使TxFIFO復位
        44. U0IER=0x02;//使能THRE中斷
        45. }
        46. /
        47. *名稱:UART0_Exception
        48. *功能:串口發送中斷
        49. *入口參數:無
        50. *出口參數:data發送的數據
        51. /
        52. void__irqIRQ_UART0(void)
        53. {
        54. uint32data;
        55. data=U0IIR;//清除中斷表示寄存器標志
        56. VICVectAddr=0;//清除中斷
        57. }
        58. /
        59. *名稱:Interrupt_Init
        60. *功能:初始化串口中斷,給串口中斷選擇為向量中斷,
        61. *分配向量通道號1給串口
        62. *入口參數:無
        63. *出口參數:無
        64. /
        65. voidInterrupt_Init(void)
        66. {
        67. VICIntSelect=0x00000000;//設置所有通道為IRQ中斷
        68. VICVectCntl0=0x26;//UART0中斷通道分配到IRQslot0,即優先級最高
        69. VICVectAddr0=(int)IRQ_UART0;//設置UART0向量地址
        70. VICIntEnable=0x00000040;//使能UART0中斷
        71. }
        72. /
        73. *名稱:UART0_RcvByte
        74. *功能:用查詢方式接收一字節的數據
        75. *入口參數:無
        76. *出口參數:data要接收的數據
        77. /
        78. uint8UART0_RcvByte(void)
        79. {
        80. uint8rcv_data;
        81. while((U0LSR&0X01)==0);//等待數據到達
        82. rcv_data=U0RBR;//從U0RBR中讀出接收到的數據
        83. returnrcv_data;//返回接收到的數據
        84. }
        85. /
        86. *名稱:UART0_RecBuf()
        87. *功能:接收串口發送過來的幀數據,
        88. *入口參數:*buffer存放一幀數據
        89. *出口參數:無
        90. /
        91. voidUART0_RecBuf(uint8*buffer)
        92. {
        93. uint8*pbuffer;
        94. uint8i;
        95. for(pbuffer=buffer,i=0;i<8;i++)
        96. {
        97. *(pbuffer++)=UART0_RcvByte();
        98. }
        99. }
        100. /
        101. *名稱:main()函數
        102. *功能:上位機接收的數據開頭兩個字符為0x10,0x11,
        103. *則原樣輸出,否次輸出0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27
        104. *入口參數:*buffer存放一幀數據
        105. *出口參數:無
        106. /
        107. intmain(void)
        108. {
        109. uint8i;
        110. uint8send_buffer[8]={0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27};//定義發送幀緩沖區
        111. UART0_Init(115200);
        112. Interrupt_Init();
        113. while(1)
        114. {
        115. UART0_RecBuf(recver_buffer);//接收8字節數據
        116. if(0x10==recver_buffer[0]&&0x11==recver_buffer[1])
        117. {
        118. for(i=0;i<8;i++)
        119. {
        120. U0THR=send_buffer[i];//用中斷發送每次8字節
        121. }
        122. }
        123. else
        124. {
        125. for(i=0;i<8;i++)//用中斷發送每次8字節
        126. {
        127. U0THR=recver_buffer[i];
        128. }
        129. }
        130. }
        131. return0;
        132. }
        133. /*
        134. EndOfFile
        135. /



        評論


        技術專區

        關閉
        主站蜘蛛池模板: 庐江县| 德安县| 同江市| 湘潭县| 界首市| 潢川县| 红桥区| 中方县| 东乡族自治县| 永兴县| 丁青县| 榆中县| 永登县| 若尔盖县| 疏附县| 丰宁| 泾川县| 利川市| 辽源市| 黑龙江省| 武清区| 尼木县| 吉木萨尔县| 夹江县| 平和县| 察哈| 湖北省| 甘孜| 溧水县| 澄城县| 江山市| 嘉义县| 罗源县| 蒙自县| 宣化县| 泰来县| 双峰县| 和平县| 天柱县| 吐鲁番市| 长治县|