ARM基本接口之外部中断实验

实验名称ARM基本接口之外部中断实验

实验目的

1. 了解中断的作用;

2. 掌握嵌入式系统中断的处理流程;

3. 掌握ARM外部中断编程。

实验内容(含步骤)

1. 总体步骤:先编译,启动目标机,待显示2440后,进行创建链接,下载,运行,观察是否显示HELLOO,按下EXINT2按钮看led灯是否变换显示效果

2. 实验过程:在实验过程中,始终显示硬件连接失败,组员认为是目标机与电脑连接问题,拔了插过,但仍然不行,后来多次更换电脑连接,花费了大量时间,终于解决问题,然后在紧迫的时间内修改代码,编译,链接,下载,运行,终于成功显示效果。理解原理后,通过在主程序中运行数码管显示代码,使得宿主机能正确显示HELLOO字样,然后通过按下EXINT2按钮请求中断,执行中断服务程序,使得led灯能变换显示

3.代码如下:

/****************************************************************************/

/*实验现象: 共阳数码管显示HELLOO,触发外部中断后,led灯由奇数管亮(灭)转变为偶数管亮(灭)*/

/****************************************************************************/

 

#define U8 unsigned char

/*HELLOO的字符编码*/

unsigned char hello[6] = {

0x89, 0x86, 0xc7, 0xc7, 0xc0, 0xc0,

};

/*六个数码管只亮一个的状态编码*/

unsigned char con[6] = {

0xdf, 0xef, 0xf7, 0xfb, 0xfd, 0xfe

};

 

void myDelay(int time);

Void Delay(int time);

 

/********************************************************************

// Function name	: Isr_Init

// Description	    : 中断初始化功能

// Return type	: void

// Argument         : void

*********************************************************************/

void Isr_Init(void)

{

    pISR_UNDEF  = (unsigned)HaltUndef;

    pISR_SWI    = (unsigned)HaltSwi;

    pISR_PABORT = (unsigned)HaltPabort;

    pISR_DABORT = (unsigned)HaltDabort;

 

    rINTMOD     = 0x0;                     //中断模式设置为IRQ

    rINTMSK     = BIT_ALLMSK;              //All interrupt is masked.

    rINTSUBMSK  = BIT_SUB_ALLMSK;          //All sub-interrupt is masked.

}

 

/********************************************************************

// Function name	: Isr_Request

// Description	    : 注册中断函数(中断请求)

// Return type	: void

// Argument         : int irq_no

//                    #define IRQ_EINT0     1

//                    #define IRQ_EINT1     2

//                    #define IRQ_EINT2     3

//                    #define IRQ_EINT3     4 //**

//                    #define IRQ_EINT4_7   5

//                    #define IRQ_EINT8_23  6

//                    #define IRQ_NOTUSED6  7

//                    #define IRQ_BAT_FLT   8

//                    #define IRQ_TICK      9

//                    #define IRQ_WDT       10

//                    #define IRQ_TIMER0    11

//                    #define IRQ_TIMER1    12

//                    #define IRQ_TIMER2    13

//                    #define IRQ_TIMER3    14

//                    #define IRQ_TIMER4    15

//                    #define IRQ_UART2     16

//                    #define IRQ_LCD       17

//                    #define IRQ_DMA0      18

//                    #define IRQ_DMA1      19

//                    #define IRQ_DMA2      20

//                    #define IRQ_DMA3      21

//                    #define IRQ_SDI       22

//                    #define IRQ_SPI0      23

//                    #define IRQ_UART1     24

//                    #define IRQ_NOTUSED24 25

//                    #define IRQ_USBD      26

//                    #define IRQ_USBH      27

//                    #define IRQ_IIC       28

//                    #define IRQ_UART0     29

//                    #define IRQ_SPI1      30

//                    #define IRQ_RTC       31

//                    #define IRQ_ADC       32

// Argument         : void* irq_routine

*********************************************************************/

//第一个参数表示中断请求源, 第二个参数为该中断请求源定义的中断服务函数

void Irq_Request(int irq_no, void* irq_routine)

{

if(irq_no >= IRQ_MIN && irq_no <= IRQ_MAX)

*(unsigned int*)((irq_no - 1) * sizeof(unsigned int) + (unsigned int)(_ISR_STARTADDRESS+0x20)) = (unsigned int)irq_routine;

// _ISR_STARTADDRESS+0x20 就是跳过前面的异常向量,进入IRQ中断向量的入口

// 三级跳到指定地址,即从flash中跳到了RAM的中断入口,然后又从中断入口跳到中断//分发例程入口

}

 

/********************************************************************

// Function name	: Irq_Enable

// Description	    : 开中断

// Return type	: void

// Argument         : int irq_no

*********************************************************************/

//参数表示中断请求源,该函数使能某中断

void Irq_Enable(int irq_no)

{

if(irq_no >= IRQ_MIN && irq_no <= IRQ_MAX)

rINTMSK &= ~(1 << (irq_no - 1));//全部置零,使能中断

}

 

