IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> 史上最详细的STM32教程(2) 使用外部中断控制按键 -> 正文阅读

[嵌入式]史上最详细的STM32教程(2) 使用外部中断控制按键

目录

中断概述

M3内核中断源

外部中断EXTI概述

输入线(以EXTI0为例)

程序流程

1.初始化要连接到EXTI的GPIO

2.初始化EXTI用于产生的中断/事件

3.初始化NVIC,用于处理中断

4.编写中断服务函数

5.main函数

代码示例:外部中断控制按键


中断概述

中断:打断CPU正常程序运行,转去执行中断服务函数的内容,然后再回来执行原来的程序

NVIC:嵌套向量中断控制器,属于内核外设,管理怎与中断相关的功能

bit7

bit6

bit5

bit4

bit3

bit2

bit1

bit0

用于表达优先级

没用,恒定为0

typedef struct
{
  uint8_t NVIC_IRQChannel;        //中断源          

  uint8_t NVIC_IRQChannelPreemptionPriority; 	//抢占优先级 

  uint8_t NVIC_IRQChannelSubPriority;         //子优先级

  FunctionalState NVIC_IRQChannelCmd;       //使能或失能
} NVIC_InitTypeDef;
  1. NVIC_IRQChannel?????:对于RCT6来说,它的中断源如上图所示,在stm32f103.h中已经配置好寄存器,直接调用即可,下图中,RCT6主要用的是STM32F103X_HD的中断源

M3内核中断源

/******  Cortex-M3 Processor Exceptions Numbers ***************************************************/
  NonMaskableInt_IRQn         = -14,    /*!< 2 Non Maskable Interrupt                             */
  MemoryManagement_IRQn       = -12,    /*!< 4 Cortex-M3 Memory Management Interrupt              */
  BusFault_IRQn               = -11,    /*!< 5 Cortex-M3 Bus Fault Interrupt                      */
  UsageFault_IRQn             = -10,    /*!< 6 Cortex-M3 Usage Fault Interrupt                    */
  SVCall_IRQn                 = -5,     /*!< 11 Cortex-M3 SV Call Interrupt                       */
  DebugMonitor_IRQn           = -4,     /*!< 12 Cortex-M3 Debug Monitor Interrupt                 */
  PendSV_IRQn                 = -2,     /*!< 14 Cortex-M3 Pend SV Interrupt                       */
  SysTick_IRQn                = -1,     /*!< 15 Cortex-M3 System Tick Interrupt                   */


外设中断源
/******  STM32 specific Interrupt Numbers *********************************************************/
  WWDG_IRQn                   = 0,      /*!< Window WatchDog Interrupt                            */
  PVD_IRQn                    = 1,      /*!< PVD through EXTI Line detection Interrupt            */
  TAMPER_IRQn                 = 2,      /*!< Tamper Interrupt                                     */
  RTC_IRQn                    = 3,      /*!< RTC global Interrupt                                 */
  FLASH_IRQn                  = 4,      /*!< FLASH global Interrupt                               */
  RCC_IRQn                    = 5,      /*!< RCC global Interrupt                                 */
  EXTI0_IRQn                  = 6,      /*!< EXTI Line0 Interrupt                                 */
  EXTI1_IRQn                  = 7,      /*!< EXTI Line1 Interrupt                                 */
  EXTI2_IRQn                  = 8,      /*!< EXTI Line2 Interrupt                                 */
  EXTI3_IRQn                  = 9,      /*!< EXTI Line3 Interrupt                                 */
  EXTI4_IRQn                  = 10,     /*!< EXTI Line4 Interrupt                                 */
  DMA1_Channel1_IRQn          = 11,     /*!< DMA1 Channel 1 global Interrupt                      */
  DMA1_Channel2_IRQn          = 12,     /*!< DMA1 Channel 2 global Interrupt                      */
  DMA1_Channel3_IRQn          = 13,     /*!< DMA1 Channel 3 global Interrupt                      */
  DMA1_Channel4_IRQn          = 14,     /*!< DMA1 Channel 4 global Interrupt                      */
  DMA1_Channel5_IRQn          = 15,     /*!< DMA1 Channel 5 global Interrupt                      */
  DMA1_Channel6_IRQn          = 16,     /*!< DMA1 Channel 6 global Interrupt                      */
  DMA1_Channel7_IRQn          = 17,     /*!< DMA1 Channel 7 global Interrupt                      */


