当前位置:   article > 正文

STM32(三):外部中断 (标准库函数)_stm32外部中断的库函数程序怎么写

stm32外部中断的库函数程序怎么写

前言

上一篇文章已经介绍了如何用按键点灯,使用的是按键扫描的方式,实现了点灯的第二步。这一篇则介绍如何用外部中断的方式实现按键点灯的过程。

一、实验原理

1.外部中断的定义

中断想必大家都知道,通俗来说也就是你现在在做事情1,被打扰了先去做了事情2,事情2做完了回去继续做事情1。

而STM32的外部中断也是如此,只是它做的事情跟你做的不太一样罢了,而且对处理事情有更为严格的优先级关系。举个通俗的例子,它在做事情1,但是被事情2和事情3同时打扰了,事情2的优先级大于事情3,那么它会先去做事情2再去做事情3,都做完了才回归主线事情1。所以有利于提高cpu的利用率。

2.外部中断的介绍

嵌入式要学好必然要把图看好,那么先上个外部中断的流程框图:

2.1 STM32的外部中断线

每个输入线可以独立地配置输入类型(脉冲或挂起)和对应的触发事件(上升沿或下降沿或者双边沿触发)。每个输入线都可以独立地被屏蔽。挂起寄存器保持着状态线的中断请求。

 STM32的中断控制器支持19个外部中断/事件请求:

  • 线0~15:对应外部IO口的输入中断。
  • 线16:连接到PVD输出。
  • 线17:连接到RTC闹钟事件。
  • 线18:连接到USB唤醒事件

2.2 外部中断线与IO引脚对应关系  

每个IO口都可以对应作为中断,几个IO口为一组映射到一个中断线上,如GPIOx.0映射到EXTI0,GPIOx.1映射到EXTI1,...,GPIOx.15映射到EXTI15.

外部中断通用I/O映像

2.3外部中断所需寄存器

STM32外部中断需要用到以下几个寄存器:

  1.  中断屏蔽寄存器(EXTI_IMR)
  2. 事件屏蔽寄存器(EXTI_EMR)
  3. 上升沿触发选择寄存器(EXTI_RTSR)
  4. 下降沿触发选择寄存器(EXTI_FTSR)
  5. 软件中断事件寄存器(EXTI_SWIER)
  6. 挂起寄存器(EXTI_PR) 

2.4外部中断与中断服务函数

IO口外部中断只有7个中断服务函数

  • EXTI0~EXTI4 分别对应一个中断服务函数
  • EXTI5~EXTI9 对应一个中断服务函数 
  • EXTI10~EXTI15 对应一个中断服务函数

ps:这边值得注意的是EXTI5~EXTI9与EXTI10~EXTI15对应的都只有一个中断服务函数,所以要是出现在这范围出现多个线程的中断会有点问题,但在后面对这问题进行了解决。而且还有多个IO口出现同一线程该如何区分开的问题,也对其进行解决。

二、实验步骤

1.NVIC配置

1. 对NVIC初始化,用到 NVIC_InitTypeDef 结构体,其中四个成员:  

  • NVIC_IRQChannel参数来选择将要配置的中断向量;
  • NVIC_IRQChannelCmd参数来进行使能(ENABLE)或关闭(DISABLE)该中断;
  • NVIC_IRQChannelPreemptionPriority成员要配置中断向量的抢占优先级;
  • NVIC_IRQChannelSubPriority需要配置中断向量的子优先级(响应优先级);

2. NVIC只可配置16种中断向量的优先级:编号越小,优先级别越高;

3. 抢占优先级:是指打断其它中断,会出现嵌套中断;

4. 子优先级(响应优先级):先处理响应优先级高的中断; 

  1. /* 选择中断优先级配置组为4个抢占式优先级和4个子优先级,可以参考misc.h文件了解相关设置 */ NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
  2. /* 使能KEY1所在的外部中断通道 */
  3. NVIC_InitStructure.NVIC_IRQChannel = KEY_IRQCHANNEL;
  4. /* 设置抢占式优先级为2 */
  5. NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02;
  6. /* 设置子优先级为3 */
  7. NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x03;
  8. /* 使能外部中断通道 */
  9. NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  10. /* 初始化配置嵌套向量中断控制器 */
  11. NVIC_Init(&NVIC_InitStructure);

