S02_CH09_UART串口中斷實驗


S02_CH09_UART串口中斷實驗

本章的UART中斷將在之前PL_PS中斷和定時器中斷上推導出來,因此本章有點難度,如果前兩章還不是很熟悉的話,需要返回到前面兩章把這兩章的內容再次消化一下,再來學習本章的內容。本章的硬件工程可以直接使用定時器中斷的硬件工程,因此此次試驗就直接到SDK軟件部分。

9.1 加載到SDK

Step1:打開定時器中斷的工程。

Step2:導出硬件。

Step3:新建一個空SDK工程,並添加一個main.c的文件。

Step4:在main.c文件中添加以下程序,按Ctrl+S保存后自動開始編譯。

/*

* main.c

*

*  Created on: 2016年6月26日

*      Author: Administrator

*/

#include <stdio.h>

#include "xadcps.h"

#include "xil_types.h"

#include "Xscugic.h"

#include "Xil_exception.h"

#include "xuartps.h"

//timer info

#define UART_DEVICE_ID      XPAR_PS7_UART_1_DEVICE_ID

#define INTC_DEVICE_ID      XPAR_SCUGIC_SINGLE_DEVICE_ID

#define UART_IRPT_INTR      XPAR_XUARTPS_1_INTR

static XScuGic Intc; //GIC

static XUartPs Uart;//uart

static void UartIntrHandler(void *CallBackRef)

{

    XUartPs *InstancePtr = (XUartPs *) CallBackRef;

u32 IsrStatus;

u32 ReceivedCount=0;

u32 CsrRegister;

/*

* Read the interrupt ID register to determine which

* interrupt is active

*/

IsrStatus = XUartPs_ReadReg(InstancePtr->Config.BaseAddress,

   XUARTPS_IMR_OFFSET);//e0001000+10=regaddr=e0001010

IsrStatus &= XUartPs_ReadReg(InstancePtr->Config.BaseAddress,

   XUARTPS_ISR_OFFSET);//e0001000+14=regaddr=e0001014

/* Dispatch an appropriate handler. */

if((IsrStatus & ((u32)XUARTPS_IXR_RXOVR | (u32)XUARTPS_IXR_RXEMPTY |

(u32)XUARTPS_IXR_RXFULL)) != (u32)0) {

CsrRegister = XUartPs_ReadReg(InstancePtr->Config.BaseAddress,//判斷FIFO觸發標准位

XUARTPS_SR_OFFSET);//e0001000+2c=regaddr=e000102c

while((CsrRegister & XUARTPS_SR_RXEMPTY)== (u32)0){//讀取FIFO中所有數據

//InstancePtr->ReceiveBuffer.NextBytePtr[ReceivedCount] =//每次循環讀取1byte

;

XUartPs_WriteReg(InstancePtr->Config.BaseAddress,//每次循環發送讀取到的數據

   XUARTPS_FIFO_OFFSET,

   XUartPs_ReadReg(InstancePtr->Config.

  BaseAddress,

  XUARTPS_FIFO_OFFSET));

ReceivedCount++;//計數

CsrRegister = XUartPs_ReadReg(InstancePtr->Config.BaseAddress,

XUARTPS_SR_OFFSET);

}

}

printf("this time ReceivedCount=%d\r\n",ReceivedCount);

XUartPs_WriteReg(InstancePtr->Config.BaseAddress, XUARTPS_ISR_OFFSET,

IsrStatus);

}

void SetupInterruptSystem(XScuGic *GicInstancePtr,

XUartPs *UartInstancePtr, u16 UartIntrId)

{

        XScuGic_Config *IntcConfig; //GIC config

        Xil_ExceptionInit();

        //initialise the GIC

        IntcConfig = XScuGic_LookupConfig(INTC_DEVICE_ID);

        XScuGic_CfgInitialize(GicInstancePtr, IntcConfig,

                        IntcConfig->CpuBaseAddress);

        Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,

                    (Xil_ExceptionHandler)XScuGic_InterruptHandler,//connect to the hardware

                    GicInstancePtr);

        Xil_ExceptionEnable();

        XScuGic_Connect(GicInstancePtr, UartIntrId,

                        (Xil_InterruptHandler)UartIntrHandler,//set up the timer interrupt

                        (void *)UartInstancePtr);

        XScuGic_Enable(GicInstancePtr, UartIntrId);//enable the interrupt for the Timer at GIC

        XUartPs_SetInterruptMask(UartInstancePtr, XUARTPS_IXR_RXOVR/* | XUARTPS_IXR_TXEMPTY | XUARTPS_IXR_TNFUL*/ );

       // XUartPs_EnableUart(UartInstancePtr);//enable interrupt on the timer

        Xil_ExceptionEnableMask(XIL_EXCEPTION_IRQ); //Enable interrupts in the Processor.

    }

int main()

{

XUartPs_Config *UartConfigPtr;     //timer config

//    printf("------------START-------------\n");

     UartConfigPtr = XUartPs_LookupConfig(UART_DEVICE_ID);

     XUartPs_CfgInitialize(&Uart,UartConfigPtr,UartConfigPtr->BaseAddress);

     //set up the interrupts

     SetupInterruptSystem(&Intc,&Uart,UART_IRPT_INTR);

     while(1);

     return 0;

}

Step4:右擊工程,選擇Debug as ->Debug configuration。

Step5:選中system Debugger,雙擊創建一個系統調試。

wps7CA1.tmp

Step6:設置系統調試。

wps7CA2.tmp

打開系統自帶的窗口調試助手,點擊運行按鈕開始運行程序。

