OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 3595|回复: 13

按键中断,主优先级相同,副优先级不同。当第一个中断响应过程中,来了第二个中断,有响应完第一个中断后,第二个中断不响应...

[复制链接]

5

主题

17

帖子

0

精华

新手上路

积分
46
金钱
46
注册时间
2018-7-26
在线时间
11 小时
发表于 2018-7-26 07:22:38 | 显示全部楼层 |阅读模式
当前发现一个想不通的问题。
按键0、按键1,按键WK_UP的主优先级相同,副优先级不同分别是1,2,3。
每个按键的中断函数处理时长约10秒左右。按键中断函数可以从灯闪的不同效果看出。
当按键0中断处理约2秒后,按下按键1,过两秒后再按按键2。按键0的中断函数处理完毕,程序没有继续处理按键1和按键WK_UP的中断。

当重新设定中断分组,按键0、1、WK_UP,主优先级为1、2、3,副优先级相同。
先按下按键WK_UP,两秒后按下按键1 ,继续两秒后按下按键0,程序能形成嵌套。正常。

求指导。程序见附件。

#include "exti.h"

#include "bsp_key.h"
#include "bsp_led.h"
#include "delay.h"

u8 extern KEY_NUM;

//按键中断初始化函数
void EXTIX_Init(void)
{       
  EXTI_InitTypeDef EXTI_InitStructure;
  NVIC_InitTypeDef NVIC_InitStructure;

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);//外部中断,需要使能AFIO时钟       

  Key_Init( );       

/*---------------------------配置KEY0------------------------------*/       
/* 选择EXTI的信号源 */
  GPIO_EXTILineConfig(KEY0_EXTI_PORTSOURCE, KEY0_EXTI_PINSOURCE);
  EXTI_InitStructure.EXTI_Line = KEY0_EXTI_LINE;
       
        /* EXTI为中断模式 */
  EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
        /* 下降沿中断 */
  EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
  /* 使能中断 */       
  EXTI_InitStructure.EXTI_LineCmd = ENABLE;
  EXTI_Init(&EXTI_InitStructure);
       
/*---------------------------配置KEY1------------------------------*/       
        /* 选择EXTI的信号源 */
  GPIO_EXTILineConfig(KEY1_EXTI_PORTSOURCE, KEY1_EXTI_PINSOURCE);
  EXTI_InitStructure.EXTI_Line = KEY1_EXTI_LINE;
       
        /* EXTI为中断模式 */
  EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
        /* 下降沿中断 */
  EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
  /* 使能中断 */       
  EXTI_InitStructure.EXTI_LineCmd = ENABLE;
  EXTI_Init(&EXTI_InitStructure);       

/*---------------------------配置WK_UP------------------------------*/       
  /* 选择EXTI的信号源 */
  GPIO_EXTILineConfig(WK_UP_EXTI_PORTSOURCE, WK_UP_EXTI_PINSOURCE);
  EXTI_InitStructure.EXTI_Line = WK_UP_EXTI_LINE;
       
        /* EXTI为中断模式 */
  EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
        /* 上升沿中断 */
  EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
  /* 使能中断 */       
  EXTI_InitStructure.EXTI_LineCmd = ENABLE;
  EXTI_Init(&EXTI_InitStructure);




/*---------------------------配置KEY0 优先级 高------------------------------*/
    /* 配置NVIC为优先级组1 */
  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);

  /* 配置中断源:按键KEY0 */
  NVIC_InitStructure.NVIC_IRQChannel = KEY0_EXTI_IRQ;
  /* 配置抢占优先级 */
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
  /* 配置子优先级 */
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
  /* 使能中断通道 */
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);

/*---------------------------配置KEY1 优先级 中------------------------------*/
  /* 配置NVIC为优先级组1 */
  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);       
  /* 配置中断源:按键KEY1,其他使用上面相关配置 */  
  NVIC_InitStructure.NVIC_IRQChannel = KEY1_EXTI_IRQ;
  /* 配置抢占优先级 */
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
  /* 配置子优先级 */
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
  /* 使能中断通道 */
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);


