OpenEdv-开源电子网

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

f4进入中断后,中断不返回主函数

[复制链接]

4

主题

22

帖子

0

精华

初级会员

Rank: 2

积分
87
金钱
87
注册时间
2022-1-6
在线时间
27 小时
发表于 2022-4-16 15:08:20 | 显示全部楼层 |阅读模式
2金钱
f4进入中断后,不能返回,程序如下:
********************************************************************************fire.h**************************************************************************************************#ifndef _FIRE_H
#define _FIRE_H
#include "sys.h"
#include "delay.h"
#include "oled.h"
#include "led.h"
// E2 E3 E4 E5 E6

#define fire1 PEin(10)
#define fire2 PEin(11)
#define fire3 PEin(12)
#define fire4 PEin(13)
#define fire5 PEin(14)

void Fire_init(void);  //火焰传感器初始化
void EXTI15_10_Init(void); //中断向量初始化

#endif
********************************************************************************fire.c**************************************************************************************************



#include "fire.h"

void Fire_init(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;

    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE); //使能GPIOE时钟

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14; // fire12345对应引脚
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;                                                       //普通输入模式
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;                                                 // 100M
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN;                                                     //下拉
    GPIO_Init(GPIOE, &GPIO_InitStructure);                                                             //初始化GPIOE2,3,4
}

void EXTI15_10_Init(void)
{
    NVIC_InitTypeDef NVIC_InitStructure;
    EXTI_InitTypeDef EXTI_InitStructure;

    Fire_init(); //按键对应的IO口初始化

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE); //使能SYSCFG时钟

    SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOE, EXTI_PinSource10); // PE10 连接到中断线10
    SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOE, EXTI_PinSource11); // PE11 连接到中断线11
    SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOE, EXTI_PinSource12); // PE12 连接到中断线12
    SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOE, EXTI_PinSource13); // PE13 连接到中断线13
    SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOE, EXTI_PinSource14); // PE14 连接到中断线14

    /* 配置EXTI_Linex */
    EXTI_InitStructure.EXTI_Line = EXTI_Line10 | EXTI_Line11 |
                                   EXTI_Line12 | EXTI_Line13 | EXTI_Line14; // LINEx
    EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;                     //中断事件
    EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;                  //上升沿触发
    EXTI_InitStructure.EXTI_LineCmd = ENABLE;                               //使能LINE
    EXTI_Init(&EXTI_InitStructure);                                         //配置

    NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn;         //外部中断
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x01; //抢占优先级1
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02;        //子优先级2
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;              //使能外部中断通道
    NVIC_Init(&NVIC_InitStructure);                              //配置
}

void EXTI15_10_IRQHandler(void)
{

    delay_ms(100);
    if (fire1 == 1)
    {
        EXTI_ClearITPendingBit(EXTI_Line10); //清除LINE0上的中断标志位
        OLED_Clear();
        OLED_ShowString(25, 20, "Find fire1", 16, 1);
        OLED_Refresh();
        LED0 = 0;
        LED1 = !LED1;
    }

    if (fire2 == 1)
    {
        EXTI_ClearITPendingBit(EXTI_Line11); //清除LINE0上的中断标志位
        OLED_Clear();
        OLED_ShowString(25, 20, "Find fire2", 16, 1);
        OLED_Refresh();
        LED0 = 1;
        LED1 = 0;
    }

    if (fire3 == 1)
    {
        EXTI_ClearITPendingBit(EXTI_Line13); //清除LINE0上的中断标志位
        OLED_Clear();
        OLED_ShowString(25, 20, "Find fire3", 16, 1);
        OLED_Refresh();
        LED0 = 0;
        LED1 = 0;
    }

    if (fire4 == 1)
    {
        EXTI_ClearITPendingBit(EXTI_Line14); //清除LINE0上的中断标志位
        OLED_Clear();
        OLED_ShowString(25, 20, "Find fire4", 16, 1);
        OLED_Refresh();
        LED0 = !LED0;
        LED1 = 1;
    }

    if (fire5 == 1)
    {
        EXTI_ClearITPendingBit(EXTI_Line15); //清除LINE0上的中断标志位
        OLED_Clear();
        OLED_ShowString(25, 20, "Find fire5", 16, 1);
        OLED_Refresh();
        LED0 = 1;
        LED1 = !LED1;
    }
}


**********************************************************************************main.c********************************************************************************************

