×
单片机 > 单片机程序设计 > 详情

STM学习笔记--STM32F10X中断

发布时间:2020-06-06 发布时间:
|
CM3支持256个中断,16个内核中断+240个外部中断,并具有256级可编程中断

STM32支持76个中断,16个内核中断+60个外部中断,16个可编程优先级

 

16个内核中断:每个中断占用地址为0X0000_0004

 

 

 
60个可屏蔽中断:其中0,1,2,3,4表示中断编号IRQ Channels在STM32F10x_lib.h程序中体现

 

 

 

 
 

 16个中断优先级

先看看嵌套中断向量控制器的定义STM32F10X_map.h

/*------------------------ Nested Vectored Interrupt Controller --------------*/

typedef struct

{

  vu32 ISER[2];          //Interrupt set-enable registers   2个32BITS

  u32  RESERVED0[30]; 

  vu32 ICER[2];          //Interrupt clear-enable registers  

  u32  RSERVED1[30];  

  vu32 ISPR[2];          //Interrupt set-pending registers

  u32  RESERVED2[30]; 

  vu32 ICPR[2];          //Interrupt clear-pending registers

  u32  RESERVED3[30];

  vu32 IABR[2];         //Interrupt active bit registers 只读寄存器

  u32  RESERVED4[62];

  vu32 IPR[15];         //Interrupt priority registers

} NVIC_TypeDef;

 

 

其中vu32 IPR[15],表示Interrupt Priority Registers中断优先级寄存器

表示15个32bit寄存器,每个屏蔽中断占用8位,只用到高4位,低4位没用到。

每个屏蔽寄存器拥有的中断编号为4个,即32bit/8bit=4

 

IPR[0]—[31-24] [23-16] [15-8] [7-4] 对应中断3,2,1,0

IPR[1]—[31-24] [23-16] [15-8] [7-4] 对应中断7,6,5,4

IPR[2]—[31-24] [23-16] [15-8] [7-4] 对应中断11,10,9,8

IPR[3]—[31-24] [23-16] [15-8] [7-4] 对应中断15,14,13,12

IPR[4]—[31-24] [23-16] [15-8] [7-4] 对应中断19,18,17,16

IPR[5]—[31-24] [23-16] [15-8] [7-4] 对应中断23,22,21,20

IPR[6]—[31-24] [23-16] [15-8] [7-4] 对应中断27,26,25,24

IPR[7]—[31-24] [23-16] [15-8] [7-4] 对应中断31,30,29,28

IPR[8]—[31-24] [23-16] [15-8] [7-4] 对应中断35,34,33,32

IPR[9]—[31-24] [23-16] [15-8] [7-4]  对应中断39,38,37,36

IPR[10]—[31-24] [23-16] [15-8] [7-4] 对应中断43,42,41,40

IPR[11]—[31-24] [23-16] [15-8] [7-4] 对应中断47,46,45,44

IPR[12]—[31-24] [23-16] [15-8] [7-4] 对应中断51,50,49,48

IPR[13]—[31-24] [23-16] [15-8] [7-4] 对应中断55,54,53,52

IPR[14]—[31-24] [23-16] [15-8] [7-4] 对应中断59,58,57,56

IPR[15]—[31-24] [23-16] [15-8] [7-4]           未使用     

 

 

STM32将中断分为5组,组数为0-5。由控制器SCB->AIRCR【10:8】寄存器控制

 

  

例如如果AIRCR为100,则60个中断(15个中断优先级寄存器)的每个中断的高3位为抢占优先级,低1位为响应优先级。那么抢占优先级可以设置7个,由000~111,而响应优先级只能为0或者1。数值越小,表示优先级越高,同时抢占优先级高于响应优先级。如果抢占优先级与响应优先级一致,则看哪个中断先发生,哪个先执行;高优先级的抢占优先级可以打断正在进行的低抢占优先级的,高响应优先级的不能打断低响应优先级的中断。

AIRCR—应用程序中断及复位控制寄存器,它是属于SCB中的一个。

//System control space memory map

typedef struct

{

  vuc32 CPUID;

  vu32 ICSR;

  vu32 VTOR;

  vu32 AIRCR;

  vu32 SCR;

  vu32 CCR;

  vu32 SHPR[3];

  vu32 SHCSR;

  vu32 CFSR;

  vu32 HFSR;

  vu32 DFSR;

  vu32 MMFAR;

  vu32 BFAR;

  vu32 AFSR;

} SCB_TypeDef;

  

  