2.EXTI配置

EXTI的配置步骤如下所示:

 ①使能EXTIx线的IO时钟和复用时钟(AFIO)

 ②配置EXTI中断线与I/O的映射关系

 ③EXTI的I/O口线引脚和工作模式的配置

 ④配置EXTIx线的中断优先级

 ⑤EXTI 中断线工作模式配置

  1. /* 为启用IO引脚中断功能需要使能复用功能时钟 */
  2. KEY1_RCC_CLOCKCMD(KEY1_RCC_CLOCKGPIO | KEY1_RCC_CLOCKAFIO,ENABLE);
  3. /* 选择PE7作为中断输入源 */
  4. GPIO_EXTILineConfig(KEY1_GPIO_PORTSOURCE,KEY1_GPIO_PINSOURCE);
  5. /* KEY1对应的断线 */
  6. EXTI_InitStructure.EXTI_Line=KEY1_EXITLINE;
  7. /* 外部中断模式 */
  8. EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
  9. /* 上升沿触发方式 */
  10. EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
  11. /* 使能中断 */
  12. EXTI_InitStructure.EXTI_LineCmd = ENABLE;
  13. /* 根据EXTI_InitStruct中指定的参数初始化外设EXTI寄存器 */
  14. EXTI_Init(&EXTI_InitStructure);

其中AFIO的作用是信号传输媒介或者说是信号搬运工,EXTI的时钟是由AFIO提供的,所以需要开启。而AFIO时钟在APB2总线上的原因是端口重映射之后,映射的新引脚都是GPIO的引脚,GPIOx又是APB2的外设,使用APB2给其提供时钟非常合适。

参考:AFIO时钟误区及其用法解析-CSDN博客

3.中断函数

  1. /* 中断服务函数,用于产生中断动作 */
  2. EXTIx_IRQHandler();
  3. /* 中断判断函数,用于判断中断动作 */
  4. EXTI_GetITStatus()
  5. /* 中断清除函数,用于清除中断动作 */
  6. EXTI_ClearITPendingBit()

上面说过由于EXTI5~EXTI9与EXTI10~EXTI15分别对于中断服务函数EXTI9_5_IRQHandler和EXTI15_10_IRQHandler,所以要是出现在这范围出现多个线程的中断,可能会出现问题,则需要进行对线程判断的处理,以及对IO口判断的处理。

  1. void KEY_IRQHANDLER(void)
  2. {
  3. /* 处理Line7的中断 */
  4. if(EXTI_GetITStatus(EXTI_Line7) != RESET)
  5. {
  6. /* 处理GPIOA的PIN7的中断,若没有多个IO占用Line7可以注释 */
  7. if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_7) == Bit_SET) // 检查引脚状态
  8. {
  9. //事件
  10. }
  11. /* 处理EXTI_Line7的中断 */
  12. EXTI_ClearITPendingBit(EXTI_Line7);
  13. }
  14. // 重复上述逻辑,检查其他线(如EXTI_Line5, EXTI_Line6,...)
  15. }

三、实操代码

程序分为3个文件:bsp_key.c、bsp_key.h、main.c

1.bsp_key.c

