【转】GD32中断按下一次却响应两次的解决

[复制链接]
2328|10
 楼主| sunmeat 发表于 2015-3-16 14:38 | 显示全部楼层 |阅读模式
今天用按键中断来控制LED灯闪烁。当时有时候经常会出现自己设置的LED闪烁是4下,但是结果却是双倍次数,8下。很不解。源代码如下。
  1. Test3_Led1(void)
  2. {
  3. int K;
  4. for(K=0;K<4;K++)
  5.   {
  6.   GPIO_SetBits(GPIOF,GPIO_Pin_6);
  7.   Mydelay_ms(1000);
  8.   GPIO_ResetBits(GPIOF, GPIO_Pin_6);
  9.   Mydelay_ms(1000);
  10. }


 楼主| sunmeat 发表于 2015-3-16 14:39 | 显示全部楼层
经过研究,发现应该是按键中断没做好,每次都产生2次的中断。这是为什么?
中断服务函数如下:
  1. void EXTI0_IRQHandler(void)
  2.   {
  3.   //if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
  4.      if (EXTI_GetITStatus( EXTI_Line0)!= RESET)
  5.       {
  6.        EXTI_ClearITPendingBit(EXTI_Line0);  //0
  7.    Led1_Flag++;//做测试用,发现每次都加了2.
  8.    Test3_Led1();
  9.    //EXTI_ClearITPendingBit(EXTI_Line0); //最好放在后面以免造成一清0后,因为按键延时又变1。
  10.       }
  11.   }
 楼主| sunmeat 发表于 2015-3-16 14:41 | 显示全部楼层
    于是我继续研究。发现原来是这样的。
    每次按键按下是一定有抖动的,抖动应该会有很多下,5下以上是很正常的。按理论上将每次抖动都会长生一个脉冲,也就是一个中断。应该会有不下于5次中断,为什么只响应2次呢。
    其实这个很简单。因为相同管脚每次中断都是相同优先级的,所以即使产生中断也不会响应。只有在第一个中断函数结束之后再来中断才会响应。虽然不响应,但是却会改变中断标志位。一定还有有人问,不是服务函数中把标志位清0了吗?但是由于单片机执行代码速度很快,你请0之后,抖动如果还在那么就还会产生中断号(虽然不响应)。只有在第一次中断结束之后,再次去查看中断号的时候才响应。(注:响应中断首先是直接给总线发命令,不需要单片机查询。因此采用中断比采用查询方式要好的多,减少了CPU的工作量。一旦中断标志位变1,而且没有优先级更高的中断在执行,那么就会响应中断服务函数)现在我们就是每次按键按下以后,虽然中断标志经过清0,但是由于抖动的存在,清0后很有可能再变1。当时不会立刻执行。只有当这个中断服务函数执行完毕才执行。所以每次都有可能调用2次中断服务函数。
 楼主| sunmeat 发表于 2015-3-16 14:41 | 显示全部楼层
    那么我们应该怎么改变呢?
    其实很简单,最好在中断服务函数开头和结尾都把中断标志位清0,那么即使第一次清0后再变1,但是第二次清0是一定会成功的。或者是一次清0,但是在清0之前先延时,确保已经没有抖动。
 楼主| sunmeat 发表于 2015-3-16 14:42 | 显示全部楼层
我是选用第一种方案。
代码如下:
  1. void EXTI0_IRQHandler(void)
  2.   {
  3.   //if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
  4.      if (EXTI_GetITStatus( EXTI_Line0)!= RESET)
  5.       {
  6. Mydelay_ms(1000);
  7.        EXTI_ClearITPendingBit(EXTI_Line0);  //0
  8.    Led1_Flag++;//做测试用,发现每次都加了2.
  9.    Test3_Led1();
  10.    //EXTI_ClearITPendingBit(EXTI_Line0); //最好放在后面以免造成一清0后,因为按键延时又变1。
  11.       }
  12.   }

这样即使有抖动每次也只会调用一次中断服务函数。
aozima 发表于 2015-3-16 15:12 | 显示全部楼层
竟然在中断IRQ里面delay
 楼主| sunmeat 发表于 2015-3-16 15:44 | 显示全部楼层
aozima 发表于 2015-3-16 15:12
竟然在中断IRQ里面delay

我也觉得这个解决办法,有点。。。那么的不靠谱,哈哈,只不过正好碰到这个问题了。
rogerllg 发表于 2015-3-17 13:26 | 显示全部楼层
太不靠谱了,当心死机~
niuyaliang 发表于 2015-3-17 15:36 | 显示全部楼层
rogerllg 发表于 2015-3-17 13:26
太不靠谱了,当心死机~

是呀,确实不靠谱滴
smilingangel 发表于 2015-3-17 21:52 | 显示全部楼层
这个是按键处理上的问题的呗。
angerbird 发表于 2015-3-22 12:39 | 显示全部楼层
这个需要对按键程序的做消振处理的。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

208

主题

2132

帖子

13

粉丝
快速回复 在线客服 返回列表 返回顶部