[MM32软件] 【MM32 eMiniBoard测评报告】+中断内指针切换问题

[复制链接]
 楼主| gaoyang9992006 发表于 2020-4-23 11:14 | 显示全部楼层 |阅读模式
本帖最后由 gaoyang9992006 于 2020-4-23 13:08 编辑

昨晚一个问题一直困惑我。
我之前发过一个测评,花样流水灯。用扫描法实现按键操作。通过分支语句修改一个函数指针,用于切换while循环里
的函数指针指向不同的流水灯子函数。
那么问题来了,我那个程序是在执行完子函数后才扫描键盘切换指向的。
这有一个问题,就是要按着,直到当前指向的那个子函数执行完。
如果我按键在中断里实现,那么我可以在函数没有执行完的时候就切换函数指针的指向。
问题来了,退出中断后,执行了一半的子函数会继续执行完吗?如果会,那么还会正常的退回到
原来的while循环执行新的指向吗?
会跑飞吗?
所以我做了测试,测试结果是完美的。上工程。
Blink_EXTI.zip (510.69 KB, 下载次数: 5)

点评

已经优化部分内容。  发表于 2020-4-23 13:10
 楼主| gaoyang9992006 发表于 2020-4-23 11:14 | 显示全部楼层
结果就是:当发生中断后,原来的函数继续执行,当执行完成后,会切换到新指向的函数。
 楼主| gaoyang9992006 发表于 2020-4-23 11:15 | 显示全部楼层
本帖最后由 gaoyang9992006 于 2020-4-23 13:09 编辑

  1. #include "delay.h"
  2. #include "sys.h"
  3. #include "led.h"
  4. #include "key.h"
  5. #include "exti.h"
  6. typedef void (*BL)(void);
  7. static volatile BL BLINK = NULL;

  8. /********************************************************************************************************
  9. **函数信息 :main(void)                       
  10. **功能描述 :
  11. **输入参数 :无
  12. **输出参数 :无
  13. ********************************************************************************************************/
  14. int main(void)
  15. {
  16.    
  17.     delay_init();       
  18.     LED_Init();                                                //初始化与LED连接的硬件接口
  19.     KEY_Init();                                                //初始化与按键连接的硬件接口
  20.     EXTIX_Init();
  21.                 BLINK=(BL)LED_Blink0; //给指针指向一个全部灭灯函数,防止跑飞。
  22.     while(1)
  23.     {
  24.                         LED_Blink0();
  25.                         BLINK();
  26.                 }
  27. }

  28. /*
  29.         下面是中断函数
  30. */

  31. void EXTI0_1_IRQHandler(void)
  32. {
  33.                 delay_ms(10);
  34.     if(KEY1==1)
  35.     {          
  36.                                 BLINK=(BL)LED_Blink1;
  37.     }
  38.     EXTI_ClearFlag(EXTI_Line1);  //清除EXTI0线路挂起位
  39. }

  40. void EXTI2_3_IRQHandler(void)
  41. {                       
  42.                 delay_ms(10);
  43.     if(KEY2==0)
  44.     {          
  45.                                 BLINK=(BL)LED_Blink2;
  46.     }

  47.     EXTI_ClearFlag(EXTI_Line2);   //清除EXTI2线路挂起位
  48.    
  49. }

  50. void EXTI4_15_IRQHandler(void)
  51. {                       
  52.                 delay_ms(10);
  53.     if(KEY3==0)
  54.     {          
  55.                                 BLINK=(BL)LED_Blink3;
  56.     }       
  57.     else if(KEY4==0)
  58.     {          
  59.                                 BLINK=(BL)LED_Blink4;
  60.     }
  61.     EXTI_ClearFlag(EXTI_Line10|EXTI_Line11);   //清除EXTI10,11线路挂起位
  62.    
  63. }

 楼主| gaoyang9992006 发表于 2020-4-23 11:17 | 显示全部楼层