如需修改SCB->AIRCR寄存器的值,首先得写入访问钥匙0X05FA,遵循读—改—写的操作步骤。

下面是设置NVIC分组函数:

//设置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_Group=0;~NVIC_Group=0X1111 1111&0X0000 0111 ,得temp1=0X0000 0111即第0组 ,0位抢占优先级,4位相应优先级

当NVIC_Group=1;~NVIC_Group=0X1111 1110&0X0000 0111 ,得temp1=0X0000 0110即第1组,1位抢占优先级,3位相应优先级

当NVIC_Group=2;~NVIC_Group=0X1111 1101&0X0000 0111 ,得temp1=0X0000 0101即第2组,2位抢占优先级,2位相应优先级

当NVIC_Group=3;~NVIC_Group=0X1111 1100&0X0000 0111 ,得temp1=0X0000 0100即第3组,3位抢占优先级,1位相应优先级

当NVIC_Group=4;~NVIC_Group=0X1111 1011&0X0000 0111 ,得temp1=0X0000 0011即第4组,4位抢占优先级,0位相应优先级

temp1<<=8;从第8位开始

接着读改写。先清空先前分组,temp&=0X0000F8FF; //清空先前分组,高16位为0,低16位BIT11-8,为1000。再写入钥匙,0X05FA0000,再写入分组temp1,最后将temp1写入SCB->AIRCR寄存器。

 

NVIC配置理解

NVIC初始化函数

//设置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;      

    u8 IPRADDR=NVIC_Channel/4;  //每组只能存4个,得到组地址

    u8 IPROFFSET=NVIC_Channel%4;//在组内的偏移

    IPROFFSET=IPROFFSET*8+4;    //得到偏移的确切位置

    MY_NVIC_PriorityGroupConfig(NVIC_Group);//设置分组

    temp=NVIC_PreemptionPriority<

    temp|=NVIC_SubPriority&(0x0f>>NVIC_Group);

    temp&=0xf;//取低四位

    if(NVIC_Channel<32)

{

NVIC->ISER[0]|=1<

}

    else

{

NVIC->ISER[1]|=1<

    NVIC->IPR[IPRADDR]|=temp<

}

(1)

       u8 IPRADDR=NVIC_Channel/4;   //每组只能存4个,得到组地址

       u8 IPROFFSET=NVIC_Channel%4; //在组内的偏移

       IPROFFSET=IPROFFSET*8+4;    //得到偏移的确切位置

对于窗口 WWDG_IPQChanel 的中断编号为0X00,那么

IPRADDR=0X00/4=0;           //得到第0组,IPR[0]

IPROFFSET=0X00%4=0;        //在组内的偏移为0

IPROFFSET=0X00*8+4=4;      //*8的意思是一个字节,就是跳过一个中断;+4的意思是,低4位无效

在IPR[IPRADDR]的中断组中,左移IPROFFSET的位置开始设置中断分组,temp为设置好的抢占优先级及响应优先级。

NVIC->IPR[IPRADDR]|=temp<

 

(2)

    u32 temp;      

       temp=NVIC_PreemptionPriority<

       temp|=NVIC_SubPriority&(0x0f>>NVIC_Group);   //相应优先级设置

       temp&=0xf;//取低四位

   

例:NVIC_Group分组为1,则为1位抢占优先级,3位响应优先级

则NVIC_PreemptionPriority<<4-1

temp|=NVIC_SubPriority&(0x0000 1111>>1)=(0000 0BBB)

temp  =  (?AAA A000)|(0000 0BBB)

      =  (?AAAABBB)

那么AAAA只能是从0000-0001,BBB能从000-111刚好对应起来。

temp&=0X0F,因为只是bit[7:4]有效。

 

(3)

     if(NVIC_Channel<32)

{

NVIC->ISER[0]|=1<

}

       else