#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "oled.h"
#include "bluetooth.h"
#include "timer34.h"
#include "fire.h"
#include "led.h"

u16 pwmval1 = 25;
u16 pwmval2 = 25;
u16 pwmval3 = 25;
u16 pwmval4 = 25;

int main(void)
{
    int t=0;
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置系统中断优先级分组2
    LED_Init();
    uart_init(115200);
    delay_init(168);                                //初始化延时函数
    OLED_Init();                                    // OLED初始化
    Usart3_init(9600);
    EXTI15_10_Init();
    TIM3_Int_Init(500 - 1, 84 - 1); //定时器时钟84M,分频系数84,所以84M/84=1Mhz的计数频率,频率为10khz
    TIM4_Int_Init(500 - 1, 84 - 1); //定时器时钟84M,分频系数84,所以84M/84=1Mhz的计数频率,频率为10khz
    while (1)
    {
        OLED_Clear();
        OLED_ShowString(25, 20, "work", 16, 1);
        OLED_Refresh();
        LED2=!LED2;
        printf("t:%d\r\n",t);
        t++;
        delay_ms(500);
    }
}






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

使用道具 举报

13

主题

250

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
2248
金钱
2248
注册时间
2019-8-7
在线时间
364 小时
发表于 2022-4-16 15:17:09 | 显示全部楼层
你中断延时太长了 这样会迭代的 你在这个中断程序中100ms内触发另一个中断 可以让你无限循环下去这辈子出不来除非没电
回复

使用道具 举报

4

主题

22

帖子

0

精华

初级会员

Rank: 2

积分
87
金钱
87
注册时间
2022-1-6
在线时间
27 小时
 楼主| 发表于 2022-4-16 15:24:36 | 显示全部楼层
远命 发表于 2022-4-16 15:17
你中断延时太长了 这样会迭代的 你在这个中断程序中100ms内触发另一个中断 可以让你无限循环下去这辈子出不 ...

不行呀,大哥,我把我中断里面所有的延时全部注释掉了以后还是出不来
回复

使用道具 举报

13

主题

250

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
2248
金钱
2248
注册时间
2019-8-7
在线时间
364 小时
发表于 2022-4-16 15:31:55 | 显示全部楼层
抓催表面 发表于 2022-4-16 15:24
不行呀,大哥,我把我中断里面所有的延时全部注释掉了以后还是出不来

你这看的好难受  判断是哪个触发中断后 用一个变量来存储标志位 在主循环中判断标志位是否被置位了 例如初始状态为0 每次触发为不为0的数 触发后初始化标志位 通过这个变量来执行程序 中断内 执行程序是实在没办法才那样的基本不要
回复

使用道具 举报

14

主题

821

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
2070
金钱
2070
注册时间
2021-7-17
在线时间
647 小时
发表于 2022-4-16 16:40:00 | 显示全部楼层
中断卡死,可以考虑是否有清中断
回复

使用道具 举报

3

主题

821

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
3359
金钱
3359
注册时间
2011-11-10
在线时间
207 小时
发表于 2022-4-16 18:20:48 | 显示全部楼层
检查你的OLED_Clear();
        OLED_ShowString(25, 20, "Find fire1", 16, 1);
        OLED_Refresh();三个函数里面,是否有依靠systic计数的延时,如果有,换成纯代码的for循环延时即可。任何时候,都不建议在中断里呆的时间太长。编写代码这个应该作为一个基本规则。
回复

使用道具 举报

4

主题

22

帖子

0

精华

初级会员

Rank: 2

积分
87
金钱
87
注册时间
2022-1-6
在线时间
27 小时
 楼主| 发表于 2022-4-16 22:22:44 | 显示全部楼层