#ifdef STM32F10X_HD
  ADC1_2_IRQn                 = 18,     /*!< ADC1 and ADC2 global Interrupt                       */
  USB_HP_CAN1_TX_IRQn         = 19,     /*!< USB Device High Priority or CAN1 TX Interrupts       */
  USB_LP_CAN1_RX0_IRQn        = 20,     /*!< USB Device Low Priority or CAN1 RX0 Interrupts       */
  CAN1_RX1_IRQn               = 21,     /*!< CAN1 RX1 Interrupt                                   */
  CAN1_SCE_IRQn               = 22,     /*!< CAN1 SCE Interrupt                                   */
  EXTI9_5_IRQn                = 23,     /*!< External Line[9:5] Interrupts                        */
  TIM1_BRK_IRQn               = 24,     /*!< TIM1 Break Interrupt                                 */
  TIM1_UP_IRQn                = 25,     /*!< TIM1 Update Interrupt                                */
  TIM1_TRG_COM_IRQn           = 26,     /*!< TIM1 Trigger and Commutation Interrupt               */
  TIM1_CC_IRQn                = 27,     /*!< TIM1 Capture Compare Interrupt                       */
  TIM2_IRQn                   = 28,     /*!< TIM2 global Interrupt                                */
  TIM3_IRQn                   = 29,     /*!< TIM3 global Interrupt                                */
  TIM4_IRQn                   = 30,     /*!< TIM4 global Interrupt                                */
  I2C1_EV_IRQn                = 31,     /*!< I2C1 Event Interrupt                                 */
  I2C1_ER_IRQn                = 32,     /*!< I2C1 Error Interrupt                                 */
  I2C2_EV_IRQn                = 33,     /*!< I2C2 Event Interrupt                                 */
  I2C2_ER_IRQn                = 34,     /*!< I2C2 Error Interrupt                                 */
  SPI1_IRQn                   = 35,     /*!< SPI1 global Interrupt                                */
  SPI2_IRQn                   = 36,     /*!< SPI2 global Interrupt                                */
  USART1_IRQn                 = 37,     /*!< USART1 global Interrupt                              */
  USART2_IRQn                 = 38,     /*!< USART2 global Interrupt                              */
  USART3_IRQn                 = 39,     /*!< USART3 global Interrupt                              */
  EXTI15_10_IRQn              = 40,     /*!< External Line[15:10] Interrupts                      */
  RTCAlarm_IRQn               = 41,     /*!< RTC Alarm through EXTI Line Interrupt                */
  USBWakeUp_IRQn              = 42,     /*!< USB Device WakeUp from suspend through EXTI Line Interrupt */
  TIM8_BRK_IRQn               = 43,     /*!< TIM8 Break Interrupt                                 */
  TIM8_UP_IRQn                = 44,     /*!< TIM8 Update Interrupt                                */
  TIM8_TRG_COM_IRQn           = 45,     /*!< TIM8 Trigger and Commutation Interrupt               */
  TIM8_CC_IRQn                = 46,     /*!< TIM8 Capture Compare Interrupt                       */
  ADC3_IRQn                   = 47,     /*!< ADC3 global Interrupt                                */
  FSMC_IRQn                   = 48,     /*!< FSMC global Interrupt                                */
  SDIO_IRQn                   = 49,     /*!< SDIO global Interrupt                                */
  TIM5_IRQn                   = 50,     /*!< TIM5 global Interrupt                                */
  SPI3_IRQn                   = 51,     /*!< SPI3 global Interrupt                                */
  UART4_IRQn                  = 52,     /*!< UART4 global Interrupt                               */
  UART5_IRQn                  = 53,     /*!< UART5 global Interrupt                               */
  TIM6_IRQn                   = 54,     /*!< TIM6 global Interrupt                                */
  TIM7_IRQn                   = 55,     /*!< TIM7 global Interrupt                                */
  DMA2_Channel1_IRQn          = 56,     /*!< DMA2 Channel 1 global Interrupt                      */
  DMA2_Channel2_IRQn          = 57,     /*!< DMA2 Channel 2 global Interrupt                      */
  DMA2_Channel3_IRQn          = 58,     /*!< DMA2 Channel 3 global Interrupt                      */
  DMA2_Channel4_5_IRQn        = 59      /*!< DMA2 Channel 4 and Channel 5 global Interrupt        */
#endif /* STM32F10X_HD */  

外部中断EXTI概述

输入线(以EXTI0为例)

PA0~PG0????? EXTI0

.

.

.

PA15~PG15? EXTI15

EXTI 16——PVD输出

EXTI 17——RTC闹钟事件

EXTI 18——USB唤醒事件

EXTI 19——以太网唤醒事件(只适用于互联型产品) Cotex-3无该项功能

注意是AFIO寄存器控制着外部中断

程序流程

1.初始化要连接到EXTI的GPIO

2.初始化EXTI用于产生的中断/事件

EXTI_TypeDef一个外部中断的结构体

