×
单片机 > 单片机程序设计 > 详情

ARM的中断(S3C2440)

发布时间:2020-06-15 发布时间:
|

中断要发生需要三部分同时工作:


中断源

中断控制器

CPU使能中断

中断控制器的作用:

汇集各类中断信号并发给CPU。


中断处理过程:

1.中断控制器汇集各类中断信号并发给CPU。

2.CPU保存当前程序的运行环境(各个寄存器),调用中断服务程序ISR来处理中断

3.在ISR中通过读取中断控制器、外设相关寄存器来识别哪个中断,并处理。

4.清除中断:通过读写中断控制器和外设相关寄存器来实现。

5.最后恢复中断程序的运行环境(即2中保存的各个寄存器)。继续执行。


看一下中断控制器的内部结构框图,了解中断处理细节。

有些请求源是带sub寄存器的,有些则不带。

(1) 对于带sub寄存器的,中断源被触发之后,SUBSRCPND寄存器相应位被置1,如果没有被SUBMASK屏蔽的话,它在SRCPND的相应位也被置1,如果没有被MASK屏蔽的话或者FIQ的话,它将被进一步处理。


(2) 对于不带sub的,它在SRCPND的相应位被置1,如果没有被MASK屏蔽的话或者FIQ的话,它将被进一步处理。


(3) 对于一般中断,可能同时有几个中断被触发,未被INTMASK屏蔽的中断经比较后,选出优先级最高的中断,此中断再INTPND的相应位被置1,然后CPU进入中断模式进行处理。中断服务子程序通过读INTPND寄存器或者INTOFFSET寄存器来确定中断源。


清中断


指定中断源的中断服务程序中,必须通过清除 SRCPND 寄存器的相应位来正确的获得来自相同源的中断请求。如果从 ISR 中返回并且未清除相应位,则中断控制器的操作就好像其它中断请求已经从同一个源进入了。换句话说,如果 SRCPND 寄存器的指定位被设置为 1,其通常被认作一个有效中断请求正在等待服务。

清除相应位的时间依赖于用户的需要。如果希望收到来自相同冤源的其它有效请求,则应该首先清除相应位,并且接着使能中断。

可以通过写入一个数据到此寄存器来清除 SRCPND 寄存器的指定位。其只清除那些数据中被设置为 1 的相应位置的 SRCPND 位。那些数据中被设置为 0 的相应位置的位保持不变

就如 SRCPND 寄存器,必须在中断服务程序中清除了 SRCPND 寄存器后清除此寄存器。可以通过写入数据到此寄存器中来清除 INTPND 寄存器的指定位。只会清除数据中设置为 1 的相应 INTPND 寄存器位的位置。数据中设置为 0 的相应位的位置则保持不变。

可以通过写入数据到此寄存器来清除 SUBSRCPND 寄存器的指定位。只有数据中那些被设置为 1 的相应SUBSRCPND 寄存器的位的位置才能被清除。数据中那些被设置为 0 的相应位的位置则保持不变。

编程

对于特定的中断,不仅要设置中断控制器,还要进行其它设置。


外部中断:


设置中断源,让它能发出中断信号

设置中断控制器

设置CPU,CPSR的 I 位,是中断总开关

处理时要分辨中断源

处理完要清中断

汇编中的异常处理程序

.align 4

irq_eint:

ldr sp, =0x33d00000

/* 保护现场 */

stmdb sp!, {r0-r12,lr}

/* 处理异常 */

bl key_eint_isr

/* 恢复现场 */

ldmia sp!, {r0-r12,pc}^


相关C程序



/* 初始化中断控制器 */

void interrupt_init(void)

{


INTMSK &= ~(1<<0); /* Service available */

}


/* 初始化中断源,设置KEY为中断源 */

void key_eint_init(void)

{

GPFCON &= ~(3<<0);

GPFCON |=  (2<<0);

EXTINT0 |= (7<<0); /* 设置双边沿触发 */

}


/* 按键外部中断处理函数 */

void key_eint_isr(void)

{

/* 中断处理 */

int val = GPFDAT;

if (val & (1<<4))

{

/* 当前状态是灭 */

GPFDAT &= ~(1<<4);

}

else

{

GPFDAT |= (1<<4);

}


/* 清中断 */

SRCPND |= (1<<0);

INTPND |= (1<<0);

}


定时器中断:


设置时钟

设置初值

加载初值,启动Timer

设置自动加载

中断相关

对于定时器部分,还要参考S3C2440的定时器功能。不再细述。

具体代码如下


#include "timer.h"

extern flag;


void interrupt_init(void)

{


INTMSK &= ~(1<<10); /* Service available */

}



/* 定时器输入时钟频率 = PCLK / {预分频值+1} / {分频值} */

/* 31250 = 50000000/(99+1)/16  */

void timer_init(void)

{

TCFG0 = 99; //定时器0和1的预分频值为99

TCFG1 &= ~(0xf<<0);

TCFG1 |= (3<<0); //定时器1的分频值为1/16

TCNTB0 = 31250; //定时周期设为1s

TCON |= (1<<1); //手动更新

TCON &= ~(1<<1);

TCON |= ((1<<0) | (1<<3)); //开启自动重载,开启定时器

}


void timer_isr(void)

{

if (flag)

{

GPFDAT |= (1<<4);

GPFDAT |= (1<<5);

GPFDAT |= (1<<6);

flag = 0;

}

else

{

GPFDAT &= ~(1<<4);

GPFDAT &= ~(1<<5);

GPFDAT &= ~(1<<6);


flag = 1;

}

SRCPND |= (1<<10);

INTPND |= (1<<10);

}


关键字:ARM  中断  S3C2440 

『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
基于单片机的医院护理呼叫对讲系统设计