历史上的今天
今天是:2025年03月06日(星期四)
2020年03月06日 | 【ARM裸板】按键外部中断过程及示例
2020-03-06 来源:eefocus
1.初始化
设置中断源(让它能发出中断信号)
设置中断控制器(让它能发出中断信号给CPU)
设置CPU总开关(CPSR有I位,设置总开关,使能中断)
处理时要分辨中断源
处理完要清中断

1.1 中断源
设置按键为中断源引脚
配置引脚为外部中断模式
配置中断为下降沿触发
配置外部中断MASK使能
//初始化外部中断,设置按键为中断源
void key_eint_init(void)
{
/* 引脚:GPF0、2 GPG3、11 */
/* 中断:EINT0、2 EINT11、19*/
GPFCON &= ~((3<<0) | (3<<4)); //清零
GPFCON |= ((2<<4) | (2<<0)); //设置[10],配置为外部中断
GPGCON &= ~((3<<6) | (3<<22));
GPGCON |= ((2<<6) | (2<<22)); //设置[10],配置为外部中断
/* 设置中断触发方式:双边沿触发 */
EXTINT0 |= (3<<0) | (3<<8); //配置EINT0、2
EXTINT1 |= (3<<12); //配置EINT11
EXTINT2 |= (3<<12); //配置EINT19
/* 设置外部MASK清零使能 */
EINTMASK &= ((1<<11) | (1<<19));
}

1.2 中断控制器
设置INTMASK(INTERRUPT MASK (INTMSK) REGISTER)中断屏蔽寄存器
0 = Interrupt service is available.
1 = Interrupt service is masked.
//初始化中断控制器
void interrupt_init(void)
{
INTMASK &= ~((1<<0) | (1<<2) | (1<<5));//使能中断
}

1.3 CPU使能中断
设置CPSR的I位
当设置为0时enable,设置为1时disable
mrs r0,cpsr //读出CPSR
bic r0,r0,#(1<<7) //第7位清零(IRQ)
msr cpsr,r0


1.4 start.S设置中断向量表
在0x18处调用中断服务函数
/*====================================异常向量表===========================================*/
_start:
b reset //vector 0x00: reset(0地址对应reset)
ldr pc, und_addr //vector 0x04: und (发生未定义指令异常,则进入“处理未定义异常函数”)绝对跳转,跳转至sdram中
ldr pc, swi_addr //vector 0x08: swi
b halt //vector 0x0c: prefetch aboot
b halt //vector 0x10: data aboot
b halt //vector 0x14: reserved
bl irq_addr //vector 0x18: IRQ
b halt //vector 0x1c: FIQ
irq_addr:
.word do_irq

1.5 start.S设置中断处理
执行中断处理之前,硬件会处理的事情:
1.lr_irq保存有被中断模式中的下一条即将执行的指令的地址
2.SPSR_irq保存被中断模式CPSR
3.CPSR的[M4:M0]=[10010],进入到irq模式
4.跳到0x08的模式执行程序,即跳到bl do_irq这一指令
1.5.1 设置栈
sp_irq 设置栈,因为后面函数需要栈
ldr sp, =0x33D00000
1.5.2 保存现场
在irq处理函数总有可能需要用到r0~r12,因此先保存下来
由下图可知,lr-4是异常处理完后的返回地址,也需要保存
sub lr,lr,#4
stmdb sp!, {r0-r12,lr}

1.5.3 处理中断
跳转到中断处理函数中
bl handle_irq_c
1.5.4 恢复现场
将lr的值赋给pc ,^会把spsr的值恢复到cpsr中
ldmia sp,{r0-r12,pc}^
2.中断服务函数
void handle_irq_c(void)
{
/* 1.分辨中断源 */
int bit = INTOFFSET;
/* 2.调用对应的处理函数 */
key_eint_irq(bit); //处理中断,清除外部中断标志
/* 3.清中断 :从源头开始清 */
SRCPND = (1< 2.1 分辨中断源 中断偏移寄存器 (INTERRUPT OFFSET (INTOFFSET) REGISTER) 可通过判断INTOFFEST的中的可知当前中断源 2.2 调用处理函数 该为触发外部中断,因此需要清除外部中断 EINTPEND (External Interrupt Pending Register) 清除该中断,只需要对应写1即可,又因为其发生什么中断,对应为会变成1,因此产生什么中断,只需要把该中断的EINTPEND的值写入EINTPEND /* 2.调用对应的处理函数 ,清除对应的中断*/ key_eint_irq(bit); 2.3 清中断 从源头开始清:即先清除SRCPND,再清除INTPND 它只清除SRCPND与INTPND寄存器对应于数据中设置为1的位的位置,因此清除哪一个中断,只需要对应为写1即可 SRCPND(SOURCE PENDING (SRCPND) REGISTER) INTPND(INTERRUPT PENDING (INTPND) REGISTER)



下一篇:【ARM裸板】软件中断分析及示例
史海拾趣
|
核心提示:近日美国官方公布了一段关于军用机械狗的录像,视频中机械狗展示了它惊人的活动能力和适应性,一举在互联网上造成轰动。研发公司称经过测试,该机械狗能在战场上为士兵运送弹药、食物和其他物品。 这个形似机械狗的四足机器人被命名为“ ...… 查看全部问答> |
|
我现在做的是一个windows CE下传感器的项目,其中有一个过程,是给传感器发一个读指令(16进制),然后传感器会自动返回一组数据(16进制);传感器的数据刷新是50次每秒,所以在20ms内必须主动接受数据并进行处理。这里的主动是细节上的,文章题目 ...… 查看全部问答> |
|
《evc高级编程及其应用开发》例程中这样用OnOk(),OnClose(), 为何? void CDlgSeriesSetup::OnBtnopen() { CComboBox *pCmbName = NULL; CComboBox *pCmbBaud = NULL; CComboBox *pCmbParity = NULL; &nbs ...… 查看全部问答> |
|
有哪位前辈有意出售的吗?现在我们急需这些,为明年的比赛做准备,谢谢各位了,有闲置的也有意出售的请联系qq362313998,谢谢… 查看全部问答> |




