你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【经验分享】STM32开发项目:如何配置GPIO的外部中断

[复制链接]
STMCU小助手 发布时间:2022-4-15 10:00
如何配置GPIO的外部中断
# D1 `4 o" r( [; ?1 h以STM32F103为例,记录配置GPIO外部中断的一般方法与流程。4 ^2 y8 W' n3 R$ j3 t& H

2 r, Y: Y/ M# ?# l. f9 g( S配置RCC时钟
5 r' K8 U, R7 [" X2 J7 i- YRCC时钟配置是STM32MCU顺利运行的必备步骤,笔者使用的参考代码如下:- E3 s% J! G' i, x/ ]$ D: y

7 y3 ^# Y1 C7 R( Z
  1. void RCC_Config()
    , M1 E% z' q$ N4 y
  2. {
    % I- W+ n, }. n/ J' n
  3.         RCC_DeInit();- G. a1 V) C' v3 ~- E
  4.         //使能HSE,并等待 HSE 稳定
    + P- o9 p9 `  k0 a% |
  5.         RCC_HSEConfig(RCC_HSE_ON);! W: ~5 m% L; ?, C
  6.         ErrorStatus HSEStartUpStatus;1 D3 `5 T' X8 k; J( M* `/ l
  7.         HSEStartUpStatus = RCC_WaitForHSEStartUp();
    , [; j! U. q! ^
  8.         //HSE启动成功* r$ _/ B/ Y4 z- S  H" T
  9.         if (HSEStartUpStatus == SUCCESS)" K, Z  \* g: ?9 _0 g
  10.         {
    9 P. Z% G( V% @7 B. ?/ ~
  11.                 //使能FLASH预存取缓冲区# Z# B7 u# Q# A+ d1 Y9 L* I. `
  12.                 FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);
    ; g" |" V( f3 b# T! W
  13.                 //SYSCLK周期与闪存访问时间的比例设置
    # s- @! |/ l/ E) y+ Y
  14.                 FLASH_SetLatency(FLASH_Latency_2);
    # g: M% J) E- s9 l/ @: [
  15.                 //Configures the AHB clock (HCLK): AHB clock = SYSCLK
    * E  |9 A9 w4 o) b6 }4 v) z/ `9 ^
  16.                 RCC_HCLKConfig(RCC_SYSCLK_Div1);: W, P5 O9 c) M  a8 d
  17.                 //Configures the High Speed APB clock (PCLK2): APB2 clock = HCLK2 c1 H* q' p6 O7 r1 n
  18.                 RCC_PCLK2Config(RCC_HCLK_Div1);
    8 n0 x: l" V4 j+ G9 @
  19.                 //Configures the High Speed APB clock (PCLK2): APB1 clock = HCLK/2# n' T) t* L) e! L. ~+ g6 |
  20.                 RCC_PCLK1Config(RCC_HCLK_Div2);" E* Y+ V  m, `, C' J. N" Q
  21.                 //Configures the PLL clock source and multiplication factor:
      {4 s* W* \& b
  22.                 //HSE oscillator clock selected as PLL clock entry
    " {, V1 P9 I+ t" U2 N( J
  23.                 //The PLL multiplication factor is 9* q4 a: G. t2 B- e$ s; A
  24.                 RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);
    . l' ^4 U# T# `, v& h  ^
  25.                 //Enables the PLL.5 I# x/ p" ?5 R' E
  26.                 RCC_PLLCmd(ENABLE);& O9 ^+ O2 q& |4 [! g* B3 P& F! N
  27.                 //等待PLL时钟稳定
    ; e% P8 {7 C+ v6 p& L. j
  28.                 while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET)+ ?- X4 `( R6 _/ k
  29.                         ;
    % J* p8 _: X9 O' h$ k* [
  30.                 //Configures the system clock (SYSCLK): PLL selected as system clock
      M! _7 W: @1 `) W
  31.                 RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
    8 t3 q" E6 J1 M$ N; L! i( ]& @
  32.                 //读取时钟切换状态位,确保PLLCLK被选为系统时钟
    0 E5 ~% p& z2 @6 T
  33.                 while (RCC_GetSYSCLKSource() != 0x08). O2 I; G6 L; S' i6 c
  34.                         ;' `/ z7 ~' ]4 c0 P
  35.         }3 P# y8 q5 K, F7 {0 F; V" ^, {
  36.         //HSE启动失败
    3 Z. B. u0 k) \
  37.         else: X7 n% E4 M% x
  38.         {& `9 R% R) a0 r1 ~8 G1 V! W2 c1 I3 s
  39.                 while (1)
    $ g( ~: w; K" V* R7 S  A
  40.                         ;7 M  v" V3 x, B( D7 t. k/ p4 X
  41.         }  g, T; X# k6 E& @8 m( `
  42. }