/*---------------------------配置WK_UP 优先级 低------------------------------*/
  /* 配置NVIC为优先级组1 */
  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);  
  /* 配置中断源:按键WK_UP,其他使用上面相关配置 */  
  NVIC_InitStructure.NVIC_IRQChannel = WK_UP_EXTI_IRQ;
  /* 配置抢占优先级 */
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority =1;
  /* 配置子优先级 */
  NVIC_InitStructure.NVIC_IRQChannelSubPriority =3;
  /* 使能中断通道 */
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);       
}


//按键中断服务函数   优先级高中低 KEY0\ KEY1 \WK_UP
void KEY0_IRQHandler(void)
{       
        u8 i=20;
       
        delay_ms(10);   //消抖                         
        if(KEY0==0)       
    {
     while(i--)
     {
            delay_ms(200);
            LED1=ON;LED0=OFF;
            delay_ms(200);
            LED1=OFF;LED0=ON;

      }
      LED1=OFF;LED0=OFF;
        }

         EXTI_ClearITPendingBit(EXTI_Line5);    //清除LINE5上的中断标志位

}


void KEY1_IRQHandler(void)
{  u32 i=30;
  delay_ms(10);    //消抖                         
  if(KEY1==0)       
    {   
       while(i--)
       {
                LED1=ON;LED0=ON;delay_ms(400);
        }
        LED1=OFF;LED0=OFF;
        }   
         EXTI_ClearITPendingBit(EXTI_Line15);  //清除LINE15线路挂起位

}

void  WK_UP_IRQHandler(void)
{
    u8 i=10;
    delay_ms(10);    //消抖
        if(WK_UP==1)
        {       
       while(i--)
       {

            delay_ms(1000);
            LED1=ON;LED0=ON;
            delay_ms(1000);
            LED1=OFF;LED0=OFF;

       }
         LED1=OFF;LED0=OFF;   
        }   
        EXTI_ClearITPendingBit(EXTI_Line0);  //清除EXTI0线路挂起位

}

按键控制led-中断.zip

370.15 KB, 下载次数: 88

正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

13

主题

71

帖子

0

精华

高级会员

Rank: 4

积分
696
金钱
696
注册时间
2017-8-14
在线时间
131 小时
发表于 2018-7-26 08:38:09 | 显示全部楼层

回帖奖励 +10 金钱

请看第二条
优先级.png
yi?我的二哈哪去了
回复 支持 反对

使用道具 举报

31

主题

1955

帖子

3

精华

论坛元老

Rank: 8Rank: 8

积分
4521
金钱
4521
注册时间
2018-5-11
在线时间
946 小时
发表于 2018-7-26 08:44:41 | 显示全部楼层
本帖最后由 warship 于 2018-7-26 08:45 编辑

别的不说,中断服务时间10秒先改了再说,10秒对mcu来说已经是天文数字了
我的开源链接 https://github.com/ShuifaHe/STM32.git  请关注,点赞支持哦。
回复 支持 反对

使用道具 举报

5

主题

17

帖子

0

精华

新手上路

积分
46
金钱
46
注册时间
2018-7-26
在线时间
11 小时
 楼主| 发表于 2018-7-26 08:54:43 | 显示全部楼层

7和3是不可以相互打断。中断7>中断3。1)在中断7执行中断函数过程中,如果来了中断3,那么中断7继续执行直到完毕,然后执行任务队列的中断3的中断服务函数。2)中断3在执行中断服务函数过程中,如果来了中断7,中断3继续执行直到完毕,然后执行任务队列的中断7服务函数。按道理是这样吧。但我的程序并没有执行后面来的任务队列里的中断函数。
回复 支持 反对

使用道具 举报

5

主题

17

帖子

0

精华

新手上路

积分
46
金钱
46
注册时间
2018-7-26
在线时间
11 小时
 楼主| 发表于 2018-7-26 08:56:18 | 显示全部楼层
warship 发表于 2018-7-26 08:44
别的不说,中断服务时间10秒先改了再说,10秒对mcu来说已经是天文数字了

10秒是为了服务函数的灯的闪烁效果。不然看不出来
回复 支持 反对

使用道具 举报

5

主题

17

帖子

0

精华

新手上路

