STM32f407系列之中断

1、基本概念

(1)中断:即CPU在正常执行程序的过程中,遇到外部(例如常见的按键中断)/内部(例如定时器中断)的紧急事件需要处理,暂时中断(中止)当前程序的执行,而转去为事件服务,待服务完毕,再返回到暂停处(断点)继续执行原来的程序。

(2)中断优先级:事件具有不同的轻重、缓急程度。系统工作时,我们总希望最紧急的事件优先被处理,以保证系统的实时性。这就引出了中断的优先级、中断嵌套问题。与中断控制器相连的每条线叫做中断线,要使用中断线,就得进行中断线的申请,就是IRQ,把申请一条中断线称为申请一个IRQ或者是申请一个中断号。IRQ和向量之间的映射可以通过中断控制器进行修改。

中断优先级的一个意义是出现多个中断同时触发,但是不能同时处理,所以先后顺序之分,要根据实际上的运行环境优先处理重要的中断。STM32 对中断优先级进行分组,共 5 组,组 0~4,这些分组是用于指定当前M4支持多少级抢占优先级和多少个响应优先级。同时,对每个中断设置一个抢占优先级和一个响应优先级。函数原型如下:

/**
  * @brief  Configures the priority grouping: pre-emption priority and subpriority.
  * @param  NVIC_PriorityGroup: specifies the priority grouping bits length. 
  *   This parameter can be one of the following values:
  *     @arg NVIC_PriorityGroup_0: 0 bits for pre-emption priority    //不支持抢占优先级
  *                               1 bits for subpriority             //支持16级响应优先级(0 ~ 15)
  *     @arg NVIC_PriorityGroup_1: 1 bits for pre-emption priority    //支持2级抢占优先级(0 ~ 1)
  *                                3 bits for subpriority             //支持8级响应优先级(0 ~ 7)
  *     @arg NVIC_PriorityGroup_2: 2 bits for pre-emption priority    //支持4级抢占优先级(数值0~3)
  *                                2 bits for subpriority             //支持4级响应优先级(数值0~3)
  *     @arg NVIC_PriorityGroup_3: 3 bits for pre-emption priority    //支持8级抢占优先级
  *                                1 bits for subpriority             //支持2级响应优先级
  *     @arg NVIC_PriorityGroup_4: 4 bits for pre-emption priority    //支持16级抢占优先级(数值0~15)
  *                                0 bits for subpriority             //不支持响应优先级
  * @note   When the NVIC_PriorityGroup_0 is selected, IRQ pre-emption is no more possible. 
  *         The pending IRQ priority will be managed only by the subpriority. 
  * @retval None
  */
void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup)

(3)抢占优先级与响应优先级

A.高抢占优先级是可以打断正在进行的低抢占优先级的中断。抢占优先级若相同,则不会出现抢占的过程

B.抢占优先级相同的中断,高响应优先级不可以打断低响应优先级的中断。

C.抢占优先级相同的中断,当两个中断同时发生的情况下,哪个响应优先级高,哪个先执行(响应)。

D.抢占优先级相同且响应优先级相同的中断,假如同时发生,会按照硬件内部固定的优先级执行

2、代码思路

#include "stm32f4xx.h"
static GPIO_InitTypeDef   GPIO_InitStructure;
static EXTI_InitTypeDef   EXTI_InitStructure;
static NVIC_InitTypeDef   NVIC_InitStructure;

void delay(void)
{
    uint32_t i=0xA00000;
    while(i--);
}

void exit_init()
{
    //打开端口A的硬件时钟,就是为端口A供电
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
    //打开系统配置硬件时钟,就是为系统配置硬件时钟供电
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
    
    //配置PA0引脚为输入模式
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
    
    SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA, EXTI_PinSource0);//将中断0连接PA0
    
    //配置外部中断0
    EXTI_InitStructure.EXTI_Line = EXTI_Line0;                   //配置外部中断0
    EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;          //中断模式
    EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;      //下降沿触发
    EXTI_InitStructure.EXTI_LineCmd = ENABLE;//允许外部中断0工作
    EXTI_Init(&EXTI_InitStructure);
    
    //配置NVIC
    NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;             //中断号
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x0F; //抢占优先级
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x0F;        //响应优先级
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;              //打开外部中断0通道
    NVIC_Init(&NVIC_InitStructure);
}


#define PFout(x) *(volatile uint32_t *)(0x42000000+(GPIOF_BASE+0x14-0x40000000)*32+(x)*4)
#define PAin(x) *(volatile uint32_t *)(0x42000000+(GPIOA_BASE+0x10-0x40000000)*32+(x)*4)

int main()
{
    
    //打开端口F的硬件时钟,就是为端口F供电
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE);
    
    //配置引脚
    GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9;
    GPIO_InitStructure.GPIO_Mode=GPIO_Mode_OUT;
    GPIO_InitStructure.GPIO_Speed=GPIO_High_Speed;
    GPIO_InitStructure.GPIO_OType=GPIO_OType_PP;
    GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_NOPULL;
    GPIO_Init(GPIOF,&GPIO_InitStructure);//为何传地址
    
    exit_init();
    PFout(9)=1;
    while(1)
    {
        
    }
}
void EXTI0_IRQHandler(void)
{
    //检测标志位
    if(EXTI_GetITStatus(EXTI_Line0) != RESET)
        {
            PFout(9)=0;
            delay();
            PFout(9)=1;
            delay();
            //清空标志位
            EXTI_ClearITPendingBit(EXTI_Line0);
        }
 }

3、总结

配置中断的思路大致为:

端口A硬件时钟使能

SYSCFG硬件时钟使能

配置引脚的工作模式

将引脚连接到外部中断

中断触发方式:下降沿触发、上升沿触发

允许外部中断引脚申请中断请求

优先级的配置

中断服务函数

4.思考题

配置两个中断,设置不同的抢占优先级和响应优先级,观察优先级不同引起的现象的区别。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值