alexbird 发表于 2011-12-26 10:47:12

求教按键中断方式去抖方法

问题:按键中断抖动厉害,按一次出几十个中断,导致栈溢出。
背景:nano2410板,4个按键接EINT0-3,ucosii中写了按键中断处理程序,只是简单地打印而已。ucosii的中断处理方式是进中断就保存LR和SPSR,然后切回SVC下处理,堆栈都是在SVC的SP里(就是在进程空间里),最后出中断时:
ldmfd sp!, {r0,r1} ;实际是pop出中断前的cpsr和spsr,r0=spsr r1=cpsr
msr spsr_all, r0
msr cpsr_all, r1
ldmfd sp!, {r0-r12, lr, pc}
也就是先恢复进程中断前的cpsr,再将所有寄存器出栈,pc回到中断前;这种写法是参考了《ARM中断处理的安全性与高效性研究》中带任务切换的非嵌套中断处理方式,目的是在进中断时就将所有寄存器等存在进程空间,这样任务切换时就不会再出IRQ栈再入SVC栈了,因为SVC中已经保存好了各寄存器,只要直接保存SP到TCB里就行了。省2次出入栈。

这样在恢复cpsr后和所有寄存器出栈前,打开了I位,允许中断,这里如果有大量中断涌入,会导致实际的堆栈嵌套,一层嵌套就要占近20个字,普通进程栈我才定义512个字,所以20多次后溢出崩溃,通过UART输入也确实看到在按下按键后,打印了20多次按键中断输出,然后挂掉

我想解决方法有两方面:
一、中断恢复cpsr方式
1。改中断处理方式,恢复成普通的进IRQ处理,用ldmfd sp!, {r0-r12,lr,pc}^来出栈并同时恢复cpsr,确保即使中断非常多,堆栈也不会嵌套,但这并不能解决按键中断抖动,按一次几十个中断的问题;而且中断中发生任务切换时效率低了
2。改CPSR恢复方式,保持现中断处理不变,而是将保存的cpsr装入spsr中,用ldmfd sp!, {r0-r12, lr, pc}^出栈同时恢复cpsr,保持了中断中切换效率,但破坏了任务中的spsr寄存器内容。(不过任务中的spsr应该没用吧)。但是,依然没解决抖动问题。
二、按键去抖
1。建一个按键驱动任务,平时等待信号量,发生中断后屏蔽相应按键的INTMSK,置信号量,唤醒驱动任务后执行相应的按键处理
2。占用一个定时器,中断后开定时器,屏蔽相应按键的INTMSK,定时器中断后执行按键处理
不过这两种方法都只能响应第一次中断,如果是电路异常跳了一下,系统就会当成是一次按键,无法做到轮询式的延时几十ms后读按键状态,如果依然按下再执行按键处理。

还请指点

alexbird 发表于 2011-12-30 13:34:36

审核通过,感谢莫版

顶一下,盼解答

源代码在另一个贴子里 http://www.ourdev.cn/bbs/bbs_content.jsp?bbs_sn=5315662&bbs_page_no=1&search_mode=3&search_text=alexbird&bbs_id=9999

编译前要去掉gui的一些测试调用
页: [1]
查看完整版本: 求教按键中断方式去抖方法