STM32关于开关总中断的问题

NVIC 共支持 1 至 240 个外部中断输入(通常外部中断写作 IRQs)。 具体的数值由芯片厂商在设计芯片时决定。此外, NVIC 还支持一个“永垂不朽”的不可屏蔽中断(NMI)输入。NMI 的实际功能亦由芯片制造商决定。在某些情况下, NMI 无法由外部中断源控制。

在 STM32/Cortex-M3 中是通过改变 CPU 的当前优先级来允许或禁止中断。​  

异常掩蔽寄存器PRIMASK位只允许 NMI 和 hard  fault 异常,其他中断/异常都被屏蔽(当前 CPU 优先级=0,为可编程优先级中的最高优先级) 。 

该寄存器可以通过 MRS 和 MSR 以下例方式访问:

​1. 关中断MOV R0, #1

             MSR PRIMASK, R0

​2. 开中断MOV R0, #0

             MSR PRIMASK, R0 ​

此外,还可以通过CPS指令快速完成上述功能:​

CPSID I;//PRIMASK=1 ; 关中断

CPSIE  I;//PRIMASK=0 ; 开中断

CPSID F;//FAULTMASK=1, ; 关异常

CPSIE  F;//FAULTMASK=0 ; 开异常

异常掩蔽寄存器FAULTMASK位:只允许 NMI,其他所有中断/异常都被屏蔽(当前 CPU 优先级=-1)。注意的是,FAULTMASK会在异常退出时自动清零。

掩蔽寄存器虽然能一手遮天,却都动不了NMI,因为NMI是用在最危急的情况下的。因此系统为它开出单行道,无需挂号只是不要迟到。

​在 STM32 固件库中(stm32f10x_nvic.c 和 stm32f10x_nvic.h) 定义了四个函数操作 PRIMASK 位和FAULTMASK 位,改变 CPU 的当前优先级,从而达到控制所有中断的目的。   

​下面两个函数等效于关闭总中断:  

​void NVIC_SETPRIMASK(void);   void NVIC_SETFAULTMASK(void);   

​下面两个函数等效于开放总中断:  

​void NVIC_RESETPRIMASK(void);   void NVIC_RESETFAULTMASK(void);  

 上面两组函数要成对使用,不能交叉使用。 

 例如: 第一种方法(常用): NVIC_SETPRIMASK();   //关闭总中断  

                                ​NVIC_RESETPRIMASK();//开放总中断   

​第二种方法:  NVIC_SETFAULTMASK();      //关闭总中断  

               ​      NVIC_RESETFAULTMASK();    //开放总中断

在 3.0 的库中上述库函数已经没有​,可以用下列方法实现:

​#define CLI()      __set_PRIMASK(1)  

​#define SEI()      __set_PRIMASK(0) 

或者在编译器里使用:

__disable_irq();   // 关闭总中断

​__enable_irq();    // 开启总中断​

补充1:​异常掩蔽寄存器BASEPRI

在更精巧的设计中,需要对中断掩蔽进行更细腻的控制——只掩蔽优先级低于某一阈值的中断(它们的优先级在数字上大于等于某个数)。那么这个数存储在哪里?就存储在BASEPRI中。

不过,如果往BASEPRI中写0,则另当别论——BASEPRI将停止掩蔽任何中断。

如果你需要掩蔽所有优先级不高于0x60的中断,则可以如下编程:

​MOV R0, #0x60

MSR BASEPRI, R0

​如果需要取消 BASEPRI 对中断的掩蔽,则示例代码如下:

​MOV R0, #0

MSR BASEPRI, R0

补充2:关闭全局中断时需要注意的问题(未验证是否确有此问题)

STM32在使用时有时需要禁用全局中断​。但测试发现一个问题,在关闭总中断后,如果有中断触发,虽然此时不会引发中断,但在调用__enable_irq()开启总中断后,MCU会立即处理之前触发的中断。这说明__disable_irq()只是禁止CPU去响应中断,没有真正的去屏蔽中断的触发,中断发生后,相应的寄存器会将中断标志置位,在__enable_irq()开启中断后,由于相应的中断标志没有清空,因而还会触发中断。

所以要想禁止所有中断,必须对逐个模块的中断进行Disable操作,由于每个模块中断源有很多,对逐个中断Disable的话比较复杂,较为简单的方法是通过XXX_ClearITPendingBit()清除中断标志或者直接通过XXX_DeInit()来清除寄存器的状态。这样在__enable_irq()开启总中断后,MCU就不会响应之前触发的中断了。

  • 3
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
STM32中,关闭和开启中断的函数是通过操作相关的寄存器来实现的。要关闭中断,可以使用函数`__disable_irq()`。这个函数会禁用所有中断,包括外部中断和内部中断。要开启中断,可以使用函数`__enable_irq()`。这个函数会重新启用所有中断。需要注意的是,在关闭中断期间,任何触发中断的事件都不会引起中断服务函数的执行。而在开启中断之后,如果有中断事件发生,中断服务函数会被执行。在配置STM32中断时,还需要注意关闭和开启NVIC中断通道和EXTI中断通道。NVIC中断通道是用来管理中断优先级的,可以使用相关的寄存器进行配置。EXTI中断通道是用来管理外部中断的,可以通过配置相关的寄存器来设置外部中断的触发方式和优先级。在编写中断服务函数时,需要使用事先定义好的函数名。在STM32中,IO口外部中断函数一共有7个,可以根据需要选择合适的函数进行编写。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [STM32如何关闭,开启中断](https://blog.csdn.net/qq_41245148/article/details/107787776)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *3* [STM32外部中断](https://blog.csdn.net/m0_62005595/article/details/128071557)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值