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

【经验分享】STM32CubeMX教程-GPIO输入之外部中断

[复制链接]
STMCU小助手 发布时间:2022-6-26 14:04
    本篇主要讲述GPIO外部中断输入检测,实际物理输入方式是按键,但是实际上更适合外部设备信号的输入检测,物理按键输入因为有抖动,还需要硬件或者软件去抖才比较可靠。这个例子不考虑防抖的情况。
软件版本:
! L; B* S1 p$ H- B% d2 V! d) oSTM32CubeMX V4.25.0  . E- r5 j( D7 `1 V2 D5 ^
System Workbench V2.4
硬件:OneNet 麒麟座V2.3
    在STM32CubeMX中新建项目,选择正确的MCU型号
& L5 V! z  k; A' a
P3(JN_GJJ{EAO_QWJ71@6QD.png

+ U2 S, U0 X' j  ]' K; P
    设置RCC和SYS,然后根据板子实际情况设置时钟(麒麟座外部晶振是12M,STM32F103x的最高主频是72M)
: F9 k4 `8 {' Q: W0 [- \$ C
RNKZ)M(_OU8}{69@22(N}6L.png
! m' C: K- h; [- J  z+ m
    根据板子的具体连接设置4个GPIO_OUTPUT (连接到LED)和4个GPIO_EXIT*(外部中断模式,连接到物理按键)。
SHZX%))XIBBR8WZL0}[)G]A.png

( l1 E8 y2 F; k/ L% ~% T' L
    GPIO OUTPUT引脚设置

2 H! S0 N) l/ q6 ^+ N% d  j
867WS$DX8`YK)@IR`YNS.png
! x) K3 r6 j: U: o
    麒麟座按键有外部上拉,所以GPIO_EXIT*不需要配置内部上拉,检测下降沿(Falling Edge),GPIO_EXIT*设置如下
