OpenEdv-开源电子网

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

关于外部中断的寄存器配置

[复制链接]

3

主题

13

帖子

0

精华

新手上路

积分
33
金钱
33
注册时间
2017-1-11
在线时间
6 小时
发表于 2017-1-11 23:43:23 | 显示全部楼层 |阅读模式
3金钱
大神好,我用的板子是原子的stm32f103rc,软件是MDK5, 我在用库函数配置外部中断的时候后下载到板子里,可以进入中断;但是用寄存器配置外部中断的时候,发现进入不到中断。我的配置过程如下:(基本上都是基于资料的例程稍作修改)
一、正常进入中断的库函数代码:

1. 打开示例程序库函数版本,实验4外部中断实验
2.屏蔽掉delay_init,因为目前还不需要systick.
3.屏蔽延时函数,因为systick没配置,所以也屏蔽相关函数,去不去抖的先放一边。
主程序如下:
[mw_shl_code=c,true]#include "led.h"
#include "delay.h"
#include "sys.h"
#include "key.h"
#include "usart.h"
#include "exti.h"
int main(void)
{       

        //delay_init();                     //延时函数初始化       
        NVIC_Configuration();// 设置中断优先级分组  
        //uart_init(9600);         //串口初始化为9600
        LED_Init();                           //初始化与LED连接的硬件接口
        EXTIX_Init();                //外部中断初始化
  LED0=0;                                //点亮LED
        while(1);
        /*{            
                printf("OK\n");       
                delay_ms(1000);          
        }*/
}[/mw_shl_code]

中断服务例程如下:
[mw_shl_code=c,true] void EXTI9_5_IRQHandler(void)
{                       
        //delay_ms(10);   //消抖                         
        if(KEY0==0)        {
                LED0=!LED0;
        }
         EXTI_ClearITPendingBit(EXTI_Line5);    //清除LINE5上的中断标志位  
}[/mw_shl_code]



二、不能进入中断的寄存器版代码:
1. 打开示例程序寄存器版本,实验4外部中断实验
2.屏蔽掉Stm32_Clock_Init函数
3.屏蔽掉delay_init(), uart_init(),以及和systick相关的代码。
主程序代码如下:
[mw_shl_code=c,true]#include "sys.h"
#include "usart.h"               
#include "delay.h"       
#include "led.h"  
#include "exti.h"
//ALIENTEK Mini STM32开发板范例代码4
//外部中断实验   
//技术支持:www.openedv.com
//广州市星翼电子科技有限公司

int main(void)
{                       
        //Stm32_Clock_Init(9);//系统时钟设置
        //delay_init(72);            //延时初始化
        //uart_init(72,9600); //串口初始化
        LED_Init();                          //初始化与LED连接的硬件接口
        EXTI_Init();                //外部中断初始化
        LED0=0;                                //点亮LED
        while(1);
        /*{            
                printf("OK\r\n");       
                delay_ms(1000);          
        } */
}[/mw_shl_code]

中断处理函数如下:
[mw_shl_code=c,true]//外部中断15~10服务程序
void EXTI15_10_IRQHandler(void)
{                       
        //delay_ms(10);   //消抖                         
    if(KEY1==0)                //按键1
        {
                LED0=0;
                LED1 = 1;
        }
        EXTI->PR=1<<15; //清除LINE15上的中断标志位  
}[/mw_shl_code]

通过软件仿真查看寄存器配置都一样,请教大神为什么寄存器版进入不了外部中断。


最佳答案

