打印
[MM32软件]

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

[复制链接]
4557|8
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
gaoyang9992006|  楼主 | 2020-4-23 11:14 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 gaoyang9992006 于 2020-4-23 13:08 编辑

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

使用特权

评论回复
评论
gaoyang9992006 2020-4-23 13:10 回复TA
已经优化部分内容。 
沙发
gaoyang9992006|  楼主 | 2020-4-23 11:14 | 只看该作者
结果就是:当发生中断后,原来的函数继续执行,当执行完成后,会切换到新指向的函数。

使用特权

评论回复
板凳
gaoyang9992006|  楼主 | 2020-4-23 11:15 | 只看该作者
本帖最后由 gaoyang9992006 于 2020-4-23 13:09 编辑

#include "delay.h"
#include "sys.h"
#include "led.h"
#include "key.h"
#include "exti.h"
typedef void (*BL)(void);
static volatile BL BLINK = NULL;

/********************************************************************************************************
**函数信息 :main(void)                       
**功能描述 :
**输入参数 :无
**输出参数 :无
********************************************************************************************************/
int main(void)
{
   
    delay_init();       
    LED_Init();                                                //初始化与LED连接的硬件接口
    KEY_Init();                                                //初始化与按键连接的硬件接口
    EXTIX_Init();
                BLINK=(BL)LED_Blink0; //给指针指向一个全部灭灯函数,防止跑飞。
    while(1)
    {
                        LED_Blink0();
                        BLINK();
                }
}

/*
        下面是中断函数
*/

void EXTI0_1_IRQHandler(void)
{
                delay_ms(10);
    if(KEY1==1)
    {          
                                BLINK=(BL)LED_Blink1;
    }
    EXTI_ClearFlag(EXTI_Line1);  //清除EXTI0线路挂起位
}

void EXTI2_3_IRQHandler(void)
{                       
                delay_ms(10);
    if(KEY2==0)
    {          
                                BLINK=(BL)LED_Blink2;
    }

    EXTI_ClearFlag(EXTI_Line2);   //清除EXTI2线路挂起位
   
}

void EXTI4_15_IRQHandler(void)
{                       
                delay_ms(10);
    if(KEY3==0)
    {          
                                BLINK=(BL)LED_Blink3;
    }       
    else if(KEY4==0)
    {          
                                BLINK=(BL)LED_Blink4;
    }
    EXTI_ClearFlag(EXTI_Line10|EXTI_Line11);   //清除EXTI10,11线路挂起位
   
}

使用特权

评论回复
地板
gaoyang9992006|  楼主 | 2020-4-23 11:17 | 只看该作者
主函数如上楼所示。中断的配置初始化函数如下
#include "exti.h"
#include "led.h"
#include "key.h"
#include "delay.h"

//////////////////////////////////////////////////////////////////////////////////         
//开发板
//外部中断 驱动代码                          
//////////////////////////////////////////////////////////////////////////////////           


//外部中断初始化函数
void EXTIX_Init(void)
{
   
    EXTI_InitTypeDef EXTI_InitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;
   
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG,ENABLE);//外部中断,需要使能AFIO时钟
   
    KEY_Init();//初始化按键对应io模式
   
    //GPIOB.1 中断线以及中断初始化配置
    SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOB,EXTI_PinSource1);
   
    EXTI_InitStructure.EXTI_Line=EXTI_Line1;
    EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;       
    EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;//上升沿触发
    EXTI_InitStructure.EXTI_LineCmd = ENABLE;
    EXTI_Init(&EXTI_InitStructure);                 //根据EXTI_InitStruct中指定的参数初始化外设EXTI寄存器
   
    //GPIOB.2 中断线以及中断初始化配置
    SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOB,EXTI_PinSource2);
   
    EXTI_InitStructure.EXTI_Line=EXTI_Line2;
    EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;       
    EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;//下降沿触发
    EXTI_InitStructure.EXTI_LineCmd = ENABLE;
    EXTI_Init(&EXTI_InitStructure);                 //根据EXTI_InitStruct中指定的参数初始化外设EXTI寄存器
   
    //GPIOB.10          中断线以及中断初始化配置
    SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOB,EXTI_PinSource10);
   
    EXTI_InitStructure.EXTI_Line = EXTI_Line10;
    EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;       
    EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;//下降沿触发
    EXTI_InitStructure.EXTI_LineCmd = ENABLE;
    EXTI_Init(&EXTI_InitStructure);                //根据EXTI_InitStruct中指定的参数初始化外设EXTI寄存器
   
    //GPIOB.11          中断线以及中断初始化配置
    SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOB,EXTI_PinSource11);
   
    EXTI_InitStructure.EXTI_Line=EXTI_Line11;
    EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;       
    EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;//下降沿触发
    EXTI_InitStructure.EXTI_LineCmd = ENABLE;
    EXTI_Init(&EXTI_InitStructure);                //根据EXTI_InitStruct中指定的参数初始化外设EXTI寄存器
   
   
    NVIC_InitStructure.NVIC_IRQChannel = EXTI4_15_IRQn;                        //使能按键所在的外部中断通道
    NVIC_InitStructure.NVIC_IRQChannelPriority = 0x02;                                        //子优先级2
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;                                                                //使能外部中断通道
    NVIC_Init(&NVIC_InitStructure);            //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器

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

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





使用特权

评论回复
5
lansebuluo| | 2020-4-23 12:44 | 只看该作者
这个理解起来不难,一个任务执行完,才能执行另一个任务。只看了你贴出来的代码,有一个问题,想问,灭灯的程序,是不是存在问题,中断里灭灯,函数指针切换,中断退出,原来执行的函数继续执行,将影响灭灯函数的结果

使用特权

评论回复
6
gaoyang9992006|  楼主 | 2020-4-23 13:04 | 只看该作者
lansebuluo 发表于 2020-4-23 12:44
这个理解起来不难,一个任务执行完,才能执行另一个任务。只看了你贴出来的代码,有一个问题,想问,灭灯的 ...

你这个问题问的好,这跟之前查询法的理念不同了,所以你说的对,不应该在这个位置灭灯,也起不到那个效果。应该在while循环里,BLINK()之前调用或者之后调用都可以。
我只是直接复制过来了我之前写的查询法的语句,没想到是否起效。

使用特权

评论回复
7
lansebuluo| | 2020-4-23 13:30 | 只看该作者
来点高级点的想法,任务优先级。按键切换后,保存上一个任务task1的灯状态,中断退出,立即执行新的任务task2;当按键要切换任务task1时,先加载task1上次执行到的状态,继续执行。动态调整任务的优先级。

使用特权

评论回复
8
gaoyang9992006|  楼主 | 2020-4-23 13:37 | 只看该作者
lansebuluo 发表于 2020-4-23 13:30
来点高级点的想法,任务优先级。按键切换后,保存上一个任务task1的灯状态,中断退出,立即执行新的任务tas ...


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

使用特权

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

本版积分规则

认证:西安公路研究院南京院
简介:主要工作从事监控网络与通信网络设计,以及从事基于嵌入式的通信与控制设备研发。擅长单片机嵌入式系统物联网设备开发,音频功放电路开发。

1897

主题

15634

帖子

198

粉丝