|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
Questions:为实现任务的快速响应,应用通常会设计外设中断,在中断函数内响应事件标志对应的回调任务。但大多外设均具备多个可引起中断的事件标志,如何实现回调任务的精确响应将变得尤其重要,本文档旨在介绍一种保障回调任务可被精确响应的方法。
* k) X1 i1 f# Q2 w( \3 C% c. U: L
( Q8 R u) S( _- U; x. xAnswer:
: N/ ]8 n) i4 U6 l以下将以USART2为例进行阐述。
9 i9 u4 w5 `# S/ d5 y9 o5 R
' C, ~& I+ }0 _% E. K. `4 u
. X/ x: \$ H# h# f1 W中断响应过程及注意事项
, M* d+ G. C: q5 W2 u1) 事件标志置位 6 t" V- N' V; L7 J
当事件标志产生条件成立后,硬件会置位对应的事件标志。8 s0 V' ^- G. d
示例:当USART2接收数据缓冲器满时,会立即置位对应的RDBF标志。
' d$ }3 s5 M, Q* b" u* e$ A注意:事件标志的置位发生在其对应的事件产生条件成立时,不受对应的中断使能状态影响。
; m2 s' w: G9 B* j: Z9 X1 S2) 中断服务响应- c. H+ W8 B/ j% J1 G; h* \ T7 `5 o
当事件标志,且对应的外设中断处于使能状态时,硬件会通过外设中断通道向内核申请中断服务。; j* Q3 \3 F( Y
示例:当USART2的RDBF标志置位,且RDBFIEN处于开启状态时,硬件会自动通过USART2中断通道向内核申请中断服务,同步置位USART2的NVIC pending位来指示有中断申请出现,以指示代码需要跳转到中断服务函数执行。
2 Q( Q! X: C: V% i* I. n2 F注意:外设中断处于失能状态时,对应的事件标志置位并不会申请中断服务。# z7 k& c- l) U4 R& |6 b x# F8 s) u/ t
3) 中断函数执行: P9 ~1 I1 b1 z4 u
在符合中断响应优先级规则条件时,代码就会自动跳转执行中断函数内的回调任务。
5 ?# c2 C3 d9 g由于同一个中断通道具备多个引起中断的事件标志,对应共用同一个NVIC pending位,且该pending位在代码跳转到中断函数后会被硬件自动清零。. Q9 P" f( e- ~+ {' r5 H
注意:该NVIC pending位会跟随该中断通道内的任意被使能中断的事件标志置位而置位,其只记录有无,不会累加。并在响应中断函数时被硬件自动清除。
- _1 H% t' T$ `: A- ?: {为避免事件标志的回调任务被漏执行或误执行,软件必须要在中断函数内做好事件标志的区分处理。如下建议方法:5 F3 q! c0 G# [ Y; X1 ]9 z
回调任务漏执行的避免方法
! ]5 x+ A4 a2 h& p* }当同时使用同一外设的多个事件中断时,中断到底是由什么事件标志产生的须由软件按照如下区分:4 Q* ?. I$ Z9 l$ n- D
在中断函数内,查询每一个事件标志的状态来决定是否响应对应的回调任务。
# q& R0 A6 h9 c, g$ Z3 N: P6 i% a示例1:当同时使用USART2的RDBF中断和TDBE中断时,中断函数需如下设计* R# m2 |/ g% Z- R
void USART2_IRQHandler(void)
; K0 ^$ f8 a/ M+ K/ q/ \{
m+ y9 J) H2 D if(usart_flag_get(USART2, USART_RDBF_FLAG) != RESET)$ I- G8 x/ `& l* v. d
{
6 F. r4 G5 ^; R7 M2 }7 U /* user code */+ { L( H. x- {, b. h. |9 Q& h2 K
}: z; H3 v: e f6 [, x" t( N2 H
- T8 X8 S" c) q$ x' }) r0 Z
if(usart_flag_get(USART2, USART_TDBE_FLAG) != RESET)( V. k; S9 }0 J+ O( n# _' W: F- q
# y, |7 B5 q* z {
0 A# L" }1 j0 R6 l /* user code */: I2 _. N. w/ d- ]5 u
}
6 x1 Z o+ n4 h, _}
8 ?5 o1 t( I# _ u4 e2 j# V# `4 Y1 A& }
可同步参考如下路径demo示例用法AT32Fxxx_Firmware_Library_v2.x.x\project\at_start_fxxx\examples\spi\halfduplex_interrupt3 k5 v' S2 H. N; F) }! ~
回调任务误执行的避免方法& B) S" S% v& W
当分时使用同一外设的多个事件中断时,中断到底是由什么事件标志产生的须由软件按照如下区分:
% {. g2 P P3 L- ^* V! b* d在中断函数内,查询每事件的中断状态及标志状态来决定是否响应对应的回调任务。' Z5 T2 `! L, `# ?
示例1:当使用USART2的RDBF中断、并分时的使用TDBE中断时,中断函数需如下设计
& J& Z3 o0 C/ r3 u void USART2_IRQHandler(void)0 P' F5 Q! Q/ {: V" [- z2 U
{
: i8 e+ }$ v- r2 X- w7 B if(usart_flag_get(USART2, USART_RDBF_FLAG) != RESET)
3 `) S6 F( F. P0 b8 s4 [& Y {/ }. \4 V6 R* U% K3 @$ L' c/ K
/* user code */
8 {' b" ~: c' W! [: T, J& d3 t+ u }$ T) `* J/ Y9 r: ^
if(USART2->ctrl1_bit.tdbeien != RESET)
8 n, A% K) M4 D' i; Q3 d {
' J/ W1 q* J$ y- [$ e+ h& a9 Q if(usart_flag_get(USART2, USART_TDBE_FLAG) != RESET)0 s8 Y9 {! f8 ? O
{
/ M+ S& I' k4 V( V7 Y: i: r /* user code */
, f9 g- x G9 x: B% y }- B7 D7 m- \$ ?2 n" m7 D+ e
}5 x$ l M+ h6 y9 f" {
}
' H- v+ g0 y9 H1 A8 s( e; w9 M# O" |' V4 g7 X% d$ V6 X9 n* V
可同步参考如下路径demo示例用法AT32Fxxx_Firmware_Library_V2.x.x\project\at_start_fxxx\examples\spi\halfduplex_transceiver_switch
2 ?! a1 E3 g _& \( y4) 中断结束返回8 B8 Q* u" W4 V1 e3 P2 C8 @+ Q& u; c8 H
当中断回调任务执行完毕时,软件应该及时清除事件状态标志,随后代码会自动跳转回主函数。
1 z4 p& A' n. @" g! m |
|