积分
46
金钱
46
注册时间
2018-7-26
在线时间
11 小时
 楼主| 发表于 2018-7-26 08:58:23 | 显示全部楼层
warship 发表于 2018-7-26 08:44
别的不说,中断服务时间10秒先改了再说,10秒对mcu来说已经是天文数字了

谢谢提醒这个
回复 支持 反对

使用道具 举报

31

主题

1955

帖子

3

精华

论坛元老

Rank: 8Rank: 8

积分
4521
金钱
4521
注册时间
2018-5-11
在线时间
946 小时
发表于 2018-7-26 11:07:44 | 显示全部楼层
878738424 发表于 2018-7-26 08:56
10秒是为了服务函数的灯的闪烁效果。不然看不出来

可以采取在中断服务中置标志,在主函数中判断标志的方法来控制灯
我的开源链接 https://github.com/ShuifaHe/STM32.git  请关注,点赞支持哦。
回复 支持 反对

使用道具 举报

5

主题

17

帖子

0

精华

新手上路

积分
46
金钱
46
注册时间
2018-7-26
在线时间
11 小时
 楼主| 发表于 2018-7-26 19:22:51 | 显示全部楼层
warship 发表于 2018-7-26 11:07
可以采取在中断服务中置标志,在主函数中判断标志的方法来控制灯

解决了。是在确认中断那里出了问题。主优先级相同,副优先级不同,要想形成中断队列,是要用EXTI_GetITStatus(WK_UP_EXTI_LINE)!=RESET,不能通过管脚电平来判断。主优先级不同时,副优先级相同时,通过管脚电平来判断也可以。
回复 支持 反对

使用道具 举报

5

主题

17

帖子

0

精华

新手上路

积分
46
金钱
46
注册时间
2018-7-26
在线时间
11 小时
 楼主| 发表于 2018-7-26 19:24:50 | 显示全部楼层
问题已解决。
QQ图片20180726191850.png
QQ图片20180726191900.png
回复 支持 反对

使用道具 举报

5

主题

17

帖子

0

精华

新手上路

积分
46
金钱
46
注册时间
2018-7-26
在线时间
11 小时
 楼主| 发表于 2018-7-26 19:52:04 | 显示全部楼层
中断优先级的一些新理解:
2018-07-26_195012.png
回复 支持 反对

使用道具 举报

31

主题

1955

帖子

3

精华

论坛元老

Rank: 8Rank: 8

积分
4521
金钱
4521
注册时间
2018-5-11
在线时间
946 小时
发表于 2018-7-26 22:22:10 | 显示全部楼层
本帖最后由 warship 于 2018-7-26 22:46 编辑

我个人认为不是你说的这个原因,
正常情况下,判断管脚与判断挂起位是没有太大区别的(共用中断线的另说)
主要原因还是你中断服务时间太长。
这样的情况下,判断管脚就会失常,因为不够实时,如果判断管脚,可能按键已经释放,这样条件语句就不成立,所以不执行IF下的语句,造成没有进中断的假象。但判断挂起位则可以执行IF下的语句,因为挂起位你不清它就一直有效。
所以,并不是你说的主优先级、副优先级同与不同,与管脚、挂起位、消息队列的关系。
其实,这种按键中断服务,使用管脚判断反而是正常的,因为这里有消除抖动的需求。
如果改成判断挂起位后,消除抖动就失去作用了(延时10ms变成了废语句)。
总之,延时10ms消抖已经是这种按键中断服务里迫不得已的举措了,就这10ms绝大多数程序员都不认可放在这里的。
而你还在里面大量延时,总执行长度达10秒,时序不乱套才怪呢。 要知道,1ms内STM32可以执行上万行C程序(约7万条汇编语句)的。之所以大家都主张不要在中断服务程序中延时,就是要尽量减少中断服务时间(试想在没有延时的情况下,1ms内可以执行百十页纸的C代码,再长的中断服务也都搞定了),
这样快进快出的结果,就是为了其它的中断能够被最快速地得到响应,从而保证实时性。



我的开源链接 https://github.com/ShuifaHe/STM32.git  请关注,点赞支持哦。
回复 支持 反对

