打印
[PIC®/AVR®/dsPIC®产品]

关于中断消抖的问题

[复制链接]
3041|13
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
@子非鱼|  楼主 | 2015-11-3 16:57 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
        用一个独立按键接在外部中断0脚,想通过这个切换控制单片机的深度休眠和唤醒模式。即按一下进入休眠,再按退出休眠,再按的话又进入休眠。用的这款pic单片机(PIC24Fj128GC010)进入休眠后,只要产生了外部中断0他就会退出休眠模式,并且程序从之前停止的位置开始执行代码,而不是从复位向量处重新开始。问题来了:按开关的话他会执行休眠指令,会进入休眠,同时也是外部中断0的产生,会退出休眠,最终是无法进入休眠。有什么办法用单个按键实现 深度休眠和唤醒这一操作呢?求大神指导赐教!
沙发
ZG11211| | 2015-11-6 19:13 | 只看该作者
中断发生后,先取消中断,执行完中断程序后判断按键松开后再重新打开中断。

使用特权

评论回复
板凳
ayb_ice| | 2015-11-9 10:44 | 只看该作者
这东西平时根本不用中断,需要唤醒才开中断

使用特权

评论回复
地板
JerryWu75| | 2015-11-12 09:09 | 只看该作者
在正常运行时不允许中断,通过读取IO口状态判断是否按下按键.
如果按下按键,将CPU转入休眠时,再设置允许中断唤醒.中断唤醒后,立即禁止中断.
另外,软件中需要做滤波处理按键信息,防止误动作.

使用特权

评论回复
5
兰天白云| | 2015-11-12 10:20 | 只看该作者
按一下休眠,再按一下退出休眠,什么场合需要这个功能?能不能改成自动进入休眠,按一下退出休眠,这样好处理一些,防抖好处理,不用担心抖动又进入休眠

使用特权

评论回复
6
@子非鱼|  楼主 | 2015-11-12 12:26 | 只看该作者
兰天白云 发表于 2015-11-12 10:20
按一下休眠,再按一下退出休眠,什么场合需要这个功能?能不能改成自动进入休眠,按一下退出休眠,这样好处 ...

就相当于一键开关机啊,   按下去后 单片机机会进入休眠,但放手后由于抖动,就会有上升沿,产生中断,又会退出休眠,所以这种情况有没有好的办法解决呢?

使用特权

评论回复
7
@子非鱼|  楼主 | 2015-11-12 12:30 | 只看该作者
@子非鱼 发表于 2015-11-12 12:26
就相当于一键开关机啊,   按下去后 单片机机会进入休眠,但放手后由于抖动,就会有上升沿,产生中断,又 ...

也有自动休眠啊 ,  就像有的万用表一样,有手动开关机按钮,开机后但长时间不用,他又会自动关机,我要实现的就是这种功能啊,如果能长按进入开关机就更好了

使用特权

评论回复
8
@子非鱼|  楼主 | 2015-11-12 13:32 | 只看该作者
JerryWu75 发表于 2015-11-12 09:09
在正常运行时不允许中断,通过读取IO口状态判断是否按下按键.
如果按下按键,将CPU转入休眠时,再设置允许中断 ...

比如
if(按键)
  {
   开外部中断;
  sleep();//休眠
}
按键按下去后,会进入休眠, 但松开有时会抖动,就触发中断,只要有中断,就会退出休眠啊。何况进入休眠后程序不运行了,按键无法消抖

使用特权

评论回复
9
兰天白云| | 2015-11-12 13:37 | 只看该作者
进入休眠后设置一个计数器,松按键后抖动又进中断,在中断中查计数器,并--,如果没到0,则继续sleep,这样就不会退出休眠

使用特权

评论回复
10
@子非鱼|  楼主 | 2015-11-12 13:41 | 只看该作者
ayb_ice 发表于 2015-11-9 10:44
这东西平时根本不用中断,需要唤醒才开中断