查看完整内容[请看2#楼]

因为你屏蔽了delay_init,导致delay工作不正常,在中断服务函数里面,有用到delay,直接就卡死。
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2017-1-11 23:43:24 | 显示全部楼层
因为你屏蔽了delay_init,导致delay工作不正常,在中断服务函数里面,有用到delay,直接就卡死。
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复

使用道具 举报

3

主题

13

帖子

0

精华

新手上路

积分
33
金钱
33
注册时间
2017-1-11
在线时间
6 小时
 楼主| 发表于 2017-1-12 10:32:56 | 显示全部楼层
顶一下,大神们救救我啊,不能让新手寒心啊!
回复

使用道具 举报

11

主题

94

帖子

0

精华

初级会员

Rank: 2

积分
188
金钱
188
注册时间
2016-12-12
在线时间
55 小时
发表于 2017-1-12 10:35:57 | 显示全部楼层
NVIC_Configuration();// 设置中断优先级分组  

    EXTIX_Init();       //外部中断初始化

这两个函数的实现是什么样的?
回复

使用道具 举报

3

主题

13

帖子

0

精华

新手上路

积分
33
金钱
33
注册时间
2017-1-11
在线时间
6 小时
 楼主| 发表于 2017-1-12 12:50:17 | 显示全部楼层
不死鸟 发表于 2017-1-12 10:35
NVIC_Configuration();// 设置中断优先级分组  

    EXTIX_Init();       //外部中断初始化

库函数的实现是如下:
[mw_shl_code=c,true]void NVIC_Configuration(void)
{

    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);        //设置NVIC中断分组2:2位抢占优先级,2位响应优先级

}
//外部中断初始化函数
void EXTIX_Init(void)
{

          EXTI_InitTypeDef EXTI_InitStructure;
          NVIC_InitTypeDef NVIC_InitStructure;

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

          KEY_Init();//初始化按键对应io模式

    //GPIOC.5 中断线以及中断初始化配置
          GPIO_EXTILineConfig(GPIO_PortSourceGPIOC,GPIO_PinSource5);

          EXTI_InitStructure.EXTI_Line=EXTI_Line5;
          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寄存器

    //GPIOA.15          中断线以及中断初始化配置
          GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource15);

          EXTI_InitStructure.EXTI_Line=EXTI_Line15;
          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寄存器

    //GPIOA.0          中断线以及中断初始化配置
          GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource0);

           EXTI_InitStructure.EXTI_Line=EXTI_Line0;
          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寄存器



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


           NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn;                        //使能按键所在的外部中断通道
          NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02;        //抢占优先级2,
          NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x00;                                        //子优先级1
          NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;                                                                //使能外部中断通道
          NVIC_Init(&NVIC_InitStructure);

}[/mw_shl_code]

寄存器的函数实现是:
[mw_shl_code=c,true]//外部中断初始化程序
//初始化PA0,PC5,PA15为中断输入.
void EXTI_Init(void)
{
        KEY_Init();
        Ex_NVIC_Config(GPIO_A,0,RTIR);                 //上升沿触发
        Ex_NVIC_Config(GPIO_C,5,FTIR);                //下降沿触发
        Ex_NVIC_Config(GPIO_A,15,FTIR);                //下降沿触发

        MY_NVIC_Init(2,2,EXTI0_IRQn,2);            //抢占2,子优先级2,组2
        MY_NVIC_Init(2,1,EXTI9_5_IRQn,2);          //抢占2,子优先级1,组2
        MY_NVIC_Init(2,0,EXTI15_10_IRQn,2);        //抢占2,子优先级0,组2          
}

//外部中断配置函数
//只针对GPIOA~G;不包括PVD,RTC和USB唤醒这三个
//参数:
//GPIOx:0~6,代表GPIOA~G
//BITx:需要使能的位;
//TRIM:触发模式,1,下升沿;2,上降沿;3,任意电平触发
//该函数一次只能配置1个IO口,多个IO口,需多次调用
//该函数会自动开启对应中断,以及屏蔽线               
void Ex_NVIC_Config(u8 GPIOx,u8 BITx,u8 TRIM)
{
        u8 EXTADDR;
        u8 EXTOFFSET;
        EXTADDR=BITx/4;//得到中断寄存器组的编号
        EXTOFFSET=(BITx%4)*4;
        RCC->APB2ENR|=0x01;//使能io复用时钟                         
        AFIO->EXTICR[EXTADDR]&=~(0x000F<<EXTOFFSET);//清除原来设置!!!
        AFIO->EXTICR[EXTADDR]|=GPIOx<<EXTOFFSET;//EXTI.BITx映射到GPIOx.BITx
        //自动设置
        EXTI->IMR|=1<<BITx;//  开启line BITx上的中断
        //EXTI->EMR|=1<<BITx;//不屏蔽line BITx上的事件 (如果不屏蔽这句,在硬件上是可以的,但是在软件仿真的时候无法进入中断!)
        if(TRIM&0x01)EXTI->FTSR|=1<<BITx;//line BITx上事件下降沿触发
        if(TRIM&0x02)EXTI->RTSR|=1<<BITx;//line BITx上事件上升降沿触发
}           