/********************************************************************

// Function name	: Irq_Disable

// Description	    : 关中断

// Return type	: void

// Argument         : int irq_no

*********************************************************************/

//参数表示中断请求源,该函数禁止某中断

void Irq_Disable(int irq_no)

{

if(irq_no >= IRQ_MIN && irq_no <= IRQ_MAX)

rINTMSK |= (1 << (irq_no - 1));//置1,禁止中断

}

 

/********************************************************************

// Function name	: Irq_Clear

// Description	    : 清除中断

// Return type	: void

// Argument         : int irq_no

*********************************************************************/

//参数表示中断请求源,该函数清除某中断请求

void Irq_Clear(int irq_no)

{

    rSRCPND = (1 << (irq_no - 1));//置1,将该寄存器的相应位清零

    rINTPND = (1 << (irq_no - 1));//置1,将该寄存器的相应位清零

    rINTPND;

}

 

/*****************************************************************************

// Function name	: eint2_isr

// Description	    : 主函数

// Return type	: void

// Argument         : void

*****************************************************************************/

void Main(void)

{

/* 配置系统时钟 */

    ChangeClockDivider(2,1);

    U32 mpll_val = 0 ;

    mpll_val = (92<<12)|(1<<4)|(1);

    ChangeMPllValue((mpll_val>>12)&0xff, (mpll_val>>4)&0x3f, mpll_val&3);

 

/* 中断初始化 */

    Isr_Init();

    /* 初始化端口 */

    Port_Init();

 

    /* 初始化串口 */

    Uart_Init(0,115200);

    Uart_Select(0);

 

    /* 打印提示信息 */

PRINTF("\n---外部中断测试程序---\n");

PRINTF("\n请将UART0与PC串口进行连接,然后启动超级终端程序(115200, 8, N, 1)\n");

PRINTF("\n外部中断测试开始\n");

 

/* 请求中断 */

Irq_Request(IRQ_EINT3, eint3_isr);

 

    /* 使能中断 */

    Irq_Enable(IRQ_EINT3);

 

    dither_count2 = 0;

    dither_count3 = 0;

 

    while(1){

    	int i, j;

        int flag = 1;

 

        for(j=0; ; j++)	{

            *((U8*) 0x20007000) = 0x80;

            /* 数码管从0到F依次将字符显示出来 */

            for(i=0;i<6;i++){

                /* 查表并输出数据 */

                *((U8*) 0x20007000) = con[i] ;

                *((U8*) 0x20006000) = hello[i];

                myDelay(1);

            }

            dither_count3++;

         }

    }

}

 

/*****************************************************************************

// Function name	: eint3_isr

// Description	    : EINT3中断处理程序

// Return type	: int

// Argument      : void

*****************************************************************************/

void eint3_isr(void)

{

Irq_Clear(IRQ_EINT3);//清除中断

 

    if(dither_count3 > 10)//如果count大于10,变换led显示

    {

   	dither_count3 = 0;//清零

Led_Display(nLed);//led显示

nLed = ~nLed;

}

}

实验总结

lg:在计算机组成原理和操作系统中都接触过中断,有个大概了解,但都是理论上的,通过这次外部中断实验,有种理论联系实际的感觉,想起了组成原理说过的MASK。实验中知道了注册中断,开中断,清除中断对中断寄存器INTMSK,SRCPND,INTPND的写操作,和中断执行的三级跳,对中断有了更深入的理解

zhy:这次的实验,我们组花了很多时间在设备的连接上,实际修改代码,操作比较少,所以就有了更多的时间去看代码。在代码中具体实现了中断的整个过程,用了两个重要的寄存器:中断挂起寄存器(INTPND),中断屏蔽寄存器(INTMSK),什么时候置0还是置1都是有依据的。这次的外部中断是外部通过按按钮来进行中断,并让led灯实现奇偶间断灯亮起,很有中断的感觉。

wq:以前学过的中断都是比较表面的,理解的也比较浅,通过这次的中断实验,进入到硬件底层,我们对机器内的中断过程有了更加深入的了解。以及注册中断、开中断、清除中断的具体函数实现。这次的外部中断是通过按键来中断的现行程序,使得LED灯可以变换显示。但是非常遗憾这次实验由于我们组连接机器时间过长,导致实验时间极短,并没有学得尽兴。

yy:这次实验的课题是ARM基本接口之外部中断,中断的典型步骤是:保存现场,模式切换,获取中断源,处理中断,中断返回。不得不说这次的实验较以往难度更高,代码读起来也更加晦涩难懂,也涉及到了更多关于底层的知识,但实验完成之后确实感觉对中断有了进一步的了解

cxy:这次实验的内容是中断。以前经常在操作系统和计算机组成原理上听到中断的介绍,但是一直没有真正了解过中断的具体实现。这次实验让我了解中断的具体。

猜你喜欢

转载自blog.csdn.net/cinderella___/article/details/80463817