这边值得注意的是KEY的引脚线序,对下方代码进行选取,我都为大家列好情况了,看下注释即可。

  1. /* 包含头文件 ----------------------------------------------------------------*/
  2. #include "bsp/key/bsp_key.h"
  3. /**
  4. * 函数功能: 配置KEY作为中断引脚并使能中断
  5. * 输入参数:无
  6. * 返 回 值: 无
  7. * 说 明:配置KEY为上升沿中断,当按下按键时就有一个从低电平变为高
  8. * 电平过程。
  9. */
  10. void KEY1_EXIT_Config(void)
  11. {
  12. /* 定义IO硬件初始化结构体变量 */
  13. GPIO_InitTypeDef GPIO_InitStructure;
  14. /* 定义外部中断线初始化结构体变量 */
  15. EXTI_InitTypeDef EXTI_InitStructure;
  16. /* 定义嵌套向量中断控制器初始化结构体变量 */
  17. NVIC_InitTypeDef NVIC_InitStructure;
  18. /* 为启用IO引脚中断功能需要使能复用功能时钟 */
  19. KEY1_RCC_CLOCKCMD(KEY1_RCC_CLOCKGPIO | KEY1_RCC_CLOCKAFIO,ENABLE);
  20. /* 设定KEY1对应引脚IO编号 */
  21. GPIO_InitStructure.GPIO_Pin = KEY1_GPIO_PIN;
  22. /* 设定KEY1对应引脚IO最大操作速度 :GPIO_Speed_50MHz */
  23. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  24. /* 设定KEY1对应引脚IO为浮空输入模式 */
  25. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
  26. /* 初始化KEY1对应引脚IO */
  27. GPIO_Init(KEY1_GPIO, &GPIO_InitStructure);
  28. /* 选择PE7作为中断输入源 */
  29. GPIO_EXTILineConfig(KEY1_GPIO_PORTSOURCE,KEY1_GPIO_PINSOURCE);
  30. /* KEY1对应的断线 */
  31. EXTI_InitStructure.EXTI_Line=KEY1_EXITLINE;
  32. /* 外部中断模式 */
  33. EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
  34. /* 上升沿触发方式 */
  35. EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
  36. /* 使能中断 */
  37. EXTI_InitStructure.EXTI_LineCmd = ENABLE;
  38. /* 根据EXTI_InitStruct中指定的参数初始化外设EXTI寄存器 */
  39. EXTI_Init(&EXTI_InitStructure);
  40. /* 选择中断优先级配置组为4个抢占式优先级和4个子优先级,可以参考misc.h文件了解相关设置 */
  41. NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
  42. /* 使能KEY1所在的外部中断通道 */
  43. NVIC_InitStructure.NVIC_IRQChannel = KEY_IRQCHANNEL;
  44. /* 设置抢占式优先级为2 */
  45. NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02;
  46. /* 设置子优先级为3 */
  47. NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x03;
  48. /* 使能外部中断通道 */
  49. NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  50. /* 初始化配置嵌套向量中断控制器 */
  51. NVIC_Init(&NVIC_InitStructure);
  52. }
  53. void KEY2_EXIT_Config(void)
  54. {
  55. /* 定义IO硬件初始化结构体变量 */
  56. GPIO_InitTypeDef GPIO_InitStructure;
  57. /* 定义外部中断线初始化结构体变量 */
  58. EXTI_InitTypeDef EXTI_InitStructure;
  59. /* 定义嵌套向量中断控制器初始化结构体变量 */
  60. NVIC_InitTypeDef NVIC_InitStructure;
  61. /* 为启用IO引脚中断功能需要使能复用功能时钟 */
  62. KEY1_RCC_CLOCKCMD(KEY2_RCC_CLOCKGPIO | KEY2_RCC_CLOCKAFIO,ENABLE);
  63. /* 设定KEY2对应引脚IO编号 */
  64. GPIO_InitStructure.GPIO_Pin = KEY2_GPIO_PIN;
  65. /* 设定KEY2对应引脚IO最大操作速度 :GPIO_Speed_50MHz */
  66. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  67. /* 设定KEY2对应引脚IO为浮空输入模式 */
  68. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
  69. /* 初始化KEY2对应引脚IO */
  70. GPIO_Init(KEY2_GPIO, &GPIO_InitStructure);
  71. /* 选择PE8作为中断输入源 */
  72. GPIO_EXTILineConfig(KEY2_GPIO_PORTSOURCE,KEY2_GPIO_PINSOURCE);
  73. /* KEY2对应的断线 */
  74. EXTI_InitStructure.EXTI_Line=KEY2_EXITLINE;
  75. /* 外部中断模式 */
  76. EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
  77. /* 上升沿触发方式 */
  78. EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
  79. /* 使能中断 */
  80. EXTI_InitStructure.EXTI_LineCmd = ENABLE;
  81. /* 根据EXTI_InitStruct中指定的参数初始化外设EXTI寄存器 */
  82. EXTI_Init(&EXTI_InitStructure);
  83. /* 选择中断优先级配置组为4个抢占式优先级和4个子优先级,可以参考misc.h文件了解相关设置 */
  84. NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
  85. /* 使能KEY2所在的外部中断通道 */
  86. NVIC_InitStructure.NVIC_IRQChannel = KEY_IRQCHANNEL;
  87. /* 设置抢占式优先级为0 */
  88. NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x00;
  89. /* 设置子优先级为0 */
  90. NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x00;
  91. /* 使能外部中断通道 */
  92. NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  93. /* 初始化配置嵌套向量中断控制器 */
  94. NVIC_Init(&NVIC_InitStructure);
  95. }
  96. void KEY3_EXIT_Config(void)
  97. {
  98. /* 定义IO硬件初始化结构体变量 */
  99. GPIO_InitTypeDef GPIO_InitStructure;
  100. /* 定义外部中断线初始化结构体变量 */
  101. EXTI_InitTypeDef EXTI_InitStructure;
  102. /* 定义嵌套向量中断控制器初始化结构体变量 */
  103. NVIC_InitTypeDef NVIC_InitStructure;
  104. /* 为启用IO引脚中断功能需要使能复用功能时钟 */
  105. KEY1_RCC_CLOCKCMD(KEY3_RCC_CLOCKGPIO | KEY3_RCC_CLOCKAFIO,ENABLE);
  106. /* 设定KEY3对应引脚IO编号 */
  107. GPIO_InitStructure.GPIO_Pin = KEY3_GPIO_PIN;
  108. /* 设定KEY3对应引脚IO最大操作速度 :GPIO_Speed_50MHz */
  109. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  110. /* 设定KEY3对应引脚IO为浮空输入模式 */
  111. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
  112. /* 初始化KEY3对应引脚IO */
  113. GPIO_Init(KEY1_GPIO, &GPIO_InitStructure);
  114. /* 选择PE9作为中断输入源 */
  115. GPIO_EXTILineConfig(KEY3_GPIO_PORTSOURCE,KEY3_GPIO_PINSOURCE);
  116. /* KEY3对应的断线 */
  117. EXTI_InitStructure.EXTI_Line=KEY3_EXITLINE;
  118. /* 外部中断模式 */
  119. EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
  120. /* 上升沿触发方式 */
  121. EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
  122. /* 使能中断 */
  123. EXTI_InitStructure.EXTI_LineCmd = ENABLE;
  124. /* 根据EXTI_InitStruct中指定的参数初始化外设EXTI寄存器 */
  125. EXTI_Init(&EXTI_InitStructure);
  126. /* 选择中断优先级配置组为4个抢占式优先级和4个子优先级,可以参考misc.h文件了解相关设置 */
  127. NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
  128. /* 使能KEY3所在的外部中断通道 */
  129. NVIC_InitStructure.NVIC_IRQChannel = KEY_IRQCHANNEL;
  130. /* 设置抢占式优先级为1 */
  131. NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x01;
  132. /* 设置子优先级为1 */
  133. NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x01;
  134. /* 使能外部中断通道 */
  135. NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  136. /* 初始化配置嵌套向量中断控制器 */
  137. NVIC_Init(&NVIC_InitStructure);
  138. }
  139. /**
  140. * 函数功能: 针对KEY多根线序为5-9的中断服务函数
  141. * 输入参数:无
  142. * 返 回 值: 无
  143. * 说 明:在stm32f103检测到上升沿信号后会自动进入对应的中断服务函数,我们可以在
  144. * 服务函数内实现一些处理。
  145. * 多根线序为5-9的线
  146. */
  147. void KEY_IRQHANDLER(void)
  148. {
  149. if(EXTI_GetITStatus(EXTI_Line7) != RESET)
  150. {
  151. /* 延时一小段时间,消除抖动 */
  152. Delay(10);
  153. LED1_TOGGLE;
  154. /* 处理EXTI_Line7的中断 */
  155. EXTI_ClearITPendingBit(EXTI_Line7);
  156. }
  157. if(EXTI_GetITStatus(EXTI_Line8) != RESET)
  158. {
  159. Delay(10);
  160. LED2_TOGGLE;
  161. /* 处理EXTI_Line8的中断 */
  162. EXTI_ClearITPendingBit(EXTI_Line8);
  163. }
  164. if(EXTI_GetITStatus(EXTI_Line9) != RESET)
  165. {
  166. Delay(10);
  167. LED3_TOGGLE;
  168. /* 处理EXTI_Line9的中断 */
  169. EXTI_ClearITPendingBit(EXTI_Line9);
  170. }
  171. // 重复上述逻辑,检查其他线(如EXTI_Line5, EXTI_Line6)
  172. }
  173. /**
  174. * 函数功能: 针对KEY线序单独分开的中断服务函数
  175. * 输入参数:无
  176. * 返 回 值: 无
  177. * 说 明:在stm32f103检测到上升沿信号后会自动进入对应的中断服务函数,我们可以在
  178. * 服务函数内实现一些处理。
  179. * 线序单独分开的线
  180. */
  181. //void KEY1_IRQHANDLER(void)
  182. //{
  183. // /* 确保是否产生了EXTI Line中断 */
  184. // if(EXTI_GetITStatus(KEY1_EXITLINE) != RESET)
  185. // {
  186. // Delay(10);
  187. // /* LED1灯翻转 */
  188. // LED1_TOGGLE;
  189. // /* 清除中断标志位 */
  190. // EXTI_ClearITPendingBit(KEY1_EXITLINE);
  191. // }
  192. //}
  193. //void KEY2_IRQHANDLER(void)
  194. //{
  195. // if(EXTI_GetITStatus(KEY2_EXITLINE) != RESET)
  196. // {
  197. // Delay(10);
  198. // LED2_TOGGLE;
  199. // EXTI_ClearITPendingBit(KEY2_EXITLINE);
  200. // }
  201. //}
  202. //void KEY3_IRQHANDLER(void)
  203. //{
  204. // if(EXTI_GetITStatus(KEY3_EXITLINE) != RESET)
  205. // {
  206. // Delay(10);
  207. // LED3_TOGGLE;
  208. // EXTI_ClearITPendingBit(KEY3_EXITLINE);
  209. // }
  210. //}