(1)初始化输入线,选择输入线的时候要操作AFIO寄存器(外部中断配置寄存器),所以要先打开它的时钟,它的时钟线恰好挂载到RCCAPB2Per上

(2)选择输入线

//选择输入线,第一个参数是GPIO_PortSourceGPIOxx=A~G,第二个参数是GPIO_PinSourcex(x=0~15)

? ? GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource0);

下面是关于这个函数的定义

/**
  * @brief  Selects the GPIO pin used as EXTI Line.
  * @param  GPIO_PortSource: selects the GPIO port to be used as source for EXTI lines.
  *   This parameter can be GPIO_PortSourceGPIOx where x can be (A..G).
  * @param  GPIO_PinSource: specifies the EXTI line to be configured.
  *   This parameter can be GPIO_PinSourcex where x can be (0..15).
  * @retval None
  */
void GPIO_EXTILineConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource)
{
  uint32_t tmp = 0x00;
  /* Check the parameters */
  assert_param(IS_GPIO_EXTI_PORT_SOURCE(GPIO_PortSource));
  assert_param(IS_GPIO_PIN_SOURCE(GPIO_PinSource));
  
  tmp = ((uint32_t)0x0F) << (0x04 * (GPIO_PinSource & (uint8_t)0x03));
  AFIO->EXTICR[GPIO_PinSource >> 0x02] &= ~tmp;
  AFIO->EXTICR[GPIO_PinSource >> 0x02] |= (((uint32_t)GPIO_PortSource) << (0x04 * (GPIO_PinSource & (uint8_t)0x03)));
}

/**

(2)然后,配置EXTI结构体的几个参数

  1. 配置EXTI_Line,可选参数如下
    EXTI_InitStructure.EXTI_Line=EXTI_Line0;
    
    #define EXTI_Line0       ((uint32_t)0x00001)  /*!< External interrupt line 0 */
    #define EXTI_Line1       ((uint32_t)0x00002)  /*!< External interrupt line 1 */
    #define EXTI_Line2       ((uint32_t)0x00004)  /*!< External interrupt line 2 */
    #define EXTI_Line3       ((uint32_t)0x00008)  /*!< External interrupt line 3 */
    #define EXTI_Line4       ((uint32_t)0x00010)  /*!< External interrupt line 4 */
    #define EXTI_Line5       ((uint32_t)0x00020)  /*!< External interrupt line 5 */
    #define EXTI_Line6       ((uint32_t)0x00040)  /*!< External interrupt line 6 */
    #define EXTI_Line7       ((uint32_t)0x00080)  /*!< External interrupt line 7 */
    #define EXTI_Line8       ((uint32_t)0x00100)  /*!< External interrupt line 8 */
    #define EXTI_Line9       ((uint32_t)0x00200)  /*!< External interrupt line 9 */
    #define EXTI_Line10      ((uint32_t)0x00400)  /*!< External interrupt line 10 */
    #define EXTI_Line11      ((uint32_t)0x00800)  /*!< External interrupt line 11 */
    #define EXTI_Line12      ((uint32_t)0x01000)  /*!< External interrupt line 12 */
    #define EXTI_Line13      ((uint32_t)0x02000)  /*!< External interrupt line 13 */
    #define EXTI_Line14      ((uint32_t)0x04000)  /*!< External interrupt line 14 */
    #define EXTI_Line15      ((uint32_t)0x08000)  /*!< External interrupt line 15 */
    #define EXTI_Line16      ((uint32_t)0x10000)  /*!< External interrupt line 16 Connected to the PVD Output */
    #define EXTI_Line17      ((uint32_t)0x20000)  /*!< External interrupt line 17 Connected to the RTC Alarm event */
    #define EXTI_Line18      ((uint32_t)0x40000)  /*!< External interrupt line 18 Connected to the USB Device/USB OTG FS
                                                       Wakeup from suspend event */                                    
    #define EXTI_Line19      ((uint32_t)0x80000)  /*!< External interrupt line 19 Connected to the Ethernet Wakeup event */
    

  2. 配置EXTI_Mode
    typedef enum
    {
      EXTI_Mode_Interrupt = 0x00,//中断模式
      EXTI_Mode_Event = 0x04
    }EXTIMode_TypeDef;
    

  3. 配置中断发生的触发方式
    typedef enum
    {
      EXTI_Trigger_Rising = 0x08,
      EXTI_Trigger_Falling = 0x0C,  
      EXTI_Trigger_Rising_Falling = 0x10
    }EXTITrigger_TypeDef;
    

  4. 配置使能ENABLE,DISABLE;

记得把配置好的结构体写到寄存器当中

