相关码如下:
/* 初始化按键, 设为中断源 */
void key_eint_init(void)
{
/* 配置GPIO为中断引脚 */
GPFCON &= ~((3<<0) | (3<<4));
GPFCON |= ((2<<0) | (2<<4)); /* S2,S3被配置为中断引脚 */
GPGCON &= ~((3<<6) | (3<<22));
GPGCON |= ((2<<6) | (2<<22)); /* S4,S5被配置为中断引脚 */
/* 设置中断触发方式: 双边沿触发 */
EXTINT0 |= (7<<0) | (7<<8); /* S2,S3 */
EXTINT1 |= (7<<12); /* S4 */
EXTINT2 |= (7<<12); /* S5 */
/* 设置EINTMASK使能eint11,19 */
EINTMASK &= ~((1<<11) | (1<<19));
}
根据下图进行相关的配置
相关代码如下:
/* SRCPND 用来显示哪个中断产生了, 需要清除对应位
* bit0-eint0
* bit2-eint2
* bit5-eint8_23
*/
/* INTMSK 用来屏蔽中断, 1-masked
* bit0-eint0
* bit2-eint2
* bit5-eint8_23
*/
/* INTPND 用来显示当前优先级最高的、正在发生的中断, 需要清除对应位
* bit0-eint0
* bit2-eint2
* bit5-eint8_23
*/
/* INTOFFSET : 用来显示INTPND中哪一位被设置为1
*/
/* 初始化中断控制器 */
void interrupt_init(void)
{
INTMSK &= ~((1<<0) | (1<<2) | (1<<5));
}
相关代码如下:
mrs r0, cpsr /* 读出cpsr */
bic r0, r0, #0xf /* 修改M4-M0为0b10000, 进入usr模式 */
bic r0, r0, #(1<<7) /* 清除I位, 使能中断 */
msr cpsr, r0
读取INTOFFSET寄存器,表示INTPND中的值哪一位被设置为1
0-eint0
2-eint2
5-eint8-23
清中断时想EINTPND写入1清除对应的中断(读的时候1表示中断发生,写入1清除中断,很奇怪,2440手册上是这么描述的,见下图)
相关代码如下:
void key_eint_irq(int irq)
{
unsigned int val = EINTPEND;
unsigned int val1 = GPFDAT;
unsigned int val2 = GPGDAT;
if (irq == 0) /* eint0 : s2 控制 D12 */
{
...
}
else if (irq == 2) /* eint2 : s3 控制 D11 */
{
...
}
else if (irq == 5) /* eint8_23, eint11--s4 控制 D10, eint19---s5 控制所有LED */
{
if (val & (1<<11)) /* eint11 */
{
...
}
else if (val & (1<<19)) /* eint19 */
{
...
}
}
EINTPEND = val;
}
清除中断时从前向后清,即先清SRCPND,再清INTPND。否则前面的还会影响后面
相关代码如下:
void handle_irq_c(void)
{
/* 分辨中断源 */
int bit = INTOFFSET;
/* 调用对应的处理函数 */
if (bit == 0 || bit == 2 || bit == 5) /* eint0,2,eint8_23 */
{
key_eint_irq(bit); /* 处理中断, 清中断源EINTPEND */
}
/* 清中断 : 从源头开始清 */
SRCPND = (1<
interrupt.c文件代码如下
#include "s3c2440_soc.h"
/* SRCPND 用来显示哪个中断产生了, 需要清除对应位
* bit0-eint0
* bit2-eint2
* bit5-eint8_23
*/
/* INTMSK 用来屏蔽中断, 1-masked
* bit0-eint0
* bit2-eint2
* bit5-eint8_23
*/
/* INTPND 用来显示当前优先级最高的、正在发生的中断, 需要清除对应位
* bit0-eint0
* bit2-eint2
* bit5-eint8_23
*/
/* INTOFFSET : 用来显示INTPND中哪一位被设置为1
*/
/* 初始化中断控制器 */
void interrupt_init(void)
{
INTMSK &= ~((1<<0) | (1<<2) | (1<<5));
}
/* 初始化按键, 设为中断源 */
void key_eint_init(void)
{
/* 配置GPIO为中断引脚 */
GPFCON &= ~((3<<0) | (3<<4));
GPFCON |= ((2<<0) | (2<<4)); /* S2,S3被配置为中断引脚 */
GPGCON &= ~((3<<6) | (3<<22));
GPGCON |= ((2<<6) | (2<<22)); /* S4,S5被配置为中断引脚 */
/* 设置中断触发方式: 双边沿触发 */
EXTINT0 |= (7<<0) | (7<<8); /* S2,S3 */
EXTINT1 |= (7<<12); /* S4 */
EXTINT2 |= (7<<12); /* S5 */
/* 设置EINTMASK使能eint11,19 */
EINTMASK &= ~((1<<11) | (1<<19));
}
/* 读EINTPEND分辨率哪个EINT产生(eint4~23)
* 清除中断时, 写EINTPEND的相应位
*/
void key_eint_irq(int irq)
{
unsigned int val = EINTPEND;
unsigned int val1 = GPFDAT;
unsigned int val2 = GPGDAT;
if (irq == 0) /* eint0 : s2 控制 D12 */
{
if (val1 & (1<<0)) /* s2 --> gpf6 */
{
/* 松开 */
GPFDAT |= (1<<6);
}
else
{
/* 按下 */
GPFDAT &= ~(1<<6);
}
}
else if (irq == 2) /* eint2 : s3 控制 D11 */
{
if (val1 & (1<<2)) /* s3 --> gpf5 */
{
/* 松开 */
GPFDAT |= (1<<5);
}
else
{
/* 按下 */
GPFDAT &= ~(1<<5);
}
}
else if (irq == 5) /* eint8_23, eint11--s4 控制 D10, eint19---s5 控制所有LED */
{
if (val & (1<<11)) /* eint11 */
{
if (val2 & (1<<3)) /* s4 --> gpf4 */
{
/* 松开 */
GPFDAT |= (1<<4);
}
else
{
/* 按下 */
GPFDAT &= ~(1<<4);
}
}
else if (val & (1<<19)) /* eint19 */
{
if (val2 & (1<<11))
{
/* 松开 */
/* 熄灭所有LED */
GPFDAT |= ((1<<4) | (1<<5) | (1<<6));
}
else
{
/* 按下: 点亮所有LED */
GPFDAT &= ~((1<<4) | (1<<5) | (1<<6));
}
}
}
EINTPEND = val;
}
void handle_irq_c(void)
{
/* 分辨中断源 */
int bit = INTOFFSET;
/* 调用对应的处理函数 */
if (bit == 0 || bit == 2 || bit == 5) /* eint0,2,eint8_23 */
{
key_eint_irq(bit); /* 处理中断, 清中断源EINTPEND */
}
/* 清中断 : 从源头开始清 */
SRCPND = (1<
/* timer.c */
#include "s3c2440_soc.h"
void TimerFunc(int irq)
{
static int cnt = 3;
#if 0
if (GPFDAT & (1 << 4))
GPFDAT &= ~(1 << 4);
else
GPFDAT |= (1 << 4);
#endif
cnt++;
GPFDAT &= ~(1 << cnt);
if (cnt == 7)
{
cnt = 3;
GPFDAT |= (0x7 << 4);
}
}
void TimerInit(void)
{
/* 1.Set clock */
/*
* Timer input clock Frequency = PCLK / {prescaler value+1} / {divider value}
* = 50000000 / (99 + 1) / 16
* = 31250
*/
TCFG0 = 99; /* Prescaler 0 = 99 */
TCFG1 |= 0x3; /* divider value = 16 */
/* 2.Set TCNTn init val */
TCNTB0 = 15625; /* 0.5s */
/* 3.Load init val*/
TCON |= (1 << 1);
/* 4.Set Auto update, and start timer */
TCON &= ~(1 << 1);
TCON |= (1 << 0) | (1 << 3);
/* timer0的中断号是10 */
register_irq(10, TimerFunc);
}
/* interrupt.c */
#include "s3c2440_soc.h"
#include "interrupt.h"
void handle_irq(void)
{
/* 1.Resolved interrupt source */
int bit = INTOFFSET;
/* 2.handle irq */
irq_arr[bit](bit);
/* 3.clear irq */
SRCPND = (1 << bit);
INTPND = (1 << bit);
}
/* 以中断号为下标放到irq_arr指针数组中去 */
void register_irq(int irq, irq_func func)
{
irq_arr[irq] = func;
INTMSK &= ~(1 << irq);
}