2.bsp_key.h

这边值得注意的是KEY的引脚线序,对下方代码进行选取,我都为大家列好情况了,看下注释即可。

  1. #ifndef __BSP_KEY_H__
  2. #define __BSP_KEY_H__
  3. /* 包含头文件 ----------------------------------------------------------------*/
  4. #include <stm32f10x.h>
  5. #include "bsp/delay/delay.h"
  6. #include "bsp/led/bsp_led.h"
  7. /* 类型定义 --------------------------------------------------------------*/
  8. typedef enum
  9. {
  10. KEY_UP = 0,
  11. KEY_DOWN = 1,
  12. KEY_DOWN_LONG = 2,
  13. }KEYState_TypeDef;
  14. /* 宏定义 --------------------------------------------------------------------*/
  15. #define KEY1 (uint8_t)0x01
  16. #define KEY2 (uint8_t)0x02
  17. #define KEY3 (uint8_t)0x04
  18. #define IS_KEY_TYPEDEF(KEY) (((KEY) == KEY1) || ((KEY) == KEY2) || ((KEY) == KEY3))
  19. /* 宏定义 --------------------------------------------------------------------*/
  20. #define KEY1_RCC_CLOCKCMD RCC_APB2PeriphClockCmd
  21. #define KEY1_RCC_CLOCKGPIO RCC_APB2Periph_GPIOE
  22. #define KEY1_GPIO_PIN GPIO_Pin_7
  23. #define KEY1_GPIO GPIOE
  24. #define KEY1_DOWN_LEVEL 0 /* 根据原理图设计,KEY1按下时引脚为低电平,所以这里设置为0 */
  25. #define KEY1_RCC_CLOCKAFIO RCC_APB2Periph_AFIO
  26. #define KEY1_GPIO_PORTSOURCE GPIO_PortSourceGPIOE
  27. #define KEY1_GPIO_PINSOURCE GPIO_PinSource7
  28. #define KEY1_EXITLINE EXTI_Line7
  29. /* 根据线序来,需要用到则取消注释并修改*/
  30. //#define KEY1_IRQCHANNEL EXTI1_IRQn
  31. //#define KEY1_IRQHANDLER EXTI1_IRQHandler
  32. #define KEY2_RCC_CLOCKCMD RCC_APB2PeriphClockCmd
  33. #define KEY2_RCC_CLOCKGPIO RCC_APB2Periph_GPIOE
  34. #define KEY2_GPIO_PIN GPIO_Pin_8
  35. #define KEY2_GPIO GPIOE
  36. #define KEY2_DOWN_LEVEL 0 /* 根据原理图设计,KEY2按下时引脚为低电平,所以这里设置为0 */
  37. #define KEY2_RCC_CLOCKAFIO RCC_APB2Periph_AFIO
  38. #define KEY2_GPIO_PORTSOURCE GPIO_PortSourceGPIOE
  39. #define KEY2_GPIO_PINSOURCE GPIO_PinSource8
  40. #define KEY2_EXITLINE EXTI_Line8
  41. /* 根据线序来,需要用到则取消注释并修改*/
  42. //#define KEY2_IRQCHANNEL EXTI2_IRQn
  43. //#define KEY2_IRQHANDLER EXTI2_IRQHandler
  44. #define KEY3_RCC_CLOCKCMD RCC_APB2PeriphClockCmd
  45. #define KEY3_RCC_CLOCKGPIO RCC_APB2Periph_GPIOE
  46. #define KEY3_GPIO_PIN GPIO_Pin_9
  47. #define KEY3_GPIO GPIOE
  48. #define KEY3_DOWN_LEVEL 0 /* 根据原理图设计,KEY3按下时引脚为低电平,所以这里设置为0 */
  49. #define KEY3_RCC_CLOCKAFIO RCC_APB2Periph_AFIO
  50. #define KEY3_GPIO_PORTSOURCE GPIO_PortSourceGPIOE
  51. #define KEY3_GPIO_PINSOURCE GPIO_PinSource9
  52. #define KEY3_EXITLINE EXTI_Line9
  53. /* 根据线序来,需要用到则取消注释并修改*/
  54. //#define KEY3_IRQCHANNEL EXTI3_IRQn
  55. //#define KEY3_IRQHANDLER EXTI3_IRQHandler
  56. /* KEY多根线序为5-9,不用则注释 */
  57. #define KEY_IRQCHANNEL EXTI9_5_IRQn
  58. #define KEY_IRQHANDLER EXTI9_5_IRQHandler
  59. #define IRQ_DISABLE __set_PRIMASK(1) /* 关闭总中断 */
  60. #define IRQ_ENABLE __set_PRIMASK(0) /* 开放总中断 */
  61. /* 扩展变量 ------------------------------------------------------------------*/
  62. /* 函数声明 ------------------------------------------------------------------*/
  63. void KEY_GPIO_Init(void);
  64. KEYState_TypeDef KEYx_StateSet(GPIO_TypeDef* KEYx_GPIO, uint16_t KEYx_GPIO_PIN, uint8_t KEYx_DOWN_LEVEL);
  65. KEYState_TypeDef KEYx_Choice(int KEYIndex);
  66. void KEY_LED(void);
  67. void KEY1_EXIT_Config(void);
  68. void KEY2_EXIT_Config(void);
  69. void KEY3_EXIT_Config(void);
  70. #endif // __BSP_KEY_H__