{

NVIC->ISER[1]|=1<

 

则表示对应中断(0~59)使能,若中断编号小于32,则响应使能中断寄存器ISER[0],反之使能中断寄存器ISER[1]。

 

 

配置好NVIC后,接着配置外部中断寄存器EXTI

 

STM32的EXTI支持外部19个外部中断/事件,具有独立的中断屏蔽及状态位控制。

线0~15对应于外部IO的输入中断

线16连接到PVD

线17连接到RTC闹钟事件

线18连接到USB唤醒事件

/*------------------------ External Interrupt/Event Controller ---------------*/

typedef struct

{

  vu32 IMR;   //中断屏蔽寄存器    32bits,只有前19位有效

  vu32 EMR;  //事件屏蔽寄存器   

  vu32 RTSR;  //上升沿触发选择寄存器

  vu32 FTSR;  //下降沿触发选择寄存器

  vu32 SWIER; //软件中断寄存器    未设置IMR及EMR时,设置1,挂起PR,在PR清除后响应的SWIER清除

  vu32 PR;    //中断挂起寄存器    1表示中断响应,0表示未发生,向该寄存器写1,则清除挂起位

} EXTI_TypeDef

 

注:如果使用外部IO中断,还必须使用AFIO复用里的外部中断配置寄存器EXTICR。高16位保留,低16位有效。STM32任何一个IO口都可以配置成中断输入,但是IO口的数目远远大于中断线数(16个)。

GPIOA~GPIOG[15:0]分别对应中断线15:0,每条中断线对应于7个IO口。

例如:中断线0对应于GPIOA.0,GPIOB.0,GPIOC.0,GPIOD.0,GPIOE.0,GPIOF.0,GPIOG.0

 

 

 

EXTICR[0]~EXTICR[3]每个EXTICR只用到了低16位,高16位保留。

typedef struct

{

  vu32 EVCR;

  vu32 MAPR;

  vu32 EXTICR[4];

} AFIO_TypeDef

 

 

 

 

EXTICR[0] 对应于EXTI0[3:0],EXTI1[3:0],EXTI2[3:0],EXTI3[3:0]

 

EXTI0[3:0] 外部中断线0

0000àPA[0]   0001àPB[0]   0010àPC[0]  0011àPD[0]   0100àPE[0]  0101àPF[0]  0110àPG[0]

EXTI1[3:0] 外部中断线1

0000àPA[1]   0001àPB[1]   0010àPC[1]  0011àPD[1]   0100àPE[1]  0101àPF[1]  0110àPG[1]

EXTI2[3:0] 外部中断线2

0000àPA[2]   0001àPB[2]   0010àPC[2]  0011àPD[2]   0100àPE[2]  0101àPF[2]  0110àPG[2]

EXTI3[3:0] 外部中断线3

0000àPA[3]   0001àPB[3]   0010àPC[3]  0011àPD[3]   0100àPE[3]  0101àPF[3]  0110àPG[3]

                

EXTICR[1] 对应于EXTI4[3:0],EXTI5[3:0],EXTI6[3:0],EXTI7[3:0]   外部中断线4~7

EXTICR[2] 对应于EXTI8[3:0],EXTI9[3:0],EXTI10[3:0],EXTI11[3:0] 外部中断线8~11

EXTICR[3] 对应于EXTI12[3:0],EXTI13[3:0],EXTI14[3:0],EXTI15[3:0] 外部中断线12~15

 

 

/////////////////////////////////////////////////////////////////

//Ex_NVIC_Config专用定义

#define GPIO_A 0

#define GPIO_B 1

#define GPIO_C 2

#define GPIO_D 3

#define GPIO_E 4

#define GPIO_F 5

#define GPIO_G 6

#define FTIR   1  //下降沿触发

#define RTIR   2  //上升沿触发

 

BITx 范围为0~15,对应于IO口的位,对于外部中断线。

 

//外部中断配置函数

//只针对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;//得到中断寄存器组的编号  2/4=0

       EXTOFFSET=(BITx%4)*4;                  (2%4)*4 = 8

 

       RCC->APB2ENR|=0x01;//使能io复用时钟

 

       AFIO->EXTICR[EXTADDR]&=~(0x000F<

       AFIO->EXTICR[EXTADDR]|=GPIOx<

      

       //自动设置

       EXTI->IMR|=1<

       if(TRIM&0x01)

{

EXTI->FTSR|=1<

}

       if(TRIM&0x02)

{

EXTI->RTSR|=1<

}

}

 

EXTADDR=BITx/4;得到中断寄存器的编号0~4  BITx【0~15】

EXTOFFSET=(BITx%4)/4;得到中断寄存器的偏移量 0,4,8,12




『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
51单片机CO2检测显示程序解析