wps7CB3.tmp

系統運行結果如下圖所示:

wps7CB4.tmp

9.2 程序分析

本章的程序與之前兩章的程序都大同小異,一些函數都在我們之前兩章中看到和介紹過。

首先我們先介紹下面三個宏定義。

wps7CB5.tmp

第一個是我們的UART的設備ID,第二個是我們中斷的設備ID,第三個是UART的中斷號。

把鼠標停留在UART的中斷號上,按下F3跟蹤它,經過兩次跟蹤后,得到UART的中斷號如下圖所示:

wps7CB6.tmp

我們可以在ug585中查看一下中斷號82是否是串口中斷。

wps7CC6.tmp

可以看到,確實是串口中斷,高電平觸發。

再來看看main函數中的內容。首先依然是通過查找配置程序來獲取串口的硬件配置。我們跟蹤這個程序,看看他獲取的配置是什么。

wps7CC7.tmp

這個程序還是從一個配置表數組中查找的配置文件,繼續往下剝離,看一看這個數組中的內容。

wps7CD8.tmp

可以看到,這個數組里存放的是UART的設備ID,UART的基地址,時鍾頻率和一個不知道什么作用的對象。后兩個參數是我們沒用到的,因此就略過了。前兩個都是我們在硬件工程中添加了中斷后,系統自動生成的。

接下來還是一個熟悉的函數,對UART進行了初始化。可以看到這個函數的第一個參數指向了定義的UART指針,我們就跟蹤一下這個指針。

wps7CD9.tmp我們發現它指向了一個結構體,那么我們繼續跟蹤看看結構體中內容。

wps7CDA.tmp

這個結構體中的內容比較多,第一個對象是我們UART硬件的一些配置,它指向的是一個結構體。那么就來看看這個結構體吧。

wps7CDB.tmp

可以看到,這些就是剛才我們查找配置程序獲取到的硬件參數。

回到XUartPs結構體的分析。第二個對象是輸入時鍾頻率,第三個是設備是否初始化並准備好,第四個是波特率,第五個是兩個buffer,一個發送的一個接收的。挑選一個參看一下。

wps7CEC.tmp

接着第七個是一個Hander,第八個是一個回掉函數,最后一個是platform具體是什么意思不得而知。

回到初始化程序。我們來看看這個函數與之前有什么不同了。

wps7CED.tmp

wps7CEE.tmp

一開始是一長串的初始化,如下圖所示:

wps7CFE.tmp

接下來的這個函數是一個用於判斷芯片類型的函數。

wps7CFF.tmp

接下來,程序將Instance(也就是我們的UART硬件)的標志設置為XIL_COMPONENT_IS_READY,表明此時UART已經可以使用了。

wps7D10.tmp

接下來,程序將UART的波特率設置為了115200。

wps7D11.tmp

接下來的這一句是讀取UART的模式寄存器。

wps7D12.tmp

我們可以來看看讀取的什么內容,把鼠標停放在這個函數的上方,看到函數顯示出了這個函數的原函數。

wps7D13.tmp

與我們定時器實驗中講到的讀寫寄存器的函數差不多,第一個參數是UART的基地址,這在我們一開始的分析中就提到過,我們反回去看看UART的基地址是多少。

wps7D23.tmp

可以知道,此處的基地址為0xE000100,直接計算:E0001000+0x0004= E0001004。打開ug585查看下這個寄存器的介紹。

wps7D24.tmp

wps7D25.tmp

可以看到,這是一個UART的模式寄存器,通過這個寄存器可以設置串口的數據位寬,有無停止位和奇偶校驗位等信息。

再來看看下一句程序。這句是對剛才讀出的寄存器的一個運算。

wps7D36.tmp

首先得到方框中這三個參數的值。這里我們已經查看程序得知這三個值分別為:6,A0,38。然后進行運算:ModeRegister=E0001004 & (~(6|A0|38))=E0001004 & 11 =0。

wps7D37.tmp

接下來的這一句也是一個運算,不多講,直接運算。ModeRegister=0|(0|0|20)=20。

wps7D48.tmp

這段程序就是一個寫寄存器的功能了。看看這個函數的原函數。

wps7D49.tmp

由此得出,這個函數讀寫的地址為剛才模式寄存器的地址,寫入的數據就是運算得出的20h。參照剛才ug585里的模式寄存器說明,顯而易見,經過這段程序之后,把UART設置為了8個數據位,1個停止位和無奇偶校驗位的模式。

接下來的還有3個寫寄存器的程序,分析方法與剛才的一致。這里就只給出它們實現的功能。分別是:設置UART的RX FIFO在8bit處觸發、設置UART的超時為1(4個字符時間)、禁止所有中斷輪詢模式為默認的樣式。

回到main函數的分析當中,接下來的函數實現的是建立起中斷的功能,這個函數在我們上一章也進行過詳細的講解。這里我們關注一下下面這個函數。

wps7D4A.tmp

當我們運行XScuGic_Connect這個函數的時候,實際運行的就是這個回調函數。這個函數也是真正實現UART發送與接收功能的函數。可以看到這個程序是通過讀寫寄存器的方式來工作的,我們可以用剛才我們講到的方法對其進行分析,在程序中,我們也給出了分析的過程。大家可以認真的去看一看。

9.3 本章小結

本章主要詳細的分析了UART中斷的實現過程,通過本章,我們重點需要掌握的是怎樣分析一個問題的方法。通過這幾張中斷部分的講解,我們應該做到對中斷部分得心應手的程度。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM