173 2438 5004
KEROS加密芯片——品牌直销 | 免费样品 | 技术支持
当前位置:网站首页 > 资讯中心 正文 资讯中心

stm32f4怎么设置中断向量表(stm32中断向量表理解)

htxw 2022-12-05 资讯中心 12 ℃

关于STM32的中断向量表的重映射的问题

问题一:想要解释你的疑惑先要明白几个道理

1、无论向量表是否重映射过,复位后都是从0地址的向量表处获取SP和复位入口。

2、0地址处的中断向量表,通常是ROM地址。通常只能通过指定链接地址,然后烧录改写。

3、在一些带升级功能的产品中,通常分为boot和app两部分。boot通常出产以后就不再变化,使用0地址向量表,必须通过Jtag之类的工具才能改写。而boot中带有下载功能个(USB、串口或SPI),用户可以根据需要下载APP。

4、注意第2条,APP通常需要自己设计中断服务。如果不重映射,只能再boot处设计查表程序,通过boot跳转,效率不高。而擦写0地址向量,如果在升级过程中掉电,则boot也无法启动。因此,需要进入APP后,重映射向量表。

问题二:你的理解的对的。然而,0地址处的中断向量表区域通常不放代码。芯片在FLASH地址分配上,也很少有将FLASH地址紧密的排在向量表之后的。因此,并不影响。

STM32中断实验了该怎么办?

具体情况具体对待,你可以看我下面的实验对号入座来分析你的问题:

实验目的:

当按键按下时,让PF10引脚的LED灯亮,

当按键再次按下时,让PF10引脚的LED灯灭;

无论按下与否,PF9引脚的LED灯循环闪烁;

实验步骤:

实验程序:

[cpp] view plain copy

/***********************************led.c*********************************/

#include "stm32f4xx.h"  //在SYSTEM目录下可以找到

#include "sys.h"

void LED_Init(void){

RCC-AHB1ENR = 15;  //使能GPIO端口的F时钟

GPIO_Set(GPIOF,PIN9|PIN10,GPIO_MODE_OUT,GPIO_OTYPE_PP,GPIO_SPEED_25M,GPIO_PUPD_PU);

PFout(9) = 1;

PFout(10) = 1;

}

[cpp] view plain copy

/***********************************led.h*********************************/

#ifndef _LED_H

#define _LED_H

void LED_Init(void);

#endif

[cpp] view plain copy

/********************************************key.c***************************************/

#include "sys.h"

void Key_Init(void){

RCC-AHB1ENR|=14;     //使能PORTE时钟

//void GPIO_Set(GPIO_TypeDef* GPIOx,u32 BITx,u32 MODE,u32 OTYPE,u32 OSPEED,u32 PUPD);//GPIO设置函数

GPIO_Set(GPIOE,PIN3,GPIO_MODE_IN,0,0,GPIO_PUPD_PU); //PE3设置上拉输入,这样的话,

//当按键没有按下时,默认电平为高;

}

[cpp] view plain copy

/********************************************key.h***************************************/

#ifndef _KEY_H

#define _KEY_H

void Key_Init(void);

#endif

[cpp] view plain copy

/************************************exti.c********************************/

#include "sys.h"

#include "delay.h"

#include "stm32f4xx.h"

/*

本示例的作用就是,

当按键按下时,蜂鸣器发出声音,

当按键再次按下时,蜂鸣器静音;

*/

/*

中断初始化函数:

主要是关于寄存器的相关配置

*/

void EXTI3_Init(void){

//方法一:

RCC-APB2ENR |= 1  14;  //开启SYSCFG时钟

SYSCFG-EXTICR[0] |= 0x4  12;//设置IO口与中断线的映射关系;

EXTI-IMR |= 1  3;  //开启对应中断线上的中断

EXTI-FTSR |= 1  3;  //设置中断触发条件

//SCB和NVIC,可参考STM32F3与STM32F4系列Cortex M4内核编程手册.pdf

SCB-AIRCR |= 0x5  8; //设置分组

NVIC-IP[9] |= 0; //设置优先级,具体可分析MY_NVIC_Init()函数;

NVIC-ISER[0] |= 1  9;  //使能中断;

//方法二:

/************************************

使用SYSTEM目录下提供的API来实现,

具体可参考正点原子示例

************************************/

}

void EXTI3_IRQHandler(void){

/*

此按键,在按键按下时,处理不是很到位,

有待进一步改进,主要是在连按那一个环节。

*/

delay_ms(20);  //消抖

if(PEin(3) == 0){

PFout(10) = !PFout(10);

}

/*

在中断里边最后记得清中断:

*/

EXTI-PR |= 1  3;

}

[cpp] view plain copy

/*************************************exti.h*******************************/

#ifndef _EXTI_H

#define _EXTI_H

void EXTI3_Init(void);

#endif

[cpp] view plain copy

/*************************************test.c*******************************/

#include "sys.h"

#include "delay.h"

#include "key.h"

#include "beep.h"

#include "exti.h"

#include "led.h"

//int i = 0;

int main(void){

Stm32_Clock_Init(336,8,2,7);//设置时钟,168Mhz

delay_init(168);        //初始化延时函数

Beep_Init();

Key_Init();

EXTI3_Init();

LED_Init();

while(1){

PFout(9) = 0;

delay_ms(500);

PFout(9) = 1;

delay_ms(500);

}

}

实验分析:

我们主要分析一下exti.c中的寄存器设置的这几个步骤:

1. RCC-APB2ENR |= 1 14;

这一步的作用就是使能SYSCFG时钟,

在使用外部中断的时候一定要先使能SYSCFG时钟;

2. SYSCFG-EXTICR[0] |= 0x4 12;

这一步的作用就是设置IO口与中断线的映射关系;

那么问题来了,我如何知道的我的IO口与哪根中断线是关联起来的呢?

而我们是通过KEY1按键,对应的IO口就是PE3,所以由上图的映射关系,我们知道,我们应该选择中断线3与之对应;

在官方提供的头文件stm32f4xx.h中,我们可以看到:

[cpp] view plain copy

typedef struct

{

__IO uint32_t MEMRMP;       /*! SYSCFG memory remap register,                      Address offset: 0x00      */

__IO uint32_t PMC;          /*! SYSCFG peripheral mode configuration register,     Address offset: 0x04      */

__IO uint32_t EXTICR[4];    /*! SYSCFG external interrupt configuration registers, Address offset: 0x08-0x14 */

uint32_t      RESERVED[2];  /*! Reserved, 0x18-0x1C                                                          */

[cpp] view plain copy

__IO uint32_t CMPCR;        /*! SYSCFG Compensation cell control register,         Address offset: 0x20      */

SYSCFG_TypeDef;

结合上述三幅图,我们可以得知:

由于PE3对应的中断线为EXTI3,所以,我们我们这里仅需配置EXTI3,而EXTI3是在SYSCFG_EXTICR1中的;

所以我们仅需配置SYSCFG_EXTICR1寄存器的12位-15位为0100,而SYSCFG_EXTICR1寄存器在配置文件中,

对应的是SYSCFG-EXTICR[0],所以我们就写成了SYSCFG-EXTICR[0] |= 0x4 12;

3. EXTI-IMR |= 1 3;

这条语句的作用就是:开启对应中断线上的中断

由于我们操作的中断线是EXTI3,而IMR寄存器各位解释如下:

所以对应的,我们操作EXTI_IMR寄存器的第3位MR3即可;

所以这条语句就写成了:EXTI-IMR |= 1 3

4. EXTI-FTSR |= 1 3;

这条语句的作用就是设置中断触发条件;

在我的开发板中,当按键按下时,其端口就会变成低电平,在没有按下时,其是为高电平的;

因为我们key.c中,将按键的引脚设置成了上拉;所以在这里,我得将其设置成下降沿触发;

与此同时,查看EXTI_FTSR寄存器,可以看到:

又由于我们这条中断线是中断线3,所以这条语句就写成了:EXTI-FTSR |= 1 3

5. SCB-AIRCR |= 0x5 8;

这条语句的作用就是:设置分组;

所以,在这里我们只需设置SCB的AIRCR的 bit10-8即可;查看SCB的结构体,得知:

[cpp] view plain copy

typedef struct

{

__I  uint32_t CPUID;                   /*! Offset: 0x000 (R/ )  CPUID Base Register                                   */

__IO uint32_t ICSR;                    /*! Offset: 0x004 (R/W)  Interrupt Control and State Register                  */

__IO uint32_t VTOR;                    /*! Offset: 0x008 (R/W)  Vector Table Offset Register                          */

__IO uint32_t AIRCR;                   /*! Offset: 0x00C (R/W)  Application Interrupt and Reset Control Register      */

__IO uint32_t SCR;                     /*! Offset: 0x010 (R/W)  System Control Register                               */

__IO uint32_t CCR;                     /*! Offset: 0x014 (R/W)  Configuration Control Register                        */

__IO uint8_t  SHP[12];                 /*! Offset: 0x018 (R/W)  System Handlers Priority Registers (4-7, 8-11, 12-15) */

__IO uint32_t SHCSR;                   /*! Offset: 0x024 (R/W)  System Handler Control and State Register             */

__IO uint32_t CFSR;                    /*! Offset: 0x028 (R/W)  Configurable Fault Status Register                    */

__IO uint32_t HFSR;                    /*! Offset: 0x02C (R/W)  HardFault Status Register                             */

__IO uint32_t DFSR;                    /*! Offset: 0x030 (R/W)  Debug Fault Status Register                           */

__IO uint32_t MMFAR;                   /*! Offset: 0x034 (R/W)  MemManage Fault Address Register                      */

__IO uint32_t BFAR;                    /*! Offset: 0x038 (R/W)  BusFault Address Register                             */

__IO uint32_t AFSR;                    /*! Offset: 0x03C (R/W)  Auxiliary Fault Status Register                       */

__I  uint32_t PFR[2];                  /*! Offset: 0x040 (R/ )  Processor Feature Register                            */

__I  uint32_t DFR;                     /*! Offset: 0x048 (R/ )  Debug Feature Register                                */

__I  uint32_t ADR;                     /*! Offset: 0x04C (R/ )  Auxiliary Feature Register                            */

__I  uint32_t MMFR[4];                 /*! Offset: 0x050 (R/ )  Memory Model Feature Register                         */

__I  uint32_t ISAR[5];                 /*! Offset: 0x060 (R/ )  Instruction Set Attributes Register                   */

uint32_t RESERVED0[5];

__IO uint32_t CPACR;                   /*! Offset: 0x088 (R/W)  Coprocessor Access Control Register                   */

} SCB_Type;

所以,在这里,我们把这条语句写成了SCB-AIRCR |= 0x5 8;

亦即设置成了101,也就是抢占优先级占2位,响应优先级占2位;

注:抢占优先级和响应优先级一样,其值越低则表示其优先级越高;

上述说的子优先级也就是我们说的响应优先级;

6. NVIC-IP[9] |= 0;

有上条语句,我们可以得知:IP寄存器由240个8bit的寄存器组成,每个可屏蔽中断占用8bit,这样总共可以表示240个可屏蔽中断,

而STM32F4只用到了其中的82个。IP[81]~IP[0]分别对应中断81~0.而每个可屏蔽中断占用的8bit并没有全部使用,而是只用了高4位;

这4位,又分为抢占优先级和响应优先级;抢占优先级在前,响应优先级在后;也就是说,抢占优先级在高位,响应优先级在低位;

而我们又知道:我们这个中断是外部中断3,所以查看中断向量表可知:

由此可知,EXTI3在中断的位置为9,所以我们只需要设置NVIC-IP[9] 即可;

在这里我们把NVIC-IP[9] |= 0;则表示,我们设置外部中断3的抢占优先级为0,响应优先级也为0,其各占2位;

7. NVIC-ISER[0] |= 1 9;

这一步的作用就是使能中断;

ISER是一个中断使能寄存器组;这里用8个32位寄存器来控制,每个位控制一个中断;但是STM32F4的可屏蔽中断

最多只有82个,所以对我们来说,有用的就是三个(ISER[0~2]),总共可以表示96个中断;而STM32F4只用了其中的

前82个中断,ISER[0]的0bit~31分别对应中断0~31;ISER[1]的bit0~32对应中断32~63;ISER[2]的bit0~32对应中断64~81;

在这里,我们知道:我们的EXTI3对应的中断的位置是9,所以我们只需设置ISER[0]的第9位即可;所以我们在这里就将这条

语句写成了:NVIC-ISER[0] |= 1 9;

8.至于外部中断函数的名称如何编写,我们可以从启动文件中去找到;

当我们设置的外部中断函数与启动文件中定义的名称一致时,

那么当这个中断条件满足时,就会去中断函数里边执行其函数体;

我们只需要在中断发生后,记得清中断,防止中断重复发生;

注意事项:

在本实验中,关于按键处理那一块,处理不是很到位,

主要应该是处在连按这一块,暂时没去整它,待我需要时,再去整整。

转载于 ,感谢原作者非常详细的指导学习。

STM32 中断初识

前段时间经常用stm32f4 discovery,但是因为对NVIC , EXTI不是很了解,所以使用的过程中一直都在避免使用中断,这两天没什么事决定来学习一下stm32 的中断,写一下自己的心得,如有谬误之处,欢迎指正。 

我把用到的几份文档寄存器的文档(RM0090)、《Cortex-M技术参考手册》、《Cortex™-M4 Devices Generic User Guide》、《ARMv7-M Architecture Reference Manual》放在百度云,需要的自取

 密码:4g91网页链接

stm32f439中怎么让程序在片外SDRAM中执行

要想代码在SRAM中运行。有几个步骤需要做。

1、中断向量表需要修改,这样才能把中断向量表重新映射一遍。

#ifdef VECT_TAB_SRAM

NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0);

#else

NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);

#endif

2、分散加载要设置,就是设置你的代码段和数据段在ram的运行地址,就是arm手册中的运行域。

3、你的代码相当于boot 和app模式,boot在flash中执行,然后把app从nor flash搬到sram所在地址。

你的运行域地址就是代码搬移到sram所在的地址

STM32中,中断向量表,中断向量,中断服务函数3者关系。stm32中是处理中断事件的具体过程是怎么样的?

中断向量你可以理解为中断号。中断服务函数你可以理解为产生中断系统所要去调用的函数,用来处理当前中断。中断向量表就是所有中断服务函数的首地址组成的一个数组。你可以理解为一个指针数组,其中顺序严格按照中断号由小到大排列,故系统可以找到中断向量所对应的中断服务函数。

处理事件过程请看手册的图。我已经给你截下来了。

stm32中断向量表是怎么放在指定的地址的

1、keil设置ram起始为0x20000100,我们在0x20000000~0x20000100放中断向量表,其他给程序用

2、设置NVIC_SetVectorTable(NVIC_VectTab_FLASH,0);

3、跳到C时把中断向量表拷贝到0x20000000

stm32f4怎么设置中断向量表的介绍到此就结束了,感谢您耐心阅读,谢谢。

本文标签:stm32f4怎么设置中断向量表

<