复制代码
) x3 ~; Z: C1 d' O5 x7 K
GPIO配置
" O, z* q3 q; R2 R/ `7 [以PB10, PB11, PB12, PB13作为外部中断输入口为例:* B: {) V+ a8 i8 [
5 r4 F9 y5 ]5 @+ u# ?/ x, Y
  1. void GPIO_Config(): V% N( I/ |3 Q# Y; [
  2. {7 l8 g$ a& ?. S! L6 R( V1 s
  3.         GPIO_InitTypeDef GPIO_InitStructure;
    2 Y! x$ g! T5 f$ a1 ?* E- `7 t
  4.         ! t5 t. _. l) }' c4 a% U
  5.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);5 B# k5 c" c2 C' s* C) Y
  6.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
    % T5 ?; c' k9 E0 z4 |; `1 K3 k4 v
  7.         " y5 z9 k0 k/ q7 }
  8.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13;
    9 H, P" m! r9 d
  9.         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;* g! B% D7 w; N8 {. [, F
  10.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    2 ]7 S5 D+ @; v8 x+ @* Y
  11.         
    ) [0 ^8 w5 L1 M( `( S; H' w! i
  12.         GPIO_Init(GPIOB, &GPIO_InitStructure);2 P4 N1 s3 F2 _
  13.         //选择EXTI的信号源2 d) c! I; M& y+ f/ @/ T# }, O' e
  14.         GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource10);
    # V. F; [# E! G- ~. a- O
  15.         GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource11);
    : i6 |. p+ @, i2 }- U
  16.         GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource12);
    , G/ g% ]% O* \
  17.         GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource13);
    & Y# u" {  s% s4 S+ I  Y0 L7 F
  18. 7 u& {  b4 o1 Z; V6 @: q; a
  19. }
复制代码
. e, L& j' |8 R" Y) t. U9 S: L
EXTI配置2 k/ i2 ~3 u  w4 h2 b* X& m
EXTI (External interrupt/event controller): 外部中断/事件控制器,管理了控制器的 20个中断/事件线。每个中断/事件线都对应有一个边沿检测器,可以实现输入信号的上升沿检测和下降沿的检测。EXTI 可以实现对每个中断/事件线进行单独配置,可以单独配置为中断或者事件,以及触发事件的属性。; ]( ?3 t" s& g$ O
5 H$ I$ _: f6 E' |) }
  1. void EXTI_Config()( `! o0 f7 p% t5 E6 ^& B4 y) c' o
  2. {
    / v! q- T5 N$ r. k. s$ c% p
  3.         EXTI_InitTypeDef EXTI_InitStructure;. q; v: b1 f6 i! s) N8 h

  4. 8 P) R2 Q" t$ z! t
  5.         EXTI_InitStructure.EXTI_Line=EXTI_Line10 | EXTI_Line11 | EXTI_Line12 | EXTI_Line13;- a% Y3 ~6 G! i# V$ Y/ G1 f
  6.         EXTI_InitStructure.EXTI_Mode=EXTI_Mode_Interrupt;
    & G! }9 X: U/ M1 o* V8 O
  7.         EXTI_InitStructure.EXTI_Trigger=EXTI_Trigger_Falling;" g' U  k7 X, P/ g2 \9 g
  8.         EXTI_InitStructure.EXTI_LineCmd=ENABLE;
    0 l' ^! y1 e( X# q
  9.         
    ; c' I, ]1 x+ s
  10.         EXTI_Init(&EXTI_InitStructure);
    4 h. U0 X$ Y/ [: s7 }
  11. }
复制代码
# q: h1 W, c0 s
NVIC配置% A0 T/ l* i# t; E
NVIC 是嵌套向量中断控制器,控制着整个芯片中断相关的功能,它跟内核紧密耦合,是内核里面的一个外设。但是各个芯片厂商在设计芯片的时候会对 Cortex-M3内核里面的 NVIC进行裁剪,把不需要的部分去掉,所以说 STM32 的 NVIC 是 Cortex-M3 的 NVIC 的一个子集。
: L# T. `' l0 m. @$ k7 k
; c( y7 p' a& x* A# Q在 NVIC 有一个专门的寄存器:中断优先级寄存器 NVIC_IPRx,用来配置外部中断的优先级,IPR 宽度为 8bit,原则上每个外部中断可配置的优先级为 0~255,数值越小,优先级越高。! h% c7 g6 V! @7 ]8 g& O0 |8 z

% E4 L9 @2 E* v但是绝大多数CM3芯片都会精简设计,以致实际上支持的优先级数减少,在F103中,只使用了高 4bit用于表达优先级的这 4bit,又被分组成抢占优先级和子优先级。
; `/ m% ]6 T# E( B1 K9 U
+ x7 L$ X- ~! a' `, J4 u! D如果有多个中断同时响应,抢占优先级高的就会 抢占 抢占优先级低的优先得到执行,如果抢占优先级相同,就比较子优先级。如果抢占优先级和子优先级都相同的话,就比较他们的硬件中断编号,编号越小,优先级越高。  p) g! ^( \/ Y9 t4 K) c3 L

# f6 M4 P1 D  K: u; q8 E; M. n
  1. void NVIC_Config()# T; v0 x/ n5 ~0 A- s
  2. {& w  C9 t, Y% \' @3 H
  3.         NVIC_InitTypeDef NVIC_InitStructure;* [: e  n/ N2 r2 L7 W/ L
  4.         //NVIC_PriorityGroup_2: 2 bits for pre-emption priority & 2 bits for subpriority
    $ h. w$ x8 Y  S2 V
  5.         NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
    + r& y- t2 ]7 A9 g1 j
  6. % E0 x2 f3 Y6 S
  7.           NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn;" a* P2 i3 z2 M% v
  8.           NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x00; % {9 A# \+ W' e7 e. G' |: `
  9.           NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x01;
    ( _$ s, v& [1 Z2 G1 N4 x
  10.           NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;; o9 ?6 H. C* \+ {# {
  11.           / m+ D5 f# ]7 }' m
  12.           NVIC_Init(&NVIC_InitStructure);
    1 h: O% z, X  ~* b
  13. }
复制代码

: m. O/ S# p; [中断服务函数 IRQ_Handler
6 k* L& y. t. |在启动文件 startup_stm32f10x_xd.s 中,我们已经初始化了中断向量表。实际的中断服务函数都需要重新编写,为了方便管理,可以把中断服务函数统一写在 stm32f10x_it.c 这个源文件中。关于中断服务函数的函数名必须跟启动文件里面预先设置的一样,否则系统就在中断向量表中找不到中断服务函数的入口,实现不了中断。" e+ T! [. y* ^7 h

; @0 g4 w; S2 a0 U# F* @
  1. void EXTI15_10_IRQHandler(void)
    ; o% E% e8 Y, x, h2 K- x& q# b0 z
  2. {" K) P8 R" y/ i, ]& ~8 R- \
  3.         if(EXTI_GetITStatus(EXTI_Line10)!=RESET)9 w: s* u# q' J. w
  4.         {
    0 H+ `# Q5 f  d+ `
  5.                 DoSomething_Line10();  j* F" i& F$ @& S; q
  6.                 EXTI_ClearITPendingBit(EXTI_Line10);2 B& m- s4 p; ~" S
  7.         }) a5 a  F8 ]7 o4 e  k4 a/ E
  8.         else if(EXTI_GetITStatus(EXTI_Line11)!=RESET)
    1 W, m9 F* c/ K) A7 ^$ A% G) X
  9.         {4 I- O: G- r4 @- ]4 R
  10.                 DoSomething_Line11();  i! B/ @6 k+ R" r% y
  11.                 EXTI_ClearITPendingBit(EXTI_Line11);
    . z+ k5 N# s" Y5 }( ]! @+ t1 G
  12.         }
    6 m! @5 l% e; f( L. l# z
  13.         else if(EXTI_GetITStatus(EXTI_Line12)!=RESET)
    4 Y, [- l% j5 G
  14.         {
    + B6 X* P2 N6 f' u  p# X0 o% n# P
  15.                 DoSomething_Line12();4 k  h0 v# U7 K. B# O
  16.                 EXTI_ClearITPendingBit(EXTI_Line12);& \5 g, W( \  ^' J1 m; Z7 h
  17.         }; p; H; i& [) Y+ a
  18.         else if(EXTI_GetITStatus(EXTI_Line13)!=RESET)" S: |6 ~' Y* p' A$ e
  19.         {( N, y8 [. {9 {* `4 Q0 k
  20.                 DoSomething_Line13();6 S8 A: E, N6 b- d  I# t
  21.                 EXTI_ClearITPendingBit(EXTI_Line13);
    ' ?+ b4 g- {. E6 D( X9 k; G/ A
  22.         }
    & S1 l" F: @! u! O- @7 e* N1 r
  23.         else if(EXTI_GetITStatus(EXTI_Line14)!=RESET)$ U, x+ x* K  P; q& H9 ^* Y2 H7 e
  24.         {) |" n' M6 r- ?
  25.                 DoSomething_Line14();. c8 `  _  k; U- V2 k
  26.                 EXTI_ClearITPendingBit(EXTI_Line14);
    " x( w- u& v3 Z( j1 p
  27.         }( T% J; V$ G2 H7 o: B
  28.         else if(EXTI_GetITStatus(EXTI_Line15)!=RESET)9 P" n% |( a4 ]9 G; p
  29.         {
    5 ], _) M6 R( _
  30.                 DoSomething_Line15();
    # T. H& L) R9 T# o+ G& A
  31.                 EXTI_ClearITPendingBit(EXTI_Line15);, Z2 N; P# }( J. ~
  32.         }  ]2 q; w  G( K7 C' y/ `1 [
  33.         else
    ; h2 U. J3 N! L/ K
  34.         {
    % o) x6 U  y1 Q* B1 p7 r. D
  35. . h2 r: X5 _4 {
  36.         }" k# `' U% C" v6 X- G. v0 J
  37. }
复制代码
, J- h$ A$ b- N
' s* b3 e5 O' e0 c5 o) ?
; k$ E! U( C) x  L

3 N5 q' L1 {  b( i! O6 _; e
赞 收藏 评论0 发布时间:2022-4-15 10:00

举报

0个回答

所属标签

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版