3.main.c

这边值得注意的while函数里面什么都不用加,较为简单,运行就完事儿了!

  1. /* 包含头文件 ----------------------------------------------------------------*/
  2. #include "stm32f10x.h"
  3. #include "bsp/led/bsp_led.h"
  4. #include "bsp/key/bsp_key.h"
  5. #include "bsp/delay/delay.h"
  6. /* 函数体 --------------------------------------------------------------------*/
  7. /**
  8. * 函数功能: 主函数.
  9. * 输入参数: 无
  10. * 返 回 值: 无
  11. * 说 明: 无
  12. */
  13. int main(void)
  14. {
  15. LED_GPIO_Init();
  16. KEY1_EXIT_Config();
  17. KEY2_EXIT_Config();
  18. KEY3_EXIT_Config();
  19. while (1)
  20. {
  21. //什么都不加
  22. }
  23. }

四、实验效果

外部中断-点灯

结束语

本文以STM32VET6为例讲解了用外部中断控制按键点灯的实现方法,并解决了几个可能会在实际中遇到的问题,并在代码中也给出相应注释。希望对大家有所帮助!如果还有什么问题,欢迎评论区留言,谢谢!

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/秋刀鱼在做梦/article/detail/973078
推荐阅读
相关标签
  

闽ICP备14008679号