进休眠前要开中断喽?开关按下->开中断->休眠->松开->有抖动触发中断->唤醒,最终 无法休眠!

使用特权

评论回复
11
ayb_ice| | 2015-11-12 15:15 | 只看该作者
@子非鱼 发表于 2015-11-12 13:41
进休眠前要开中断喽?开关按下->开中断->休眠->松开->有抖动触发中断->唤醒,最终 无法休眠! ...

松开再处理进入中断事项,

或者连续一段时间没有键按下进入睡眠

使用特权

评论回复
12
JerryWu75| | 2015-11-13 08:49 | 只看该作者
@子非鱼 发表于 2015-11-12 13:32
比如
if(按键)
  {

不知道你用的是GPIO的中断,还是IOC中断, 我用的是PIC12F1501,IOC中断, 中断程序做唤醒:
        if(IOCIE&&IOCIF){
               唤醒,并设置OSC;
               设置下一次进入休眠计数器,这个计数器在定时器中递减,递减到0后将CPU置入休眠;
               IOC中断设置;
              设置唤醒标志;
        }
在背景循环中扫描按键:
                /* Key scan. */
                if(ActiveKey){ //按键被按下
                     按键计数器递加;
                     设置休眠计数器;
                } else { //按键被松开,短按键
                   if(按键计数器>100){ //滤波
                      按键有效,进行相应处理;
                     设置休眠计数器;
                   }
                   清除按键计数器;
                }
我的板上就一个按键,这个按键的IOC中断唤醒CPU,在唤醒后,读取这个IO的状态做其它功能按键。

使用特权

评论回复
评分
参与人数 1威望 +1 收起 理由
fmxssh + 1 赞一个!
13
fmxssh| | 2015-11-16 14:06 | 只看该作者
JerryWu75 发表于 2015-11-13 08:49
不知道你用的是GPIO的中断,还是IOC中断, 我用的是PIC12F1501,IOC中断, 中断程序做唤醒:
        if(IOCIE&&IOCIF ...

不太懂什么叫IOC中断,我的设计就是单片机外部中断0引脚接一开关,开关接地,边沿触发中断,这应该是GPIO中断吧?
谢谢各位的帮助,我的长按开关机已经实现了,看起来比较麻烦,方法如下:
int wg_flag;//定义一个喂狗标志位
int main()
{     
  init_timer1();     //定时器1初始化
  init_int0();    //外部中断0 初始化
  deep_sleep();   //开机进入休眠
  wg_flag=1;           
  if(开关按下不足3s) wg_flag=0;   // 如果 长按不足3秒  wg=0,不喂狗,复位
                                               //如果 长按3秒  wg不变,依然为1,喂狗,不复位
while(1)
{
if(开关按下超过3S)   wg=0;   // 如果 长按3秒  wg=0,喂狗,复位,然后休眠
}
}
void  __attribute__((interrupt,no_auto_psv))  _T1Interrupt()    //定时器一中断函数  25ms中断一次
{
   if(wg_flag)   ClrWdt(); 如果Wg为真,定时执行喂狗程序,程序运行正常
}

上面的程序大概意思如下:
在配置位中打开看门狗,开机后立马进入休眠。如果长按一个开关不足三秒,喂狗标志位为0,在定时器中断服务函数中的喂狗程序不会执行,看门狗复位,程序重头执行,再次进入休眠。如果超过3S ,喂狗标志位为1,在定时器中断服务函数中的喂狗程序正常执行,所有程序正常工作,这就是长按3S开机。在主函数while(1)中,长按超过3S,喂狗标志位为0,在定时器中断服务函数中的喂狗程序不会执行,看门狗复位,程序重头执行,进入休眠,这就是这就是长按3S关机.

使用特权

评论回复
14
JerryWu75| | 2016-11-25 08:35 | 只看该作者
在PIC12F1501中有一种中断:interrupt on change,是用来捕捉GPIO管脚信号变化的中断.

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

1

主题

5

帖子

0

粉丝