前段时间贴主看了Cortex-M3的NVIC,对其中断嵌套甚是着迷,于是瞎搞了几下下……瞎搞就瞎搞嘛,但却搞出了问题……
+ P$ ~% Y: v. t7 Z5 n
4 G9 F: m, D" f+ L2 B8 b: `* P废话不多说,直奔主题!
/ ?; b6 W3 L/ x: }! G
! E/ h4 t- d$ ?, {8 D; [通过查看Cortex-M3有关异常和NVIC章节的资料,贴主本来是想实现这么几个工程目标:
4 W- @4 u- j4 N& y% P6 r(贴主板子上的芯片型号是STM32F103C8T6,PA.8接的一个LED的阴极;MDK版本5.17&5.23)
( r7 `$ l+ `/ J5 q0 n4 u================================================================/ Q& s# F. }# e, s4 ?; I
【1】不操作优先级寄存器,软件触发EXTI2中断进入其ISR里,再软件触发EXTI1。判断是否会发生中断嵌套?
! u% r& o4 e/ }1 b& v% G 工程预估:不会。" v% E9 S! h+ @1 j) S
why:①当不操作优先级寄存器时,Cortex-M3内核默认从比特0分组(因为SCB_AIRCR寄存器的优先级分组三位复位值为0),即优先级寄存器高四位均表示抢占优先级;" I- _- l$ o. k0 _9 { I
②优先级寄存器NVIC_IPRx高四位复位值为0,由于没重新赋值,所以抢占优先级均为0;【也就类似于除能了CM3的中断嵌套机制。】7 Z& J' Q. t/ l0 Q" \/ |
③优先级寄存器高四位均表示抢占优先级且为0,亚优先级均为0。所以优先级取默认的硬件异常号,虽然EXTI1的默认异常号高于EXTI2,但不会发生中断嵌套。9 s g, M( S5 x6 x
-------------------------------------------------------------------------------------------------------------------------------0 ?8 N4 X! t Z1 N
【2】优先级寄存器的高三位表示抢占优先级,且EXTI1和EXTI2抢占优先级相同,但EXTI2的亚优先级高于EXTI1。软件触发EXTI1中断进入其ISR里,再软件触发EXTI2。判断是否会发生中断嵌套?" j1 O: K+ C0 @6 j8 ~2 |" r
工程预估:不会。
; e u# `3 o4 E6 H' u ^" N, G* u why:二者抢占优先级相同,亚优先级的高低不导致中断嵌套。只是当抢占优先级相同的异常有不止一个同时悬起时,就优先响应亚优先级最高的异常。
/ a7 `+ w& |' b; ^( P-------------------------------------------------------------------------------------------------------------------------------) b. N" L V. M, E8 t* U) d* M0 O+ Z
【3】优先级寄存器的高二位表示抢占优先级,且EXTI2抢占优先级高于EXTI1,但EXTI2的亚优先级低于EXTI1,在软件触发EXTI1中断进入其ISR里,再软件触发EXTI2。判断是否会发生中断嵌套?
1 j, L: B, k) D# w# M% }- m2 L 工程预估:会。
& q, c0 G, P) s. v5 A; T why:EXTI2抢占优先级高于EXTI1,亚优先级的高低不导致中断嵌套。
7 c: V$ \+ |9 \+ Z-------------------------------------------------------------------------------------------------------------------------------
/ M" ^; ?3 m+ D/ w【4】无抢占优先级,优先级寄存器的高四位均表示亚优先级,但EXTI2的亚优先级高于EXTI1,在软件触发EXTI1中断进入其ISR里,再软件触发EXTI2。判断是否会发生中断嵌套?
( z: e* e, u. C) j1 Z 工程预估:不会。) h: p) _# K2 ]) _
why:无抢占优先级【相当于除能了CM3中断嵌套机制】,亚优先级的高低不导致中断嵌套。
; V) Y7 U# v2 `================================================================- G/ D3 T9 w$ t) u- I
很明显,每一个程序均非常简单。但将程序下载到硬件上跑的效果会不会如预估一样呢?0 ]0 W+ T1 f& x' K( v7 K9 |
2 w7 E+ c1 d# U& a, Z
第一个工程的代码如下:3 O- S, H# h7 f2 o8 ]
“main.c”源文件里
9 b$ q% q; S6 X4 b% b! J- #include "stm32f10x.h"+ o h6 l1 J4 r, m5 p- [9 n
/ L: o, \/ e9 ?$ ^4 W* V- #define GPIOA_ODR_Addr (GPIOA_BASE+0x0C) //GPIOA端口寄存器ODR的地址5 G3 C0 {+ D# x: o$ j5 }4 Y) Q
T0 _9 |9 q8 r, J' G* t. `4 A1 C( e- #define BitBand(Addr, BitNum) *(__IO uint32_t *)((Addr&0xF0000000)+0x02000000+ \
! ` ~8 n# w" W) Z( L - ((Addr&0x000FFFFF)<<5)+(BitNum<<2))
& m/ |6 f: b W8 W - #define PAout(n) BitBand(GPIOA_ODR_Addr, n) //偏移地址取的是32位寄存器的第一字节的,所以n的取值为0~318 r1 F+ e$ c: _1 e8 _
- 9 ^+ x( w0 \4 p
- FlagStatus led = SET; //外部调用的全局变量(声明在stm32f10x_it.h头文件)
! n( u" w7 {3 a+ }3 P; @0 b
( y. C# a- p$ }: n4 A- static void RCC_Configuration(void); //函数原型声明. k" m3 ?* q7 a$ P1 C$ ?1 y
- static void GPIO_Configuration(void);2 {/ t2 I1 g% `
* v% K2 P& w4 q- J- /**********************************************************************
8 }" K7 Y& ^; z u7 n - * Function Name : MAIN
+ O8 Q) o& s1 r) P1 M; s - * Description : main program) U, w" P& z; [8 d
- * Input : None
6 L8 n) n- ~5 T" X: ^ h5 G/ k - * Output : None
: E$ w) e8 E1 L! O$ S - * Return : None
; s3 y1 T: L$ ~. [$ u1 X - **********************************************************************/+ [+ y" k6 R& X1 i% l
- int main(void)' u7 a- S1 P7 K/ h# m; P
- {4 \6 M: n& V; b I6 J! T( w
- RCC_Configuration();- `$ Q/ v! y* @% D: Y& T0 F0 @ O! X
- GPIO_Configuration();
; ?. J ?2 Z4 N" e' m - PAout(11) = led; //上电关闭LED
0 |; f l$ C% i. T; K2 t2 p -
8 ]; K& Y1 p& q( P - NVIC->ISER[0] = NVIC_ISER_SETENA_7 | NVIC_ISER_SETENA_8;
" P- U6 h4 z9 l - EXTI->IMR |= EXTI_Line1 | EXTI_Line2;2 D. X1 u' S( H( [7 U3 V) s( o
- 1 Z- u2 W9 | R1 w
- EXTI->SWIER = EXTI_Line2;
+ M9 Z8 R( W5 G) W -
3 @6 G# i2 M& Q$ J' c- b0 e0 J - while(1)
) `) j1 `$ }! K$ c4 j: b - {
. `' H9 j3 R! k- a- C2 L8 j; c4 N - PAout(11) = led;, Q0 S2 y+ a6 o, H! P
- }2 v! P' A. C1 m6 ?6 Z
-
- T5 f$ R N4 i/ ] - // return (0);8 f# |4 b& z! p3 Q0 F* Y
- }. K/ p( n+ N6 T1 e& l, f
, x$ |# P1 y1 n5 k$ W7 P+ Z- /**********************************************************************5 S: |# z# r; c! W5 n, l8 D1 t
- * Function Name : RCC_Configuration
& W( `6 J8 f; M6 z5 o0 a. J - * Description : 配置时钟参数,使能外设时钟5 T: v- F& N9 @8 s
- * Input : None1 @0 Y6 k q: `/ @4 s ~; S4 F
- * Output : None* g$ h( {2 u4 ]& h7 r! {
- * Return : None
$ B4 b$ i' P5 ~. u5 ^ - **********************************************************************/$ U( U+ R% @4 ^( K1 t- n; G
- static void RCC_Configuration(void)
1 r4 n) _/ k4 G& C& L' d' ?2 u - { * z8 d% F7 Q' W" q% [
- RCC_DeInit(); //将外设RCC寄存器重设为缺省值(选择HSI作为系统时钟,其它保持复位值)' N% G" N. l( b8 S. X% Q* A
- RCC_HSEConfig(RCC_HSE_ON); //HSE晶振ON" q/ ~7 p8 } o5 X/ y4 Z# Y
- if(RCC_WaitForHSEStartUp() == SUCCESS) //等待HSE晶振稳定, u7 k5 n' w' _+ K$ {" n0 x7 N1 m
- {. F* x1 {: _1 W+ b9 f( k
- RCC_HCLKConfig(RCC_SYSCLK_Div1); //设置AHB时钟(HCLK)—— HCLK = SYSCLK/1
) ~6 y' h' p$ G$ y' P. n1 E - RCC_PCLK2Config(RCC_HCLK_Div1); //设置高速AHB时钟(PCLK2)—— PCLK2 = HCLK/1
0 |+ K# ?; z1 g" w6 E2 I - RCC_PCLK1Config(RCC_HCLK_Div2); //设置低速AHB时钟(PCLK1)—— PCLK1 = HCLK/2. M x4 Z' i0 M" k" k4 p% f
- FLASH_SetLatency(FLASH_Latency_2); //在SYSCLK周期与闪存访问时间插入2个等待周期
0 Y, j2 `3 Y& v% S2 L$ `4 F7 Z: h- k - FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable); //启用闪存预取缓冲区# T% o8 L- @7 a! t- A
- RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9); //设置PLL时钟源及倍频系数 —— PLLCLK = (HSECLK/1) * 9 = 72MHz
3 A+ \ n. N$ k! C6 d8 e+ u/ S - RCC_PLLCmd(ENABLE); //使能PLL9 ^3 M. J5 P( ^4 |( Q) x
- while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET); //等待PLL就绪
4 l" j1 I3 Z- n - RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK); //设置系统时钟(SYSCLK)—— 选择PLL作为系统时钟; n; [/ U* z" T# s- i
- while(RCC_GetSYSCLKSource() != 0x08); //返回用作系统时钟的时钟源 —— 0x08:PLL作为系统时钟: w5 {/ S" l4 Y1 s- @9 h _
- }# y' B/ r4 N. F- R' y6 h: i
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);! E$ y$ o, \+ V0 V* D
- }
# H0 p8 ?2 P) @" ?7 s
0 W T; ?' {$ M/ y9 r$ O- /**********************************************************************" {4 ~7 b: s& x. a5 \3 v; c
- * Function Name : GPIO_Configuration
. h! V/ y) S5 p' H - * Description : 配置GPIO参数
6 \- e5 }; F2 p; {0 N5 x6 } - * Input : None7 X) y$ c/ a5 B) l. @
- * Output : None
4 o( P3 `" x3 A4 R# c0 A- t' n( W9 F - * Return : None$ z7 E' K9 @, w! E( c& M
- **********************************************************************/
) m% [% ? c w! d3 }; M - static void GPIO_Configuration(void)$ r$ a% P, C& h1 e- f
- {/ R6 U8 A9 X/ g1 Q
- GPIO_InitTypeDef GPIO_InitStructure;' t# E3 }' E' a# b2 S! K- }/ S
- 6 r$ X9 |& b) p$ ]
- /* 将GPIOA.11引脚设置为通用推挽输出模式,最大速度50MHz */8 ?1 G2 Q/ p. g& ]0 G- V: P/ ]4 k5 v
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11; U6 P6 r! A, j* w. w5 Q; |9 A
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //GPIOA.9已配置) V D: t3 c6 W8 c
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;+ @6 O9 _! }! N- w9 H4 o( s4 {3 e
- GPIO_Init(GPIOA, &GPIO_InitStructure);
' i0 g( D7 f4 t" V8 z, q" o -
4 F( e& h# z& ~! |; H6 p - /* 将GPIOA.1和GPIOA.2引脚设置为浮空输入模式 */* |8 e6 Z: M. B2 p
- // GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2;: p3 ] O! l _1 J
- // GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
2 h6 Y y; g5 ` m" S - // GPIO_Init(GPIOA, &GPIO_InitStructure);
4 x2 v0 W! X4 M7 `) Z. ? -
( ~; B8 P$ r: S$ a: v h7 L - GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource1);) [* \4 \0 @: _) v
- GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource2);
( A, P% f" m6 K7 H - }
复制代码 “stm32f10x_it.c”源文件里:: a, @& q: S# m" c/ _
- /**7 u/ ^) @6 P) g" P
- * @brief This function handles External lines 1 interrupt request.
8 S; e/ v6 ~: _( n+ c - * @param None& {! }9 q! D( w7 E' l6 d% A7 y
- * @retval None
; N5 B$ p) p" k - */) c, D; w& J) S6 R0 H& }% ?1 k
- void EXTI1_IRQHandler(void)
% n; ?( H1 w# a- [& Y+ X3 C - {
2 U) X+ P% i$ d' V- ]1 s/ Y4 D$ T - EXTI->PR = EXTI_Line1;
3 l* q9 W2 y3 h - led = RESET;: g! C! i. h7 Z# {7 {1 y
- }
! Y! d5 P4 ^. E( l8 L$ U - 4 r8 k, Y2 }7 n
- /**. E/ b* F2 A; O
- * @brief This function handles External lines 2 interrupt request.2 S9 m+ Q, x; H! \3 A8 ` x' Z2 Y4 x x* ?
- * @param None* {4 ~0 i1 y8 v# J3 H8 ~3 ^0 d
- * @retval None% `) J' B8 C0 R
- */3 C. C5 j$ ]: N# {+ c- @6 v$ p' c
- void EXTI2_IRQHandler(void)
/ }: ~# K1 i" Y - {# _+ ?- ?/ v4 c; k1 ^& V0 Y2 u
- EXTI->PR = EXTI_Line2; //同时清除了EXTI_SWIER寄存器对应位
! D9 c8 {, N3 g0 V - EXTI->SWIER = EXTI_Line1; //EXTI1触发请求7 Y) }0 u( ?. \- F. B0 R8 f
-
( s2 k! l' r0 H7 L - EXTI->PR = EXTI_Line1; //清除触发请求 {, ]- Q3 u7 ?
- NVIC->ICPR[0] = NVIC_ICPR_CLRPEND_7;//清除中断悬起标志【正常情况下,该寄存器对应的中断悬起标志在进入ISR时会自动清除】7 m& T1 T8 B. [1 i
- }
复制代码 “stm32f10x_it.h”源文件里:' }$ h% O) n; C& k- e8 V
- /****** 用户自定义 ******/. K6 ~, a: X0 R/ h( z
- extern FlagStatus led; //声明一个外部调用的全局变量(控制LED亮灭的变量)
复制代码 显然代码很简单,软件仿真时各寄存器也是按照程序的意思显示各项数据指标。但是………………很残酷………………实际与理论发生了偏差 —— 将程序烧进硬件跑,LED亮了(即PA.8被置低了。但初始化时PA.8已被置高,而且EXTI1的ISR里才有将PA.8置低的指令!)。不应该是这样啊:虽然EXTI1的优先级高于EXTI2,但二者的抢占优先级相同,因此并不会发生中断嵌套,而且在EXTI2的ISR里已将EXTI1的触发请求标志和中断悬起标志均清除了。原因何在?
7 S: _/ \7 Q5 P
+ [$ _; ?% _7 E# P) N贴主找啊找,调啊调………………好吧,既然软件仿真解决不了,咋就来瞎搞硬件仿真。# I/ U& b, v1 l" V! J
5 z s2 t1 ^6 f; C6 h! L8 u+ K
连接好JLink与板子后,在MDK里点击单步调试“Step one line(F11)”,执行触发EXTI2中断的指令“EXTI->SWIER = EXTI_Line2;”后却不进入EXTI2的ISR,而且无论点击多少次单步调试,程序一直停在while里………………问题真是接踵而至啊………………# E' \' Q8 d w+ D* j: u; ~9 i0 r
6 d- |' ~( h6 V4 \) U v. ]' B初入ARM,练习背黑锅。! b0 E5 j/ ?$ u" v2 z8 Z
. {1 m( r! t7 Y+ m, T这时贴主想起了前不久的一次调试经历:单步不行,就全速(贴主本坛第一帖),于是点击全速运行“Start code execution(F5)”试了下。哈哈,LED亮了!当然,之前的问题并没有得到解决,但是后来的在线调试问题却有了头绪 —— 通过在ISR里设置断点,只要对应的中断被触发且被使能,点击全速运行就可以进入ISR。有了这样一个认知后,贴主又开始瞎搞起来了:软件触发EXTI2后,是何时进入其ISR的?2 t* x2 ~% x) P6 ]
: i. e- Y) j3 }$ A3 h" K+ b为此,贴主就在主函数添加了三条将变量flag的值赋给其本身的赋值语句:
8 k4 g& g, ?" X2 _& }7 I8 v9 |- int main(void)
! j2 w# U' ?: g - {2 a: Z6 ^0 Z+ u! t/ D/ P* v2 O
- RCC_Configuration();
0 i5 b# M$ u+ c- G) I9 E8 P - GPIO_Configuration();' r. m/ T5 R% E' ^$ k
- PAout(11) = led; //上电关闭LED% y ~& j4 X8 W+ v
-
) U7 f- K- W8 u - NVIC->ISER[0] = NVIC_ISER_SETENA_7 | NVIC_ISER_SETENA_8;6 D! A2 A( j- s6 B, d
- EXTI->IMR |= EXTI_Line1 | EXTI_Line2;! ?) \- k: ]3 f% p, s: ~3 `. ~
-
. r) O. Y& [$ O - EXTI->SWIER = EXTI_Line2;: i9 T9 P, I' \7 R: G2 O
- ; z1 x% n8 x6 f. Z. L5 z
- flag = flag;: C7 W9 X7 A* {+ ?/ }9 a
- flag = flag;
& \' i9 @$ ]! y _ - flag = flag;
; s8 ~2 y% s( D- z `3 Y) r -
- e5 O6 k- M3 j3 G7 j - while(1)
( B9 I4 a8 c# G4 ~8 Y6 Q2 B - {" L u- ~# O2 r/ K2 M2 }- v8 ~
- PAout(11) = led;) p$ h) K1 b3 V1 w \: y
- }
& |. l, m) U/ B( e+ W -
: m4 e \* ~) s U* j8 W0 S! \ - // return (0);
: W4 H b7 Y1 J6 g$ m; g' x - }
复制代码 在线调试时在该三条语句均设置了断点,第一次全速运停在了第一条赋值语句处,再次全速运行时,程序进入到了EXTI2的ISR。如此说明软件触发一个中断,处理器并不会立即响应,这期间存在一个响应时间。学过8051单片机的童鞋应该知道,8051单片机的中断有一个响应过程:采样→查询→处理(各占1个机器周期)。Cortex-M3内核同样也存在,它将“中断延迟”定义为:从检测到某中断请求,到执行了其服务例程的第一条指令时,已经流逝了的时间。在CM3中,若存储器系统够快,且总线系统允许入栈与取指同时进行,同时该中断可以立即响应,则中断延迟是雷打不动的12周期(满足硬实时所要求的确定性)。在与时间赛跑的这12个周期里,处理器内部一直开足马力,进行了入栈、取向量、更新寄存器以及服务例程取指的一系列操作。但若存储器太慢以至于引入等待周期,或者还有其它因素,则会引入额外的延时。( l: b: X/ t: O$ U8 E
3 R2 q% o* a7 N. m$ I+ U
本帖谈论到这,再来谈在线调试为何进不去ISR,以及最开始的工程为何实现不了预期的目标,原因已很明了。, w2 b1 _0 L: F) V- u/ l2 v
5 _3 q/ w7 R0 g& h1 s* D) G在线调试为何进不去ISR:中断延迟的存在,以及中断响应机制。: |! b3 @! ?6 r8 D S0 P
0 F- v4 ^4 S* l
对于最开始的工程为何实现不了预期的目标:1 Q- S" x" k y( x8 S0 g1 R
在EXTI2的ISR里,软件是这样设置的:% k% c2 s7 [7 v3 h' S- X
- /**
: @. Q8 O. P% ]& P$ c* P - * @brief This function handles External lines 2 interrupt request.6 a) ~8 ? u/ t0 _" Q7 O
- * @param None2 K7 [/ c( _2 Y# D
- * @retval None
' B: [2 g3 k2 y5 }, S8 M1 ` - */( B: I8 \* y3 y0 C
- void EXTI2_IRQHandler(void)1 W5 H) ~$ m/ ]% W2 g1 n
- {
# O* Q9 k" D; Z. A7 \ - EXTI->PR = EXTI_Line2; //同时清除了EXTI_SWIER寄存器对应位2 M+ I) ]. k$ C( x/ \# A
- EXTI->SWIER = EXTI_Line1; //EXTI1触发请求: E) i* a( P% D
- - q( K2 z( Y5 P5 i0 N$ I9 m i% R
- EXTI->PR = EXTI_Line1; //清除触发请求( G3 l! m: F- t9 u. m! W
- NVIC->ICPR[0] = NVIC_ICPR_CLRPEND_7;//清除中断悬起标志【正常情况下,该寄存器对应的中断悬起标志在进入ISR时会自动清除】% H& r! i+ z$ ?7 b
- }
复制代码 也就是语句“EXTI->SWIER = EXTI_Line1;”触发EXTI1的中断请求,紧跟着就有清除EXTI1触发中断请求的指令“EXTI->PR = EXTI_Line1;”,显然由于CM3中断响应机制的约束,后面清除EXTI1触发中断请求的指令“EXTI->PR = EXTI_Line1;”实际无效。比如贴主在EXTI2的ISR里的第一条语句和最后一条语句各设置了一个断点,点击全速运行到最后一条指令,实际并没有清除EXTI_PR寄存器中EXTI1的挂起位(但若是在EXTI2的ISR里点击单步调试,就会清除该位,后面全速运行也不会进入EXTI1的ISR。原因前面已说明)。如下图所示:
`- O$ M [4 Z' w; W4 a% B
å¾1
! u6 G! S2 ]4 e. v9 R W1 b3 z5 B$ Q在EXTI1的ISR里的第一条语句也设置一个断点,然后继续全速运行,程序果真进入到了EXTI1的ISR,而且是在执行完EXTI2的ISR后再进入的。如下图所示:/ V1 l2 E y- t3 t0 Q% l. r2 \
å¾2
0 W: `& ~0 ?5 r: r- r+ ?这里说明了两个问题:$ o6 }9 R0 t. }/ w; c
一是前面所探讨的关于CM3中断响应机制;
/ l+ L E, o+ g1 N, X 二是只要没有清除EXTI_PR寄存器中EXTI1的挂起位,即使有清除EXTI_ICPRx寄存器中断悬起标志的指令,该中断悬起标志仍还是会悬起(前提:不是该ISR对应的中断的中断悬起标志。若是该ISR对应的中断的中断悬起标志,在跳出ISR的同时该悬起标志再次被置位。
8 t4 W6 r1 `+ n/ Q 比如:在本例的EXTI2的ISR中,由于指令“EXTI->PR = EXTI_Line1;”实际无效,所以它下一条清除EXTI1中断悬起标志的语句即使执行了,其对应的中断悬起标志仍是置位状态;而若将EXTI1的ISR里的“EXTI->PR = EXTI_Line1;”注释掉再全速运行,程序会一直停在EXTI1的ISR里。所以有时需要注意二者清除的顺序!)。关于第二点,参考手册里没有指明,但各童鞋需注意!' `) P+ _+ B$ i' U, l( y1 L
1 y; T2 e3 C* A+ X' x; c3 u# N
3 ~- z( g1 b( B6 N2 |经过以上分析,本帖最开始建立的工程的bug已经很明显:在EXTI2的ISR里的“EXTI->SWIER = EXTI_Line1;”语句后同样增加一条给变量flag赋值的语句:$ _/ n. `6 D6 k, u* {
- /**% W" V6 ]# E2 @3 ?& s/ i0 \
- * @brief This function handles External lines 2 interrupt request.
4 n- I! d* i' f' h - * @param None
' u0 P; Z: A$ W) M4 U - * @retval None
1 l9 _, \" F& S' X B: | - */" {/ ]8 N4 D! s- C" k
- void EXTI2_IRQHandler(void)
( u( _2 ?0 ]3 K' y8 u! K$ c" m - {
4 x* D% L5 E, i$ x) x v; ^! | - EXTI->PR = EXTI_Line2; //同时清除了EXTI_SWIER寄存器对应位! o* j7 c( D9 Z' J# q6 {' V! \/ w
- EXTI->SWIER = EXTI_Line1;
7 _8 x( D6 Q5 J. F* s$ w0 z+ G - flag = flag; /****** !!!此句必须有!!!否则程序运行有问题 ******/ P: O! t5 O' |+ x+ S
- /*** 以下是判断EXTI1是否已经发生中断嵌套(两条清除语句缺一不可) ***/
+ }+ p8 L# m/ j2 d8 X; w4 t - EXTI->PR = EXTI_Line1; //清除触发请求【必须先清除触发请求,然后再清除中断悬起标志 —— 软件仿真无区别,但硬件必须如此】/ U& C9 X* W c
- NVIC->ICPR[0] = NVIC_ICPR_CLRPEND_7;//清除中断悬起标志【正常情况下,该寄存器对应的中断悬起标志在进入ISR时会自动清除】& _9 p9 U" X9 E; y
- }
复制代码 0 `8 J8 [0 O' D6 p( G q" l8 {7 f
- G6 L1 a! e, F/ _7 P2 [6 W' H/ U9 |' C
总结下来,其实就是基本知识没掌握,所以每天都是在瞎搞又瞎搞………………
/ E+ s! K F( Z2 T
& t- h* V% {. x9 y
/ P- g0 z) m) s: I+ E: \
Cortex-M3ä¸æèµæ.rar
(5.19 MB, 下载次数: 24)
|
也就是第1脚必须与板子的VCC相连,至于第2脚呢?
经过帖主测试发现:JLink仿真器端口的第2脚连接的是仿真器内AMS1117稳压芯片的输出脚(或许有些JLink没有集成3.3V稳压输出),所以是可以给目标板子提供电源的。若板子没有独立供电,那么必须将JLink仿真器端口的第2脚与目标板的VCC相连。& w" o- |. I/ E h3 _" x
注意:无论目标板是否独立供电,如若不连接JLink仿真器端口的第1脚与目标板的VCC,下载程序时会依次弹出内容为“No Cortex-M Device found in JTAG chain. Please check the JTAG cable and the connected devices.”和“Error: Flash Download failed - Target DLL has been cancelled”的窗口提示! 前一个翻译出来也就是提示连接有问题。( {/ t7 g& c( r$ Q1 w/ a5 o" e8 c
(回复不能从本地上传图片,没图片显示形象,各位大虾将就下
回复时选择“高级模式”就可以添加图片了。
也可以使用ST-LINK/V2-1调试器。
哈哈,多谢大神提示,看到喃。(今后可以愉快的斗图了
目前身边只有JLink仿真器,其它仿真器今后应该用得到。; S! p( D/ A( D0 n+ f
1 o, z* C3 M+ W
借此将图片上传:
一般用FC头2*10P线连接,不会出现这种情况(前提是目标板本身已将对应的JLink输入引脚的第1脚连到VCC上。比如帖主的板子就是的,下图),容易出现这种情况是在用杜邦线去连接,又是1用JLink仿真器给目标板供电,就很容易少连这一根线。
--------------------------------------------------------------8 P9 @) }5 |6 u% e; x" M/ W" i
感谢@zero99 的支持。
--------------------------------------------------------------