8 ?3 A; T. F4 [' Q! w7 B
9M5YZ$CD02I44WJYP9VO404.png

7 P$ n, [( @# s* X6 t  Y9 {, F8 ]
    LED名称标号我用了1/2/3/4,SW名称标号我用了2/3/4/5,实例中标号也未必相同,但是要做好一一对应关系。
    在NVIC(嵌套向量中断控制器)中,勾选EXIT Line2 interrupt 和 EXIT Line[15:12] interrupt 使能中断。右边两个选项设置抢占优先级和响应优先级。此处我们选择默认的,不修改。
{OV8`3U_BK65%E~V~5KL0)G.png

' }: N& Z& |2 }/ E& r) A
    同样修改Project - setting ,ToolChain/IDE选择 SW4STM32
微信图片_20220626140135.png

. B8 Q* l; L1 F" P- @6 G2 u
    勾选这里。
NF~XL]W(CZA)S%$OYWXYI0S.png
- O2 }0 Z: x+ G( [' V. f& M) @  |
    生成代码后点击Open Project在Eclipse中打开项目,然后在 在stm32f7xx_it.c中断服务函数文件中,我们可以找到EXTI2 和EXTI15_10中断的服务函数。
  1. /******************************************************************************/
    + b5 S+ G# e  b2 \: g# k2 V3 X" j
  2. /* STM32F1xx Peripheral Interrupt Handlers                                    */1 c- ]( f; Q& L7 d2 D% K: @# V
  3. /* Add here the Interrupt Handlers for the used peripherals.                  */
    - E9 L' i2 F! Z
  4. /* For the available peripheral interrupt handler names,                      */' s3 C$ [: d1 e/ J5 T+ o! V  w
  5. /* please refer to the startup file (startup_stm32f1xx.s).                    */
    ! F7 X6 h  l' d. V/ k
  6. /******************************************************************************/3 J: z4 c0 d' q! f! i
  7. /**
    9 o+ t5 u, Q3 h( R" `" Y6 c6 O/ H
  8. * @brief This function handles EXTI line2 interrupt.
    6 U! _' v/ x; [; Z
  9. *// b  R8 J/ a3 j1 Y( Z; Q
  10. void EXTI2_IRQHandler(void)  Z: F. @3 c' t2 _/ ~4 {
  11. {+ l  n: Z$ f" J& {1 Z
  12. /* USER CODE BEGIN EXTI2_IRQn 0 */2 o" V" n- m# b" X; E
  13. /* USER CODE END EXTI2_IRQn 0 */
    ) n9 {) \8 ~# Z
  14. HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_2);
    & C) N0 e+ s: x
  15. /* USER CODE BEGIN EXTI2_IRQn 1 */' M; ?5 y; S+ r& @( W
  16. /* USER CODE END EXTI2_IRQn 1 */  ]& O+ x9 [) L: K
  17. }: x+ b) M! K+ C6 C
  18. /**
    1 a4 l+ H0 T. [* }# }8 L) d6 v
  19. * @brief This function handles EXTI line[15:10] interrupts.% A8 _; k+ f7 c
  20. */) Q$ ~5 `+ m* e4 r
  21. void EXTI15_10_IRQHandler(void)* E1 `% ^# y( |+ [
  22. {
    # H8 G; h; ]0 U. @5 ^( _6 G
  23. /* USER CODE BEGIN EXTI15_10_IRQn 0 */
    : }; y8 z' S! s- M2 B. ~! m/ }1 r
  24. /* USER CODE END EXTI15_10_IRQn 0 */
    + e0 N& b7 e" H* ?7 Z
  25. HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_11);
    ' ~9 V  Z  M8 n  E
  26. HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_12);
      ]6 R' H9 U" x2 o$ [
  27. HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_13);7 R. B4 c& `4 ~) y; C' ^* o
  28. /* USER CODE BEGIN EXTI15_10_IRQn 1 */, e! h% l+ K' Z
  29. /* USER CODE END EXTI15_10_IRQn 1 */2 I8 I; r, K( R# L- D- C$ f- Z
  30. }
复制代码
* K7 O$ n7 ?$ u/ S4 r
    右键点击HAL_GPIO_EXTI_IRQHandler 选择"Open Declaration"会跳转到如下代码:
  1. /**
    & D- l; L8 Q. D% S% V; S! L6 x
  2.   * @brief  This function handles EXTI interrupt request.2 L4 l4 k" I+ z# Z$ M( w! ^% O
  3.   * @param  GPIO_Pin: Specifies the pins connected EXTI line5 M+ N% j9 m  g% V
  4.   * @retval None' m$ G& ?' m: w2 x# h) g
  5.   */  y& R3 }- P( g6 d& J0 A
  6. void HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin)" z$ B5 V4 @6 l5 z9 A
  7. {
    2 |' M7 T  _0 C6 E9 E
  8. /* EXTI line interrupt detected */
      Z8 W3 m' E2 i- E
  9. if (__HAL_GPIO_EXTI_GET_IT(GPIO_Pin) != RESET)5 x6 N) n1 f0 ], x( d
  10. {
      Z0 c' f$ ]9 P7 Z0 ?- W$ B$ {* {
  11. __HAL_GPIO_EXTI_CLEAR_IT(GPIO_Pin);
    7 i+ I; y7 v6 h: t3 S- ^
  12. HAL_GPIO_EXTI_Callback(GPIO_Pin);9 D3 W5 Q, ^+ j0 @9 Z
  13. }
    : k, T+ k8 g( e9 y) k) L% m. q
  14. }
    6 I- m9 I) z9 j
  15. /**) p& c! R3 M8 ~
  16.   * @brief  EXTI line detection callbacks.; z+ m+ ]- W7 Y+ \! H1 i
  17.   * @param  GPIO_Pin: Specifies the pins connected EXTI line
    - R+ B- j9 R/ R& s( Z7 h! k
  18.   * @retval None1 k' l4 V4 m% {; m( b3 s0 h' b
  19.   */
    8 B( j. [5 h6 J# Z; H
  20. __weak void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
    $ B+ q1 d: f- Q/ D, L) A
  21. {
    - Z; @( v( H- B3 U( x8 z
  22. /* Prevent unused argument(s) compilation warning */
    7 O+ Q; l& _8 E- L6 @% j
  23. UNUSED(GPIO_Pin);
    - j7 E7 U8 b, `% o% y, \
  24. /* NOTE: This function Should not be modified, when the callback is needed,. ]* H$ N$ W. D9 f! [
  25.            the HAL_GPIO_EXTI_Callback could be implemented in the user file- \; Y. |: @% Y9 R& g
  26.    */
    & \6 y$ d$ F5 y! }  i
  27. }