主函数如上楼所示。中断的配置初始化函数如下
  1. #include "exti.h"
  2. #include "led.h"
  3. #include "key.h"
  4. #include "delay.h"

  5. //////////////////////////////////////////////////////////////////////////////////         
  6. //开发板
  7. //外部中断 驱动代码                          
  8. //////////////////////////////////////////////////////////////////////////////////           


  9. //外部中断初始化函数
  10. void EXTIX_Init(void)
  11. {
  12.    
  13.     EXTI_InitTypeDef EXTI_InitStructure;
  14.     NVIC_InitTypeDef NVIC_InitStructure;
  15.    
  16.     RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG,ENABLE);//外部中断,需要使能AFIO时钟
  17.    
  18.     KEY_Init();//初始化按键对应io模式
  19.    
  20.     //GPIOB.1 中断线以及中断初始化配置
  21.     SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOB,EXTI_PinSource1);
  22.    
  23.     EXTI_InitStructure.EXTI_Line=EXTI_Line1;
  24.     EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;       
  25.     EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;//上升沿触发
  26.     EXTI_InitStructure.EXTI_LineCmd = ENABLE;
  27.     EXTI_Init(&EXTI_InitStructure);                 //根据EXTI_InitStruct中指定的参数初始化外设EXTI寄存器
  28.    
  29.     //GPIOB.2 中断线以及中断初始化配置
  30.     SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOB,EXTI_PinSource2);
  31.    
  32.     EXTI_InitStructure.EXTI_Line=EXTI_Line2;
  33.     EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;       
  34.     EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;//下降沿触发
  35.     EXTI_InitStructure.EXTI_LineCmd = ENABLE;
  36.     EXTI_Init(&EXTI_InitStructure);                 //根据EXTI_InitStruct中指定的参数初始化外设EXTI寄存器
  37.    
  38.     //GPIOB.10          中断线以及中断初始化配置
  39.     SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOB,EXTI_PinSource10);
  40.    
  41.     EXTI_InitStructure.EXTI_Line = EXTI_Line10;
  42.     EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;       
  43.     EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;//下降沿触发
  44.     EXTI_InitStructure.EXTI_LineCmd = ENABLE;
  45.     EXTI_Init(&EXTI_InitStructure);                //根据EXTI_InitStruct中指定的参数初始化外设EXTI寄存器
  46.    
  47.     //GPIOB.11          中断线以及中断初始化配置
  48.     SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOB,EXTI_PinSource11);
  49.    
  50.     EXTI_InitStructure.EXTI_Line=EXTI_Line11;
  51.     EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;       
  52.     EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;//下降沿触发
  53.     EXTI_InitStructure.EXTI_LineCmd = ENABLE;
  54.     EXTI_Init(&EXTI_InitStructure);                //根据EXTI_InitStruct中指定的参数初始化外设EXTI寄存器
  55.    
  56.    
  57.     NVIC_InitStructure.NVIC_IRQChannel = EXTI4_15_IRQn;                        //使能按键所在的外部中断通道
  58.     NVIC_InitStructure.NVIC_IRQChannelPriority = 0x02;                                        //子优先级2
  59.     NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;                                                                //使能外部中断通道
  60.     NVIC_Init(&NVIC_InitStructure);            //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器

  61.     NVIC_InitStructure.NVIC_IRQChannel = EXTI2_3_IRQn;                        //使能按键所在的外部中断通道
  62.     NVIC_InitStructure.NVIC_IRQChannelPriority = 0x02;                                        //子优先级2
  63.     NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;                                                                //使能外部中断通道
  64.     NVIC_Init(&NVIC_InitStructure);            //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器

  65.     NVIC_InitStructure.NVIC_IRQChannel = EXTI0_1_IRQn;                        //使能按键所在的外部中断通道
  66.     NVIC_InitStructure.NVIC_IRQChannelPriority = 0x01;                                        //子优先级1
  67.     NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;                                                                //使能外部中断通道
  68.     NVIC_Init(&NVIC_InitStructure);
  69. }





lansebuluo 发表于 2020-4-23 12:44 来自手机 | 显示全部楼层
这个理解起来不难,一个任务执行完,才能执行另一个任务。只看了你贴出来的代码,有一个问题,想问,灭灯的程序,是不是存在问题,中断里灭灯,函数指针切换,中断退出,原来执行的函数继续执行,将影响灭灯函数的结果
 楼主| gaoyang9992006 发表于 2020-4-23 13:04 | 显示全部楼层
lansebuluo 发表于 2020-4-23 12:44
这个理解起来不难,一个任务执行完,才能执行另一个任务。只看了你贴出来的代码,有一个问题,想问,灭灯的 ...

你这个问题问的好,这跟之前查询法的理念不同了,所以你说的对,不应该在这个位置灭灯,也起不到那个效果。应该在while循环里,BLINK()之前调用或者之后调用都可以。
我只是直接复制过来了我之前写的查询法的语句,没想到是否起效。
lansebuluo 发表于 2020-4-23 13:30 来自手机 | 显示全部楼层
来点高级点的想法,任务优先级。按键切换后,保存上一个任务task1的灯状态,中断退出,立即执行新的任务task2;当按键要切换任务task1时,先加载task1上次执行到的状态,继续执行。动态调整任务的优先级。
 楼主| gaoyang9992006 发表于 2020-4-23 13:37 | 显示全部楼层
lansebuluo 发表于 2020-4-23 13:30
来点高级点的想法,任务优先级。按键切换后,保存上一个任务task1的灯状态,中断退出,立即执行新的任务tas ...


这个想法也不错,中断后先执行中断的任务,完成了再回去,那这样如果嵌套的话,处理起来就麻烦了,可以考虑一下,如何解决。一起想想。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:如果你觉得我的分享或者答复还可以,请给我点赞,谢谢。

2045

主题

16350

帖子

222

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