一、概述 1、中断简介 中断是指计算机运行过程中,出现某些意外情况需主机干预时,机器能自动停止正在运行的程序并转入处理新情况的程序,处理完毕后又返回原被暂停的程序继续运行。 中断的分类: (1)硬件中断 - 可屏蔽中断:硬件中断的一类,可通过在中断屏蔽寄存器中设定位掩码来关闭。
- 非可屏蔽中断:硬件中断的一类,无法通过在中断屏蔽寄存器中设定位掩码来关闭。典型例子是时钟中断(一个硬件时钟以恒定频率—如50Hz—发出的中断)。
- 处理器中断:一种特殊的硬件中断。由处理器发出,被其它处理器接收。仅见于多处理器系统,以便于处理器间通信或同步。
- 伪中断:一类不希望被产生的硬件中断。发生的原因有很多种,如中断线路上电气信号异常,或是中断请求设备本身有问题。
% p. ~8 V! y5 H! }% s
(2)软件中断: 是一条CPU指令,用以自陷一个中断。由于软中断指令通常运行一个切换CPU至内核态的子例程,它常被用作实现系统调用。 中断优先权: 在某一时刻有几个中断源同时发出中断请求时,处理器只响应其中优先权最高的中断源。当处理机正在运行某个中断服务程序期间出现另一个中断源的请求时,如果后者的优先权低于前者,处理机不予理睬,反之,处理机立即响应后者,进入所谓的“嵌套中断”。中断优先权的排序按其性质、重要性以及处理的方便性决定,由硬件的优先权仲裁逻辑或软件的顺序询问程序来实现。 中断过程: (1)中断源发出中断请求; (2)判断当前处理机是否允许中断和该中断源是否被屏蔽; (3)优先权排队; (4)处理机执行完当前指令或当前指令无法执行完,则立即停止当前程序保护断点地址和处理机当前状态,转入相应的中断服务程序。 (5)执行中断服务程序; (6)恢复被保护的状态,执行“中断返回”指令回到被中断的程序或转入其他程序。 2、外部中断/时间控制器(EXTI)外部中断 EXTI主要特性 (1)每个中断/事件线上都具有独立的触发和屏蔽。 (2)每个中断线都具有专用的状态位。 (3)支持多达23个软件事件/中断请求。 图3_0外部中断/事件控制器框图 外部中断/事件线映射: 多达140个的GPIO通过以下方式连接到16个外部中断/事件线: 图3_1外部中断/事件线映射图 另外七根EXTI线连接方式如下: - EXTI线16连接到PVD输出。
- EXTI线17连接到RTC闹钟事件。
- EXTI线18连接到USB OTG FS 唤醒事件。
- EXTI线19连接到以太网唤醒事件。
- EXTI线20连接到USB OTG HS (在FS中配置)唤醒事件。
- EXTI线21连接到RTC入侵和时间戳事件。
- EXTI线22连接到RTC唤醒事件。
3 f4 b$ H" C5 r- M( f' B
3、STM32中断优先级的判断* [0 o/ I- k* Q5 i4 T, X
STM32 目前支持的中断共为 84 个(16 个内核+68 个外部), 16 级可编程中断优先级的设置(仅使用中断优先级设置 8bit 中的高 4 位)和16个抢占优先级(因为抢占优先级最多可以有四位数)。 STM32(Cortex-M3)中有两个优先级的概念——抢占式优先级和响应优先级,有人把响应优先级称作'亚优先级'或'副优先级',每个中断源都需要被指定这两种优先级。 具有高抢占式优先级的中断可以在具有低抢占式优先级的中断处理过程中被响应,即中断嵌套,或者说高抢占式优先级的中断可以嵌套低抢占式优先级的中断。 当两个中断源的抢占式优先级相同时,这两个中断将没有嵌套关系,当一个中断到来后,如果正在处理另一个中断,这个后到来的中断就要等到前一个中断处理完之后才能被处理。如果这两个中断同时到达,则中断控制器根据他们的响应优先级高低来决定先处理哪一个;如果他们的抢占式优先级和响应优先级都相等,则根据他们在中断表中的排位顺序决定先处理哪一个。 优先级分组: 中断优先级分组域中,可以有8种分配方式,如下: 所有8位用于指定响应优先级。 最高1位用于指定抢占式优先级。 最低7位用于指定响应优先级。 最高2位用于指定抢占式优先级。 最低6位用于指定响应优先级。 最高3位用于指定抢占式优先级。 最低5位用于指定响应优先级。 最高4位用于指定抢占式优先级。 最低4位用于指定响应优先级。 最高5位用于指定抢占式优先级。 最低3位用于指定响应优先级。 最高6位用于指定抢占式优先级。 最低2位用于指定响应优先级。 最高7位用于指定抢占式优先级。 最低1位用于指定响应优先级。 二、硬件电路 图3_2引脚分布图
3 C4 O+ D2 S S( R' n( _# I N 图3_3电路原理图 在iCore3双核心开发板中,采用一个独立的按键与STM32F407的GPIO相连,另一端接地,且PH15外接一个1k电阻大小的上拉电阻。1 D% b! V$ R2 B) Q( l2 K2 u# S. ?
三、实验原理 按键的一端与SMT32的GPIO(PH15)相连,另一端接地,且PH15外接一个1K电流大小的上拉电阻。初始化时把PH15设置成输入模式。当按键弹起时候,PH15由于上拉电阻的作用呈高电平(3.3V);当按键按下时候,PH15直接被按键短接到GND,呈低电平。因此PH15的电平变化产生下降沿,从而进入中断函数,可得到按键状态。原理图如下: 图3_4实验原理图 四、源代码 1、主函数 - /*5 l( b% z2 R9 ?; b& @; E9 [
- * Name : main
) \7 x2 Q6 _2 w0 \4 w" A) ? - * Description : ---
+ Z" E! }# b, W: L - * Author : ysloveivy.
]: E' w6 R# Q+ C - *+ d1 X4 H7 Z8 _( {
- * History
1 q G3 g4 e; t- p" Z5 d: C l - * --------------------
: {8 R% ?% u) R& c0 S1 g - * Rev : 0.009 o8 S3 z' y$ x- ~7 t
- * Date : 11/21/2015
$ \3 {6 {7 H1 D! j% z& G: O - * 1 t# [1 {4 q0 ]" ^, a* Z( c% N
- * create.
+ V- M3 X; g$ f! T# R9 u) u - * --------------------- J$ T" D: Z% E) r5 p
- */2 e0 t$ E9 S3 A: J: h! o! }- ?+ y
- int main(void)5 J0 {6 T2 m8 l: i* v
- {
$ @& Q: O {# H; N( J0 l* _ - led.initialize();
; N+ k# U* m% s6 ?7 Y; Q - exti.initialize();* P- [) c5 ?) k5 m# y, Z/ }
- LED_RED_ON;
- e% a1 N. s- f+ l$ B - LED_GREEN_OFF;
! `5 {& y: }8 J - LED_BLUE_OFF;
9 [4 Z, Z, n& `. m
J; d; F. S( k- while(1);! d( Q4 v# ^4 C
- }
7 R/ O0 s, ~0 W+ b+ p
复制代码2、GPIO初始化 - /*
0 e6 l0 y& p. S - * Name : initialize
8 g9 l! ~) e3 b/ X - * Description : ---
: C& p- w) s* U$ `/ y6 U - * Author : ysloveivy.
. S( Z/ k! s6 m& w" o+ I5 S# d - *
/ U; E& H; T/ T3 X7 Q - * History) y! K4 D! R u9 R0 Y- y
- * -------------------
: u8 R N% r7 {9 v - * Rev : 0.00/ e% n, k* Y# G# y
- * Date : 11/21/2015
0 \( E$ p' h6 Q4 X - *
) C* u9 Q' c0 q; v2 h0 F - * create.8 C4 _3 }: I+ |4 f' W+ G+ ]
- * -------------------
0 v' z. F8 o7 s# a) H* D) [ - */# \9 E# q; m/ ]2 A
- static int initialize(void)
5 r% U/ g/ h- J* o# T2 _3 V - {0 ~: X" c# K' q0 p6 `9 N$ A+ h
- EXTI_InitTypeDef EXTI_InitStructure;
' h! s, ^6 T* {( b2 o1 F - GPIO_InitTypeDef GPIO_InitStructure;
/ W+ w4 C1 t1 L s: ?( ] - NVIC_InitTypeDef NVIC_InitStructure;( b, e1 z! O7 i1 }
) W) Z3 b3 S8 C: {: S! w& U# o( R- RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOH,ENABLE); //使能GPIOH时钟
; J0 }; h! m$ e1 p - RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE); //使能SYSCFG时钟% T* s3 e% } e4 s5 U
- # f" G8 C% V* o$ j- W" v1 c
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15;1 p7 x, e, a7 ~
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
, T- ^" t/ i7 C. j% L - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
8 d3 {0 a" [, P$ c - GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
+ l, ]8 _2 l+ O* m& z, |3 u - GPIO_Init(GPIOH, &GPIO_InitStructure);
: m0 k" D: K- p u. p" g1 Z - ; `' H# D1 j* C# A) a% ?
- SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOH, EXTI_PinSource15); //PH15与EXTI15连接0 r) A" T. T7 b' o" ^
- & O7 E* B W" G: C( d
- EXTI_InitStructure.EXTI_Line = EXTI_Line15; //设置连接中断线15
! x: _, E: k: s; R w- C - EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; //设置中断模式为中断
+ M) G" X+ W4 K# [5 ~: g& g7 s# c1 j; L - EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; //下降沿触发, [& z4 I9 S# q" O0 m! E
- EXTI_InitStructure.EXTI_LineCmd = ENABLE;. B5 r& `8 t1 f$ P3 S, T l' ~, u1 `
- EXTI_Init(&EXTI_InitStructure); @* {5 R/ D% `8 \0 I2 u8 v5 K
/ u9 N; q& B. \# q+ {3 D! H! C- //设置中断优先级分组
. c5 h4 d$ o; q9 v/ y% u6 g - NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn;' Q8 L( q& W% r' P
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x0F;: }/ s5 P3 n3 L) Y
- NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x0F;% t) t1 K) x1 r6 J8 f; c
- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
$ x! K& {( \6 \; z3 u
* W% u- G4 m1 z' t' j7 h( O, t- NVIC_Init(&NVIC_InitStructure);$ u0 Z3 _0 X4 a/ F3 t3 I
- 1 d$ t! u M k% ~+ A# [* J6 N, C
- return 0;8 Q: x! V' e4 s% ~
- }
" W' M/ J) h6 V5 k. Y; C+ x& {
1 U% X$ ?+ j: V. ~3 H- /*0 q' j2 p6 R' R% d3 R: _' S" a
- * Name : EXTI15_10_IRQHandler
6 [% s% j4 ^/ O/ g - * Description : --- D/ b" a3 r3 R* J
- * Author : ysloveivy.
1 I; n4 q- J5 ]& \- X - *; K+ {" w0 n: f1 b$ x. R, s# G# c% d
- * History
# z, I% u3 b- X* @. } G - * -------------------
/ Y3 k* a1 q% \, C - * Rev : 0.00" E& a, _9 r% `4 b6 k2 @) p! M% y( y
- * Date : 11/21/2015' c2 u' V M: @3 X4 n
- * + B8 t) C& T8 j$ {& Z
- * create.6 `9 q0 s7 G9 R- R* [+ t2 c
- * -------------------
; [' {* l* V$ L& V) g - */
' s& r8 ^3 C1 x7 Y; ], s8 w/ _ - void EXTI15_10_IRQHandler(void)
0 R: F( z5 @- Y. M3 _, Z8 a - {
- a3 c: \% e& u7 l: X8 B8 n - int i;
) u ^" P0 R4 m# [% [ - static int work_status = 0;* p9 z% o4 S0 a- P# U# x9 S, V
- if(EXTI_GetITStatus(EXTI_Line15) != RESET)( _: @" r' v1 J. y
- {, _" K" N( Y. Z7 R- w
- for(i = 0;i < 1000;i++);% |/ @/ H' o: [) [' K
- if(!KEY_INPUT){$ M9 {- {! M( i& t* `2 s
- work_status += 1;
! a G+ ]& R: A( i - if(work_status > 2)work_status = 0;8 w0 u( t& I, {/ y7 W
- }
3 T4 A0 n r8 H4 ` - switch(work_status){% u/ H# N! Z' u H5 ?* m$ C
- case 0:1 A$ |! x5 \0 k) G) ?- [
- LED_RED_ON;! g+ f) H+ C R: C- O
- LED_GREEN_OFF;
; b+ F) [5 E) g! u! V - LED_BLUE_OFF;
9 L* D5 O4 y, q; Q; q8 Y/ s! `3 a - break;
5 J1 [) D7 G5 O7 d) P9 R" _ - case 1:
2 C6 r8 }# D- N' O3 f8 x - LED_RED_OFF;
3 `9 j" j: k f - LED_GREEN_ON;# q' y2 ^+ c7 E2 b% Q2 x
- LED_BLUE_OFF;
1 ?% w: ^& |. |* l3 P# p( B - break;1 z# H' p% U5 ~6 W8 n2 d9 ] z
- case 2: O ^2 z* v' W0 ^
- LED_RED_OFF;! g. O. T4 j# v/ e: i6 G
- LED_GREEN_OFF;+ c& N. v) O7 [; P- A5 r
- LED_BLUE_ON;& x' A! Z# `. ]; O2 S3 z9 N0 Q+ }7 _
- break;: I$ [: d e" t8 O
- default:
; t4 B8 P+ P% j# {
! | k0 o; u" \% g- break;# S/ {, x" {2 g2 `" S `2 Y ^* _8 Q
- }
+ w8 P& L% k) a0 G3 w - EXTI_ClearITPendingBit(EXTI_Line15);% }" {" c9 R y& A! \
- }4 |/ M$ l2 Y# |0 `1 r4 h% \' W
- }
复制代码3、小知识: 设置中断和优先级主要用到以下两个结构体: 优先设置结构体: - typedef struct
/ P! h5 h3 M! N5 w/ R3 T - {1 s6 R+ r/ i t5 P
- uint32_t EXTI_Line; //设置连接中断线
V% t* }* x* \* V9 C - EXTIMode_TypeDef EXTI_Mode; //设置中断模式
+ {0 K- |& a' a& V - EXTITrigger_TypeDef EXTI_Trigger; //触发方式 ; C$ b+ e. G: L/ t
- FunctionalState EXTI_LineCmd; //使能与否
8 o7 Y1 o$ C2 Z4 k& v/ B# k
; q, U- r; s9 s8 V, {; X, p( G. w- }EXTI_InitTypeDef;
复制代码 优先级设置结构体: - typedef struct
7 \4 F4 \6 M; j* X/ B - {
# g' H" y0 M7 |6 F3 Z2 o* i - uint8_t NVIC_IRQChannel; //嵌套向量中断控制器通道
0 Y( C; m* `% D, q7 | - 2 T& r0 S6 @* j7 x
- uint8_t NVIC_IRQChannelPreemptionPriority; //抢占优先级" c( b/ j; i, i6 q) i. @8 i
$ D' ^& F$ ?, j- R! Q% I- uint8_t NVIC_IRQChannelSubPriority; //相应优先级0 R9 B8 b( J! v# o* c# ]2 r" m
9 b, H3 c) Z7 W- FunctionalState NVIC_IRQChannelCmd; //使能与否
* @1 Q" G' w4 N/ v - } NVIC_InitTypeDef;
复制代码 可以通过以上两个结构体来配置中断和优先级。 五、实验现象 按键每按下一次,三色LED灯变换(红色、绿色、蓝色轮流变换)一次。 六、代码包下载
) O" p$ v) ]( f# v
* r4 i C( L: _+ j' f% D4 M T6 z' I/ h3 x9 d0 e
! f% i7 O0 I* o% [% S% S: @
$ a6 g: e: e7 }8 ]9 D/ ~
0 C1 k9 }3 B9 x3 L* [0 B4 Z: ?/ t3 Y
|