复制代码

  A" [1 g3 ~' ]4 s1 G- C% l4 z% m4 F
    上述代码中可以看到GPIO外部中断处理函数首先清除中断标识位,然后调用中断回调函数HAL_GPIO_EXTI_Callback()。往下看这个回调函数定义的时候使用了__weak修饰符(关于__weak修饰符, 可以参看此博文),里面没有任何有作用的代码,我们需要重新定义这个函数。编辑gpio.c(或者main.c也可以),进行如下修改:
  1. /* USER CODE BEGIN 2 */, p  f$ H+ _" j; J& X- ~) O
  2. void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)5 p; M- J5 P- ~) |8 N
  3. {; @$ a" ]3 j9 o' T5 g# G$ Z% L( y
  4.   if(GPIO_Pin == SW2_Pin)
    4 Z1 I4 u/ x4 m: `' x  U6 B5 ~* Q
  5.   {2 S4 d6 |7 z1 s8 [% q5 D1 _
  6.   HAL_GPIO_TogglePin(LED1_GPIO_Port,LED1_Pin);
    * L4 e! X* ^! C
  7.   }
    6 Q9 K$ O4 ~5 }7 ~5 R/ Y! t: T. Q
  8.   if(GPIO_Pin == SW3_Pin), \0 i. w  s7 a% x3 K6 @8 S# L8 b. F
  9.   {  c' r3 t6 n( z+ e) V$ P
  10.   HAL_GPIO_TogglePin(LED2_GPIO_Port,LED2_Pin);
    - Z6 v3 H. j' C
  11.   }
    ; z, K$ @1 S+ N- Y* t- h" b) y
  12.   if(GPIO_Pin == SW4_Pin)3 }0 h! S' {" ~9 @; K( S
  13.   {
    1 [  R9 S' b  U  \) M) J
  14.   HAL_GPIO_TogglePin(LED3_GPIO_Port,LED3_Pin);  q) C/ U$ _  i  ?
  15.   }1 W, S7 `" h! Z4 {. _5 d( r
  16.   if(GPIO_Pin == SW5_Pin)
    . C% l% `  C1 W+ |( x" O* ]* V
  17.   {) d$ Q* |8 n( H8 W
  18.   HAL_GPIO_TogglePin(LED4_GPIO_Port,LED4_Pin);2 F* ?$ G+ q! \, Q) M6 v! m& W$ T
  19.   }
    1 O9 n" X0 _% `' `- F1 B
  20. }
    % `# ~5 s( P4 s0 U. D6 ?
  21. /* USER CODE END 2 */
复制代码
8 [8 T8 k. L0 s0 w3 O) I9 x
     然后右键点击项目,选择Properties, Run-Debug Settings, 点击右侧的New,在弹出对话框中选择Ac6 STM32 Debugging。

% }) w  h. r, r5 g" D5 Q) G
B%P@V9W8U3M94COZI6E01ZJ.png
) G7 v0 y0 Z$ r! Y* o; q9 k
    然后任务栏上点击Run图,当然会报错的,原因请查看另一篇我的博客,所以需要右键点击  项目名Run.cfg ,给它改个名字,

6 a! ~. E$ F. Z
I3CK6X3D]CWV~87E7LXL{[1.png
9 M+ T- q. L; P- I% b+ K- r
    然后右键点击项目树里面的项目名称,选择“Propeties”,然后在Run/Debug Settings-选择项目名-Edit-Main-C/C++Application那里点击“Search Project”,然后选择出现的默认的elf文件:

! w) P" ]: C# ]. {' N9 t5 L
微信图片_20220626140034.png
$ Q+ o  ~4 u  l7 p
    然后在Debugger-User Defined-Browse 那里选择你自己改名的配置文件:

1 W9 `* u9 S/ [+ I3 _
微信图片_20220626140031.png

* I1 O9 h9 ?; Y5 c6 s/ ?. {# T* v! Q2 l
    然后右键点击那个新的cfg文件,选择"Open With - Text Editor", 进行如下更改:
  1. source [find interface/stlink.cfg]
    2 R1 p" I2 Q# f, V' V9 G3 Y3 ]
  2. //更改为 source [find interface/stlink-v2.cfg]
    . U4 J: g+ Y( }* T9 N( e' K# R# H
  3. 6 r) z. D9 @( `- w1 h
  4. reset_config srst_only srst_nogate connect_assert_srst - M0 {4 b# T- g4 U$ v$ t
  5. //这一行改为 reset_config none
复制代码

/ }$ Q! r  j9 i  a- ]5 h$ f
    Run一下,就可以了。然后再Run一下,就实现四个按键分别控制LED的开关切换了。但是这里没有防抖处理,你会发现有时候LED会闪一下,或者没反应,其实是很快地点亮然后熄灭一次或者若干次,只是由于速度太快电流很小导致你看不到。下一篇我们会通过使用SysTick中断来实现按键去抖扫描。在实际项目中,最好加上硬件防抖,因为抖动产生的反向电压可能会冲击GPIO导致损坏。
" e5 V  e  V7 }& T
赞 收藏 评论0 发布时间:2022-6-26 14:04

举报

0个回答

所属标签

相似技术帖

官网相关资源

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