综上,我们已经配置完黑圈1部分的寄存器;接下来我们要配置橙圈2部分的寄存器

?

3.初始化NVIC,用于处理中断

中断服务函数编程顺序

  1. 使能中断请求
  2. 配置中断优先级分组
  3. 配置NVIC寄存器,初始化NVIC_InitTypeDef
  4. 将配置好的结构体写到寄存器中
  5. 编写中断服务函数

(1)配置中断优先级分组

/**
  * @brief  Configures the priority grouping: pre-emption priority and subpriority.
  * @param  NVIC_PriorityGroup: specifies the priority grouping bits length. 
  *   This parameter can be one of the following values:
  *     @arg NVIC_PriorityGroup_0: 0 bits for pre-emption priority
  *                                4 bits for subpriority
  *     @arg NVIC_PriorityGroup_1: 1 bits for pre-emption priority
  *                                3 bits for subpriority
  *     @arg NVIC_PriorityGroup_2: 2 bits for pre-emption priority
  *                                2 bits for subpriority
  *     @arg NVIC_PriorityGroup_3: 3 bits for pre-emption priority
  *                                1 bits for subpriority
  *     @arg NVIC_PriorityGroup_4: 4 bits for pre-emption priority
  *                                0 bits for subpriority
  * @retval None
  */
void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup)
{
  /* Check the parameters */
  assert_param(IS_NVIC_PRIORITY_GROUP(NVIC_PriorityGroup));
  
  /* Set the PRIGROUP[10:8] bits according to NVIC_PriorityGroup value */
  SCB->AIRCR = AIRCR_VECTKEY_MASK | NVIC_PriorityGroup;
}
例如:NVIC_PriorityGroup_2: 2 bits for pre-emption priority
  *                                2 bits for subpriority

主优先级有2个bit(4个级数,0~3),子优先级也有2个bit;所以总共可以有16个中断先后顺序

(2)然后,配置NVIC结构体里面的参数

(3)配置中断源

中断源在上面M3内核中断源有讲到,注意RCT6对应的是HD

(4)把结构体写入中断寄存器中

//写入主优先级
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1;
    //写入从优先级
    NVIC_InitStructure.NVIC_IRQChannelSubPriority=1;
    //使能
    NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
    //把配置好的结构体写入寄存器内
    NVIC_Init(&NVIC_InitStructure);

4.编写中断服务函数

中断服务函数必须和启动文件中的中断服务函数名字是一样的,当然,你也可以改,但没必要

打开startup_stm32f10x hd_s文件,找到86行

定义好名字后,要调用ITStatus EXTI_GetITStatus(uint32_t EXTI_Line);来检测电平变化

然后,这个函数就会返回?(SET or RESET).

?产生中断,SET

未产生中断,RESET

这时我们只需用该函数判断

?if(EXTI_GetITStatus(KEY1_EXTI_Line)!=RESET)

对于这个函数

/**
  * @brief  Checks whether the specified EXTI line is asserted or not.
  * @param  EXTI_Line: specifies the EXTI line to check.
  *   This parameter can be:
  *     @arg EXTI_Linex: External interrupt line x where x(0..19)
  * @retval The new state of EXTI_Line (SET or RESET).
  */
ITStatus EXTI_GetITStatus(uint32_t EXTI_Line)
{
  ITStatus bitstatus = RESET;
  uint32_t enablestatus = 0;
  /* Check the parameters */
  assert_param(IS_GET_EXTI_LINE(EXTI_Line));
  
  enablestatus =  EXTI->IMR & EXTI_Line;
  if (((EXTI->PR & EXTI_Line) != (uint32_t)RESET) && (enablestatus != (uint32_t)RESET))
  {
    bitstatus = SET;
  }
  else
  {
    bitstatus = RESET;
  }
  return bitstatus;
}

输入的参数是挂载的中断线

EXTI_Linex: External interrupt line x where x(0..19)

最后,记得把SET/RESET中断标志位消除,该函数输入参数也是挂载的中断线

/**
  * @brief  Clears the EXTI's line pending bits.
  * @param  EXTI_Line: specifies the EXTI lines to clear.
  *   This parameter can be any combination of EXTI_Linex where x can be (0..19).
  * @retval None
  */
void EXTI_ClearITPendingBit(uint32_t EXTI_Line)
{
  /* Check the parameters */
  assert_param(IS_EXTI_LINE(EXTI_Line));
  
  EXTI->PR = EXTI_Line;
}

5.main函数

代码示例:外部中断控制按键

代码就是简单的按一次,LED取反一次。以后有空的话就写一篇关于按键单击,双击,三击,短按,长按的博客

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2021-11-30 15:46:40  更:2021-11-30 15:46:53 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 10:35:44-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码