使用道具 举报

5

主题

17

帖子

0

精华

新手上路

积分
46
金钱
46
注册时间
2018-7-26
在线时间
11 小时
 楼主| 发表于 2018-7-28 09:59:18 | 显示全部楼层
1)中断服务时间太长。我是故意让中断服务时间长,好让CPU在处理中断服务程序的一半的时候按下第二个按键,看CPU会不会跳到第二个按键中断服务程序里面。我是看灯的闪烁效果来分析它。中断服务时间太短,现象不直观。
2)因为不够实时,如果判断管脚,可能按键已经释放,这样条件语句就不成立,所以不执行IF下的语句,造成没有进中断的假象。但判断挂起位则可以执行IF下的语句,因为挂起位你不清它就一直有效。这个我弄明白了。
3)其实,这种按键中断服务,使用管脚判断反而是正常的,因为这里有消除抖动的需求。
如果改成判断挂起位后,消除抖动就失去作用了(延时10ms变成了废语句)。这个我也明白。
4)在里面大量延时,总执行长度达10秒,时序不乱套才怪呢。我的程序没其他功能,只有三个按键中断控制灯的三种闪烁情况,没其他中断,好分析它。想让它动作慢下来才好分析。时序乱套这个有点不解,这个应该在多个中断同时来cpu来不及处理才可能吧?
回复 支持 反对

使用道具 举报

5

主题

17

帖子

0

精华

新手上路

积分
46
金钱
46
注册时间
2018-7-26
在线时间
11 小时
 楼主| 发表于 2018-7-28 09:59:38 | 显示全部楼层
warship 发表于 2018-7-26 22:22
我个人认为不是你说的这个原因,
正常情况下,判断管脚与判断挂起位是没有太大区别的(共用中断线的另说 ...


1)中断服务时间太长。我是故意让中断服务时间长,好让CPU在处理中断服务程序的一半的时候按下第二个按键,看CPU会不会跳到第二个按键中断服务程序里面。我是看灯的闪烁效果来分析它。中断服务时间太短,现象不直观。
2)因为不够实时,如果判断管脚,可能按键已经释放,这样条件语句就不成立,所以不执行IF下的语句,造成没有进中断的假象。但判断挂起位则可以执行IF下的语句,因为挂起位你不清它就一直有效。这个我弄明白了。
3)其实,这种按键中断服务,使用管脚判断反而是正常的,因为这里有消除抖动的需求。
如果改成判断挂起位后,消除抖动就失去作用了(延时10ms变成了废语句)。这个我也明白。
4)在里面大量延时,总执行长度达10秒,时序不乱套才怪呢。我的程序没其他功能,只有三个按键中断控制灯的三种闪烁情况,没其他中断,好分析它。想让它动作慢下来才好分析。时序乱套这个有点不解,这个应该在多个中断同时来cpu来不及处理才可能吧?
回复 支持 反对

使用道具 举报

31

主题

1955

帖子

3

精华

论坛元老

Rank: 8Rank: 8

积分
4521
金钱
4521
注册时间
2018-5-11
在线时间
946 小时
发表于 2018-7-28 10:21:35 | 显示全部楼层
本帖最后由 warship 于 2018-7-28 10:33 编辑
878738424 发表于 2018-7-28 09:59
1)中断服务时间太长。我是故意让中断服务时间长,好让CPU在处理中断服务程序的一半的时候按下第二个按 ...

看到你的按键中断研究的程序了,下了不少功夫。
如果是这种专门研究目的,中断里的延时就另当别论了。
所谓的时序乱套,从宏观的角度来看,就是你研究出来的结果。
正常程序,几个破按键一般不会刻意去设不同的中断优先级,
完成的功能是:按1键做A事,按2键做B事,按3键做C事,非常实时,干脆利落。
延时以后,很可能出现按1键做A事,按2键还在做A事,按3键却做B事等等,如果A事、B事、C事相互之间还有联系,彼此的变量或前提条件还有相互依赖,那就更复杂了,根本无法预料。
我的开源链接 https://github.com/ShuifaHe/STM32.git  请关注,点赞支持哦。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-6-17 22:51

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表