void Fire_init(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    EXTI_InitTypeDef EXTI_InitStruct;
    NVIC_InitTypeDef NVIC_InitStruct;

    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE); //使能GPIOE时钟

    // PG13、PG14和PG15初始化设置
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15; // 对应IO口
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;                                                       //普通输入模式
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;                                                 // 100MHz
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN;                                                     //上拉
    GPIO_Init(GPIOE, &GPIO_InitStructure);                                                             //初始化GPIO

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE); //使用外部中断时,必须使能SYSCFG时钟

    SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOE, EXTI_PinSource11);
    SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOE, EXTI_PinSource12);
    SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOE, EXTI_PinSource13);
    SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOE, EXTI_PinSource14);
    SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOE, EXTI_PinSource15);

    EXTI_InitStruct.EXTI_Line = EXTI_Line11 | EXTI_Line12 | EXTI_Line13 | EXTI_Line14 | EXTI_Line15; //选择中断线
    EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt;                                                 //选择中断模式
    EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Rising;                                              //选择上升沿触发
    EXTI_InitStruct.EXTI_LineCmd = ENABLE;                                                           //使能中断线
    EXTI_Init(&EXTI_InitStruct);

    NVIC_InitStruct.NVIC_IRQChannel = EXTI15_10_IRQn;         //指定中断向量(中断号)
    NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0x01; //指定抢占优先级(主优先级)1
    NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0x01;        //指定响应优先级(子优先级)1
    NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;              //使能NVIC
    NVIC_Init(&NVIC_InitStruct);
}

void EXTI15_10_IRQHandler(void)
{
    if (EXTI_GetFlagStatus(EXTI_Line11) != RESET) // 判断中断发生的中断线
    {
        while (fire1 == 1)
        {
            OLED_Clear();
            OLED_ShowString(25, 20, "Find fire1", 16, 1);
            OLED_Refresh();
        }
        EXTI_ClearFlag(EXTI_Line11); //清除中断标志位
    }

    if (EXTI_GetFlagStatus(EXTI_Line12) != RESET) // 判断中断发生的中断线
    {
        while (fire2 == 1)
        {
            OLED_Clear();
            OLED_ShowString(25, 20, "Find fire2", 16, 1);
            OLED_Refresh();
        }
        EXTI_ClearFlag(EXTI_Line12); //清除中断标志位
    }

    if (EXTI_GetFlagStatus(EXTI_Line13) != RESET) // 判断中断发生的中断线
    {
        while (fire3 == 1)
        {
            OLED_Clear();
            OLED_ShowString(25, 20, "Find fire3", 16, 1);
            OLED_Refresh();
        }
        EXTI_ClearFlag(EXTI_Line13); // 清除中断标志位
    }

    if (EXTI_GetFlagStatus(EXTI_Line14) != RESET) // 判断中断发生的中断线
    {
        while (fire4 == 1)
        {
            OLED_Clear();
            OLED_ShowString(25, 20, "Find fire4", 16, 1);
            OLED_Refresh();
        }
        EXTI_ClearFlag(EXTI_Line14); //清除中断标志位
    }

    if (EXTI_GetFlagStatus(EXTI_Line15) != RESET) // 判断中断发生的中断线
    {
        while (fire5 == 1)
        {
            OLED_Clear();
            OLED_ShowString(25, 20, "Find fire5", 16, 1);
            OLED_Refresh();
        }
        EXTI_ClearFlag(EXTI_Line15); // 清除中断标志位
    }
}
我也不知道为啥,我重新写了一遍代码,然后他就可以返回中函数了
回复

使用道具 举报

6

主题

34

帖子

0

精华

初级会员

Rank: 2

积分
119
金钱
119
注册时间
2019-2-12
在线时间
28 小时
发表于 2022-4-19 09:53:03 | 显示全部楼层
中断中尽量不要出现while, delay之类可能长延时的操作,你这程序是通过按键进入外部中断,然后中断里面又判断按键电平是什么骚操作……直接在中断里面将相应的变量置位,然后在主循环里面判断变量来显示
回复

使用道具 举报

4

主题

22

帖子

0

精华

初级会员

Rank: 2

积分
87
金钱
87
注册时间
2022-1-6
在线时间
27 小时
 楼主| 发表于 2022-4-23 10:56:17 | 显示全部楼层
turelon 发表于 2022-4-19 09:53
中断中尽量不要出现while, delay之类可能长延时的操作,你这程序是通过按键进入外部中断,然后中断里面又判 ...

我的想法就是如果检测到上升沿,并且一直搞电平的时候,就一直执行中断里面的这个程序,然后就检测是否等于1,然后等于1就一直循环
回复

使用道具 举报

4

主题

22

帖子

0

精华

初级会员

Rank: 2

积分
87
金钱
87
注册时间
2022-1-6
在线时间
27 小时
 楼主| 发表于 2022-4-23 13:33:38 | 显示全部楼层
这个原因好像是因为,把清除中断标志位放在了前面,好像需要放在中断服务函数用户函数的最后面
回复

使用道具 举报

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

本版积分规则



关闭

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

正点原子公众号

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

GMT+8, 2025-2-25 21:29

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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