STM32CubeMX之外部中断检测按键

STM32CubeMX之外部中断检测按键

1.中断简介

  中断,是指处理机处理程序运行中出现的紧急事件的整个过程。程序运行过程中,系统外部、系统内部或者现行程序本身若出现紧急事件,处理机立即中止现行程序的运行,自动转入相应的处理程序(中断服务程序),待处理完后,再返回原来的程序运行,这整个过程称为程序中断。当处理机接受中断时,只需暂停一个或几个周期而不执行处理程序的中断,称为简单中断,中断又可分为屏蔽中断非屏蔽中断两类。

  • STM32中断特性
     ● 68个可屏蔽中断通道(不包含16个Cortex™-M3的中断线);
     ● 16个可编程的优先等级(使用了4位中断优先级);
     ● 低延迟的异常和中断处理;
     ● 电源管理控制;
     ● 系统控制寄存器的实现;
      嵌套向量中断控制器(NVIC)和处理器核的接口紧密相连,可以实现低延迟的中断处理和高效地处理晚到的中断。
     Cortex‐M3 在内核水平上搭载了一个异常响应系统, 支持为数众多的系统异常和外部中断。其中,编号为 1- 15 的对应系统异常,大于等于 16 的则全是外部中断。除了个别异常的优先级被定死外, 其它异常的优先级都是可编程的(所有能打断正常执行流的事件都称为异常)。
      中断向量控制器, 简称 NVIC,是 Cortex‐M3 不可分离的一部分, 它与 CM3 内核的逻辑紧密耦合, 有一部分甚至水乳交融在一起。 NVIC 与 CM3 内核同声相应,同气相求,相辅相成,里应外合,共同完成对中断的响应。 NVIC 的寄存器以存储器映射的方式来访问, 除了包含控制寄存器和中断处理的控制逻辑之外, NVIC 还包含了 MPU的控制寄存器、 SysTick 定时器以及调试控制。
      每个外部中断都有一个对应的优先级寄存器,每个寄存器占用 8 位,但是允许最少只使用最高 3 位。 4 个相临的优先级寄存器拼成一个 32 位寄存器。如前所述,根据优先级组设置,优先级可以被分为高低两个位段,分别是抢占优先级和亚优先级。优先级寄存器都可以按字节访问,当然也可以按半字/字来访问。有意义的优先级寄存器数目由芯片厂商实现的中断数目决定。
  • STM32F10xxx产品(小容量、中容量和大容量)的向量表
    在这里插入图片描述在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

2.外部中断(EXTI)

  对于互联型产品,外部中断/事件控制器由20个产生事件/中断请求的边沿检测器组成,对于其它产品,则有19个能产生事件/中断请求的边沿检测器。每个输入线可以独立地配置输入类型(脉冲或挂起)和对应的触发事件(上升沿或下降沿或者双边沿都触发)。每个输入线都可以独立地被屏蔽。挂起寄存器保持着状态线的中断请求。

  • EXTI控制器的主要特性如下:
    ● 每个中断/事件都有独立的触发和屏蔽
    ● 每个中断线都有专用的状态位
    ● 支持多达20个软件的中断/事件请求
    ● 检测脉冲宽度低于APB2时钟宽度的外部信号。
  • 外部中断框图
    在这里插入图片描述
      要产生中断,必须先配置好并使能中断线。根据需要的边沿检测(上升沿、下降沿)设置2个触发寄存器,同时在中断屏蔽寄存器的相应位写’1’允许中断请求。当外部中断线上发生了期待的边沿时,将产生一个中断请求,对应的挂起位也随之被置’1’。在挂起寄存器的对应位写’1’,将清除该中断请求。

3.硬件设计

在这里插入图片描述
在这里插入图片描述
  根据硬件原理图特实物,Tout0 ~ Tout4对应的GPIO口为PA4 ~ PA7。采用外部中断方式实现触摸按键检测。其中中断线分别为:

  PA4 – EXIT4,PA4是使用外部中断线4;

  PA5 ~ PA7 – EXTI5 ~ 9,PA5 ~ PA7是使用外部中断线5~9;具体介绍可查看STM32中文参考手册。

TTP224是一款使用电容式感应原理设计的触摸IC,其稳定的感应方式可以应用到各种不同电​ ​​子类​​​产品,面板介质可以是完全绝源的材料,专为取代传统的机械结构开关或普通按键而设计.提供4个触摸输入端口及4个直接输出端口。

  • TTP224特点
  • 工作电压 2.4V~5.5V
  • 可以由外部Option选择是否启用内部稳压电路功能.
  • 工作电流@VDD=3V无负载时:
  • 低功耗模式下典型值2.5uA
  • 快速模式下典型值9uA
  • @VDD=3V时,在快速模式下KEY最快响应时间为100mS,低功耗模式下为200mS.
  • 有自动校准功能,当无按键被触摸时,系统重新校准周期约为4.0秒
    在这里插入图片描述

4.软件设计

在这里插入图片描述
  根据STM32中文参考手册外部中断章节介绍,边沿检测可选择上升沿、下降沿、双边沿(上升沿和下降沿)
  按键检测这里采用双边沿触发,即可完成按键按下与松开的状态检测
在这里插入图片描述
  外部中断使能:
在这里插入图片描述

 生成代码

  摸按键模式配置代码

void MX_GPIO_Init(void)
{

  GPIO_InitTypeDef GPIO_InitStruct = {0};

  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOD_CLK_ENABLE();
  __HAL_RCC_GPIOA_CLK_ENABLE();
  __HAL_RCC_GPIOB_CLK_ENABLE();

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOB, OLED_CS_Pin|OLED_DC_Pin|OLED_RST_Pin|OLED_SCK_Pin
                          |OLED_MOSI_Pin, GPIO_PIN_SET);

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(BEEP_GPIO_Port, BEEP_Pin, GPIO_PIN_RESET);

  /*Configure GPIO pins : PAPin PAPin PAPin PAPin */
  GPIO_InitStruct.Pin = TO0_Pin|TO1_Pin|TO2_Pin|TO3_Pin;//触摸按键引脚
  GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING_FALLING;//双边沿触发
  GPIO_InitStruct.Pull = GPIO_PULLDOWN;//上拉
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);//初始化

  /*Configure GPIO pins : PBPin PBPin PBPin PBPin
                           PBPin */
  GPIO_InitStruct.Pin = OLED_CS_Pin|OLED_DC_Pin|OLED_RST_Pin|OLED_SCK_Pin
                          |OLED_MOSI_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_PULLUP;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

  /*Configure GPIO pin : PtPin */
  GPIO_InitStruct.Pin = BEEP_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_PULLDOWN;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
  HAL_GPIO_Init(BEEP_GPIO_Port, &GPIO_InitStruct);

  /* EXTI interrupt init*/
  HAL_NVIC_SetPriority(EXTI4_IRQn, 0, 0);//外部中断4
  HAL_NVIC_EnableIRQ(EXTI4_IRQn);

  HAL_NVIC_SetPriority(EXTI9_5_IRQn, 0, 0);//外部中断5~9
  HAL_NVIC_EnableIRQ(EXTI9_5_IRQn);

}

在这里插入图片描述

  • 中断服务函数

  外部中断4中断服务函数示例代码,外部中断5~9服务函数代码与此相同。

void EXTI4_IRQHandler(void)
{
  /* USER CODE BEGIN EXTI4_IRQn 0 */
   Delay_Ms(10);//消抖
  if(HAL_GPIO_ReadPin(TO0_GPIO_Port,TO0_Pin))//判断按键1是否按下
  {
    ttp224_stat|=1<<0;
  }
  else//判断按键是否松开
  {
    ttp224_stat&=~(1<<0); 
  }
  /* USER CODE END EXTI4_IRQn 0 */
  HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_4);
  /* USER CODE BEGIN EXTI4_IRQn 1 */
  
  /* USER CODE END EXTI4_IRQn 1 */
}
  • 主函数:多个按键同时检测
int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_TIM4_Init();
  MX_USART1_UART_Init();
  MX_ADC1_Init();
  /* USER CODE BEGIN 2 */
  OLED_Init();
  OLED_Displey_Imag(48,0,32,32,(u8 *)android);
  Delay_Ms(1000);
  OLED_Clear();
  OLED_Display_folnt(32,0,16,0);
  OLED_Display_folnt(32+16,0,16,1);
  OLED_Display_folnt(32+16*2,0,16,2);
  OLED_Display_folnt(32+16*3,0,16,3);  
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)//轮询
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
    switch(ttp224_stat)
    {
      case 0:
        OLED_Display_str(0,2,8,16,"                ");
        break;
      case 1:
        OLED_Display_str(0,2,8,16,"      KEY1 ON     ");
        break;
      case 2:
        OLED_Display_str(0,2,8,16,"      KEY2 ON     ");
        break;
      case 3:
        OLED_Display_str(0,2,8,16,"   KEY1 2 ON    ");
        break;
      case 4:
        OLED_Display_str(0,2,8,16,"    KEY3 ON     ");
        break;
      case 5:
        OLED_Display_str(0,2,8,16,"   KEY1 3 ON    ");
        break;
      case 6:
        OLED_Display_str(0,2,8,16,"   KEY2 3 ON    ");
        break;
      case 7:
        OLED_Display_str(0,2,8,16,"    KEY1 2 3 ON   ");
        break;
      case 8:
        OLED_Display_str(0,2,8,16,"   KEY4 ON      ");
        break;
      case 9:
        OLED_Display_str(0,2,8,16,"   KEY1 4 ON    ");
        break;
      case 10:
        OLED_Display_str(0,2,8,16,"   KEY2 4 ON    ");
        break;
      case 11:
        OLED_Display_str(0,2,8,16,"   KEY1 2 4 ON  ");
        break;
      case 12:
        OLED_Display_str(0,2,8,16,"    KEY3 4 ON     ");
        break;
      case 13:
        OLED_Display_str(0,2,8,16,"    KEY1 3 4 ON ");
        break;
      case 14:
        OLED_Display_str(0,2,8,16,"  KEY2 3 4 ON  ");
        break;
      case 15:
        OLED_Display_str(0,2,8,16,"  KEY1 2 3 4 ON");
        break;    
    }
  }
  /* USER CODE END 3 */
}

在这里插入图片描述
  示例效果:
在这里插入图片描述
参考例程:https://download.csdn.net/download/weixin_44453694/19362281