//设置NVIC分组
//NVIC_Group:NVIC分组 0~4 总共5组                   
void MY_NVIC_PriorityGroupConfig(u8 NVIC_Group)         
{
        u32 temp,temp1;          
        temp1=(~NVIC_Group)&0x07;//取后三位
        temp1<<=8;
        temp=SCB->AIRCR;  //读取先前的设置
        temp&=0X0000F8FF; //清空先前分组
        temp|=0X05FA0000; //写入钥匙
        temp|=temp1;          
        SCB->AIRCR=temp;  //设置分组                                                        
}
//设置NVIC
//NVIC_PreemptionPriority:抢占优先级
//NVIC_SubPriority       :响应优先级
//NVIC_Channel           :中断编号
//NVIC_Group             :中断分组 0~4
//注意优先级不能超过设定的组的范围!否则会有意想不到的错误
//组划分:
//组0:0位抢占优先级,4位响应优先级
//组1:1位抢占优先级,3位响应优先级
//组2:2位抢占优先级,2位响应优先级
//组3:3位抢占优先级,1位响应优先级
//组4:4位抢占优先级,0位响应优先级
//NVIC_SubPriority和NVIC_PreemptionPriority的原则是,数值越小,越优先          
void MY_NVIC_Init(u8 NVIC_PreemptionPriority,u8 NVIC_SubPriority,u8 NVIC_Channel,u8 NVIC_Group)         
{
        u32 temp;       
        MY_NVIC_PriorityGroupConfig(NVIC_Group);//设置分组
        temp=NVIC_PreemptionPriority<<(4-NVIC_Group);          
        temp|=NVIC_SubPriority&(0x0f>>NVIC_Group);
        temp&=0xf;//取低四位  
        NVIC->ISER[NVIC_Channel/32]|=(1<<NVIC_Channel%32);//使能中断位(要清除的话,相反操作就OK)
        NVIC->IP[NVIC_Channel]|=temp<<4;//设置响应优先级和抢断优先级                                                           
} [/mw_shl_code]

求大神指点
回复

使用道具 举报

3

主题

13

帖子

0

精华

新手上路

积分
33
金钱
33
注册时间
2017-1-11
在线时间
6 小时
 楼主| 发表于 2017-1-12 16:05:42 | 显示全部楼层
顶起来啊大神们帮帮忙
回复

使用道具 举报

3

主题

13

帖子

0

精华

新手上路

积分
33
金钱
33
注册时间
2017-1-11
在线时间
6 小时
 楼主| 发表于 2017-1-14 10:29:47 | 显示全部楼层
我中断函数里把所有delay相关的都屏蔽啊
回复

使用道具 举报

3

主题

13

帖子

0

精华

新手上路

积分
33
金钱
33
注册时间
2017-1-11
在线时间
6 小时
 楼主| 发表于 2017-1-16 09:16:05 | 显示全部楼层
正点原子 发表于 2017-1-11 23:43
因为你屏蔽了delay_init,导致delay工作不正常,在中断服务函数里面,有用到delay,直接就卡死。

原子哥,我的问题没解决呢啊,为啥设置为已解决啊。“我中断函数里把所有delay相关的都屏蔽了”
回复

使用道具 举报

120

主题

7878

帖子

13

精华

资深版主

Rank: 8Rank: 8

积分
12012
金钱
12012
注册时间
2013-9-10
在线时间
427 小时
发表于 2017-1-16 17:19:57 | 显示全部楼层
确定所以延时函数都注释掉了?
回复

使用道具 举报

3

主题

13

帖子

0

精华

新手上路

积分
33
金钱
33
注册时间
2017-1-11
在线时间
6 小时
 楼主| 发表于 2017-1-16 20:04:33 | 显示全部楼层
八度空间 发表于 2017-1-16 17:19
确定所以延时函数都注释掉了?

确定,我花了半小时写的这个帖子,尽可能的把涉及到的代码都粘上去了。楼下发个附件,您可以确认下。
回复

使用道具 举报

3

主题

13

帖子

0

精华

新手上路

积分
33
金钱
33
注册时间
2017-1-11
在线时间
6 小时
 楼主| 发表于 2017-1-16 20:13:25 | 显示全部楼层
代码见附件,您确认下
回复

使用道具 举报

3

主题

13

帖子

0

精华

新手上路

积分
33
金钱
33
注册时间
2017-1-11
在线时间
6 小时
 楼主| 发表于 2017-1-16 20:14:29 | 显示全部楼层
不好意思,楼上没上传成功,再传一次

ALIENTEK MiniSTM32 实验4 外部中断实验.rar

771.4 KB, 下载次数: 330

回复

使用道具 举报

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

本版积分规则



关闭

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

正点原子公众号

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

GMT+8, 2025-6-23 20:16

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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