STM32-HAL库开发快速入门

注:本文主要记录一下STM32CubeMX软件的使用流程,记录内容以STM32外设(中断、I2C、USART、SPI等配置)在STM32CubeMX中的设置为主,对驱动代码编写不做记录,所以阅读本文最好有标准库开发经验。除第2节外,使用的都是韦东山老师的瑞士军刀系列。

01 软件安装

1.keil

需要安装以下支持包(keil在线安装里没有对应芯片支持包)。

2.STM32CubeMX

安装库:

3.串口助手

02 HAL库点灯操作

2.1 硬件连接

该原理图来源于学益得在线课堂教学项目《RTOS项目实战:从PCB到FreeRTOS|手写MQTT》。

DAPLINK电路连接:

(1)程序下载:

单片机SCK------------DAPLINK的SCK

单片机SWK------------DAPLINK的SWD

(2)串口连接

单片机TX------------DAPLINK的RX

单片机RX------------DAPLINK的TX

单片机GND------------DAPLINK的GND

单片机3V3------------DAPLINK的3V3

单片机ReSet------------DAPLINK的RST

2.2 寄存器点灯

2.2.1 官网下载库文件

ST公司官网:

STSW-STM32065 - STM32F4 DSP and standard peripherals library - STMicroelectronics

2.2.2 创建工程

(1)新建工程

(2)复制启动文件到工程

记得将文件组添加到路径中:

此时编译运行会有错误,需要进行以下处理:

(3)配置RCC时钟

如果我们需要点亮PB10引脚上的LED,让PB10等于1即可:

与STM32F1系列不同,STM32所有的GPIO都挂载再AHB总线上,所以配置GPIO的RCC时钟时,配置的是AHB的时钟。

(4)配置PB10引脚为输出模式

(5)配置PB10引脚为推挽输出

(6)配置PB10引脚为输出高电平

(7)main.c

cpp 复制代码
#include <stm32f411xe.h>                  // 我们没有把所有启动文件都复制进来,所以用<>
//#include "stm32f4xx.h"                  // Device header

int main()
{
	//使能时钟
	RCC->AHB1ENR = 0X00000002;     //使能挂载在AHB上的PB10时钟
	//配置引脚模式
	GPIOB->MODER = 0x00100000;     //配置PB10为输出模式
	//配置输出模式
	GPIOB->OTYPER = 0x00000000;    //配置PB10引脚为推挽输出模式
	//配置输出的值
	GPIOB->ODR = 0x00000400;       //配置PB10引脚输出高电平
	while(1);	
}

void SystemInit()
{

}

注意:keil代码文件最后一行必须是空行,编译才不会有问题。 下载程序时注意以下几个问题:

(1)注意切换调试工具

(2)使用微库,就是简易版本的C库、使用C语言,开发的时候需要勾选"Use MicroLIB"

2.3 CubeMX创建工程

寄存器开发:优点:程序执行的效率高;缺点:开发效率低。

库开发:标准库 HAL库(需要借助CubeMX)

新建工程

RCC(时钟源)配置

晶振频率越高,功耗越高,因此提供了两个晶振供选择。

上图这里配置的是外部晶振,我们这个案例不需要用到,因为配不配置都行。

输入100后会自动匹配其它系数 ,由内部晶振分频输出。

2.4 HAL库点灯

使用CuberMX创建完工程后,可用keil打开相应keil工程,修改源码。

main.c

cpp 复制代码
/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2024 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */

/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */

/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
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();
  /* USER CODE BEGIN 2 */
  __HAL_RCC_GPIOB_CLK_ENABLE();       // 使能GPIOB的时钟.注意:时钟使能一定要在GPIO配置完成前
  GPIO_InitTypeDef GPIO_InitStruct;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; //设置gPIOB为推挽输出
  GPIO_InitStruct.Pin = GPIO_PIN_10;          //使用PB10引脚
  GPIO_InitStruct.Pull = GPIO_NOPULL;         //配置GPIO引脚不需要上拉
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; //配置GPIO输出速度为低速
  
  HAL_GPIO_Init(GPIOB,&GPIO_InitStruct);       //使用结构体配置GPIOB 	
  HAL_GPIO_WritePin(GPIOB,GPIO_PIN_10,GPIO_PIN_SET);  //将PB10置为高电平
  /* USER CODE END 2 */

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

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  /** Configure the main internal regulator output voltage
  */
  __HAL_RCC_PWR_CLK_ENABLE();
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);

  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
  RCC_OscInitStruct.PLL.PLLM = 8;
  RCC_OscInitStruct.PLL.PLLN = 100;
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
  RCC_OscInitStruct.PLL.PLLQ = 4;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }

  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_3) != HAL_OK)
  {
    Error_Handler();
  }
}

/**
  * @brief GPIO Initialization Function
  * @param None
  * @retval None
  */
static void MX_GPIO_Init(void)
{
/* USER CODE BEGIN MX_GPIO_Init_1 */
/* USER CODE END MX_GPIO_Init_1 */

  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOC_CLK_ENABLE();
  __HAL_RCC_GPIOH_CLK_ENABLE();
  __HAL_RCC_GPIOA_CLK_ENABLE();

/* USER CODE BEGIN MX_GPIO_Init_2 */
/* USER CODE END MX_GPIO_Init_2 */
}

/* USER CODE BEGIN 4 */

/* USER CODE END 4 */

/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */
  __disable_irq();
  while (1)
  {
  }
  /* USER CODE END Error_Handler_Debug */
}

#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

注意:

2.5 CubeMX配置GPIO

直接用CubeMX配置点亮LED。

这里CubeMx实现了将PB0、PB1、PB2、PB10全部置为高电平,推挽输出模式,点亮4颗LED灯。配置完后直接用keil打开下载程序即可运行

2.6 GPIO反转操作(流水灯实现)

(1)工程配置

(2)GPIO.c

cpp 复制代码
/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file    gpio.c
  * @brief   This file provides code for the configuration
  *          of all used GPIO pins.
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2024 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
/* USER CODE END Header */

/* Includes ------------------------------------------------------------------*/
#include "gpio.h"

/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

/*----------------------------------------------------------------------------*/
/* Configure GPIO                                                             */
/*----------------------------------------------------------------------------*/
/* USER CODE BEGIN 1 */

/* USER CODE END 1 */

/** Configure pins as
        * Analog
        * Input
        * Output
        * EVENT_OUT
        * EXTI
*/
void MX_GPIO_Init(void)
{

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

}

/* USER CODE BEGIN 2 */
/*LED的初始化函数*/
void My_Led_Init(void)
{
  GPIO_InitTypeDef GPIO_Init_Struct;
  GPIO_Init_Struct.Mode = GPIO_MODE_OUTPUT_PP;   //配置GPIO为推挽输出
  GPIO_Init_Struct.Pin = GPIO_PIN_10|GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2;       //选中GPIOB上的PB0 PB1 PB2 PB10
  GPIO_Init_Struct.Pull = GPIO_NOPULL;
  GPIO_Init_Struct.Speed = GPIO_SPEED_FREQ_LOW;
  __HAL_RCC_GPIOB_CLK_ENABLE();            //开启GPIOB的时钟
  //初始化 PB0 PB1 PB2 PB10
  HAL_GPIO_Init(GPIOB,&GPIO_Init_Struct);	
}
/*LED的翻转函数*/
void My_Led_Tooggle(void)
{
	uint8_t i;
	for(i=0;i<4;i++)
	{
		switch(i)
		{
			case 0:
				HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_10);    //翻转PB10引脚的电平
				HAL_Delay(500);                           //延时500ms
				HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_10);    //翻转PB10引脚的电平
				HAL_Delay(500);
				break;
			case 1:
				HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_2);     //翻转PB2引脚的电平
				HAL_Delay(500);                           //延时500ms
			  HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_2);     //翻转PB2引脚的电平
				HAL_Delay(500);                           //延时500ms
			  break;
			case 2:
				HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_1);     //翻转PB1引脚的电平
				HAL_Delay(500);                           //延时500ms
			  HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_1);     //翻转PB1引脚的电平
				HAL_Delay(500);                           //延时500ms
				break;
			case 3:
				HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_0);     //翻转PB0引脚的电平
				HAL_Delay(500);                           //延时500ms
				HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_0);     //翻转PB0引脚的电平
				HAL_Delay(500);                           //延时500ms
			  break;
		}	
	}
}
/* USER CODE END 2 */

(3)GPIO.h

cpp 复制代码
/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file    gpio.h
  * @brief   This file contains all the function prototypes for
  *          the gpio.c file
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2024 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
/* USER CODE END Header */
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __GPIO_H__
#define __GPIO_H__

#ifdef __cplusplus
extern "C" {
#endif

/* Includes ------------------------------------------------------------------*/
#include "main.h"

/* USER CODE BEGIN Includes */

/* USER CODE END Includes */

/* USER CODE BEGIN Private defines */

/* USER CODE END Private defines */

void MX_GPIO_Init(void);

/* USER CODE BEGIN Prototypes */
void My_Led_Init(void);
void My_Led_Tooggle(void);
/* USER CODE END Prototypes */

#ifdef __cplusplus
}
#endif
#endif /*__ GPIO_H__ */

(4)main.c

cpp 复制代码
/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2024 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "gpio.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */

/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */

/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
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();
  /* USER CODE BEGIN 2 */
  My_Led_Init();	
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */
	My_Led_Tooggle();
    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  /** Configure the main internal regulator output voltage
  */
  __HAL_RCC_PWR_CLK_ENABLE();
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);

  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
  RCC_OscInitStruct.PLL.PLLM = 8;
  RCC_OscInitStruct.PLL.PLLN = 100;
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
  RCC_OscInitStruct.PLL.PLLQ = 4;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }

  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_3) != HAL_OK)
  {
    Error_Handler();
  }
}

/* USER CODE BEGIN 4 */

/* USER CODE END 4 */

/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */
  __disable_irq();
  while (1)
  {
  }
  /* USER CODE END Error_Handler_Debug */
}

#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

2.7 GPIO输入(两个按键开关灯)

1个按键开灯,另一个关灯

(1)新建3.key工程

(2)GPIO.c

cpp 复制代码
/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file    gpio.c
  * @brief   This file provides code for the configuration
  *          of all used GPIO pins.
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2024 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
/* USER CODE END Header */

/* Includes ------------------------------------------------------------------*/
#include "gpio.h"

/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

/*----------------------------------------------------------------------------*/
/* Configure GPIO                                                             */
/*----------------------------------------------------------------------------*/
/* USER CODE BEGIN 1 */

/* USER CODE END 1 */

/** Configure pins as
        * Analog
        * Input
        * Output
        * EVENT_OUT
        * EXTI
*/
void MX_GPIO_Init(void)
{

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

}

/* USER CODE BEGIN 2 */
/* LED初始化函数 */
void My_Led_Init(void)
{
	GPIO_InitTypeDef GPIO_Init_Structure;
	GPIO_Init_Structure.Mode = GPIO_MODE_OUTPUT_PP;          //配置推挽输出
	GPIO_Init_Structure.Pin = GPIO_PIN_10;
	GPIO_Init_Structure.Pull = GPIO_NOPULL;    //无需上下拉
	GPIO_Init_Structure.Speed = GPIO_SPEED_FREQ_LOW;
	__HAL_RCC_GPIOB_CLK_ENABLE();         //开启GPIOB的时钟
	HAL_GPIO_Init(GPIOB,&GPIO_Init_Structure);
}

/* 按键初始化函数 */
void My_Key_Init(void)
{
	GPIO_InitTypeDef GPIO_Init_Structure;
	GPIO_Init_Structure.Mode = GPIO_MODE_INPUT;          //输入模式,检测按键状态
	GPIO_Init_Structure.Pin = GPIO_PIN_4 | GPIO_PIN_5;
	GPIO_Init_Structure.Pull = GPIO_NOPULL;    //无需上下拉
	GPIO_Init_Structure.Speed = GPIO_SPEED_FREQ_LOW;
//	__HAL_RCC_GPIOA_CLK_ENABLE();             //在CubeMX自动生成的MX_GPIO_Init已经开启GPIOA的时钟,无需再次开启
	HAL_GPIO_Init(GPIOA,&GPIO_Init_Structure);
}
/* 开灯函数 */
void My_Led_ON()
{
	HAL_GPIO_WritePin(GPIOB,GPIO_PIN_10,GPIO_PIN_SET);   //给PB10一个高电平,开灯
}
/* 关灯函数 */
void My_Led_OFF()
{
	HAL_GPIO_WritePin(GPIOB,GPIO_PIN_10,GPIO_PIN_RESET); //给PB10一个低电平,关灯
}
/* 按键扫描函数 */
uint8_t My_Key_Scan(void)
{
	GPIO_PinState state = HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_4);   //检测接在PA4上按键状态
	if(state == GPIO_PIN_RESET)       //如果按键脚低电平,按键按下
	{
		HAL_Delay(20);        //延时20ms,软件消抖
		if(state == GPIO_PIN_RESET)
			return 1;
	}
	state = HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_5);   //检测接在PA5上按键状态
	if(state == GPIO_PIN_RESET)       //如果按键脚低电平,按键按下
	{
		HAL_Delay(20);        //延时20ms,软件消抖
		if(state == GPIO_PIN_RESET)
			return 2;
	}
	return 0;              //没有按键按下时候返回0
	
}

/* USER CODE END 2 */

(3)GPIO.h

cpp 复制代码
/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file    gpio.h
  * @brief   This file contains all the function prototypes for
  *          the gpio.c file
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2024 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
/* USER CODE END Header */
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __GPIO_H__
#define __GPIO_H__

#ifdef __cplusplus
extern "C" {
#endif

/* Includes ------------------------------------------------------------------*/
#include "main.h"

/* USER CODE BEGIN Includes */

/* USER CODE END Includes */

/* USER CODE BEGIN Private defines */

/* USER CODE END Private defines */

void MX_GPIO_Init(void);

/* USER CODE BEGIN Prototypes */
/* LED初始化函数 */
void My_Led_Init(void);
/* 按键初始化函数 */
void My_Key_Init(void);
/* 开灯函数 */
void My_Led_ON();
/* 关灯函数 */
void My_Led_OFF();
/* 按键扫描函数 */
uint8_t My_Key_Scan(void);
/* USER CODE END Prototypes */

#ifdef __cplusplus
}
#endif
#endif /*__ GPIO_H__ */

(4)main.c

cpp 复制代码
/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2024 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "gpio.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */

/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */

/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
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();
  /* USER CODE BEGIN 2 */
	My_Led_Init();
	My_Key_Init();
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */
		switch(My_Key_Scan())    //获取键值
		{
			case 1:
			{
				My_Led_ON();   //开灯
				break;
			}
			case 2:
			{
				My_Led_OFF();  //关灯
				break;
			}
			case 0:
				break;
		}
    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  /** Configure the main internal regulator output voltage
  */
  __HAL_RCC_PWR_CLK_ENABLE();
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);

  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
  RCC_OscInitStruct.PLL.PLLM = 8;
  RCC_OscInitStruct.PLL.PLLN = 100;
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
  RCC_OscInitStruct.PLL.PLLQ = 4;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }

  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_3) != HAL_OK)
  {
    Error_Handler();
  }
}

/* USER CODE BEGIN 4 */

/* USER CODE END 4 */

/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */
  __disable_irq();
  while (1)
  {
  }
  /* USER CODE END Error_Handler_Debug */
}

#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

上面我们学习了HAL库开发的基本操作,下面我们就来学习HAL库开发的外设操作吧。

03 GPIO中断编程

这节我们主要记录一下STM32CubeMX中中断配置。

(1)配置相应引脚为中断模式

(2)配置中断引脚触发方式和工作模式

(3)使能中断向量控制器

(4)设置中断优先级分组

江协科技STM32学习笔记(第04章 EXTI外部中断)_江协科技笔记-CSDN博客

勾选与不勾选的区别就是:左边是勾选上的,外设GPIO初始化完成后才初始化NVIC,右边是未勾选的,在GPIO里面就初始化了NVIC。

配置完以上几步就可以生成代码了。

(5)编写中断函数

使用HAL库配置的所有中断最终都会调用这个弱函数,我们和中断相关的代码都放这个函数里就可以了。

执行过程为:

在这个回调函数里编写我们自己的中断控制程序。

04 使用OLED进行调试

OLED使用I2C进行通信,所以这节的目的是为了了解I2C引脚的配置。

这里STM32CubeMX里就配置好了。

将OLED的驱动程序添加进工程里就可以使用oled了。

使用就是很常规的调用驱动里相关函数就行,就不记录了。

05 按键抖动处理

处理按键抖动的时候我们可能会使用延时函数,隔一段时间再判断一下电平,但是中断函数的要求是快进快出,在中断函数里使用延时函数,显示有点违背了这条准则,本节就是记录如何解决这个问题。 使用定时器来解决这个问题,定时器是如以下3个图这样来调用的。

这个定时器每1ms产生一次中断, 增加一个计数值。

使用以下函数获得计数值。

先定义相关的变量。

cpp 复制代码
struct soft_timer{
	uint32_t timeout;           //超时时间
	void *args;                 //给成员func用的参数
	void (*func)(void *);       //超时函数
};
/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */

/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */
int g_key_cnt = 0;
void key_timerout_func(void *args);

struct soft_timer key_timer = {~0,NULL,key_timerout_func};     //按键超时时间结构体定义

只要触发中断,将超时时间设置为当前时间+10。

cpp 复制代码
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
	if(GPIO_Pin == GPIO_PIN_14)
	{	
		mod_timer(&key_timer,10);                     //中断函数里修改超时时间为当前时间+10
	}
}
cpp 复制代码
void mod_timer(struct soft_timer *pTimer,uint32_t timeout)
{
	pTimer->timeout = HAL_GetTick()+timeout;         //超时时间等于当前计数值加上10,就是每次触发中断都等待10ms再检测        
}

SysTick_Handler()会每隔1ms计数一次,并且检查定时时间有没有到。

cpp 复制代码
void SysTick_Handler(void)
{
  /* USER CODE BEGIN SysTick_IRQn 0 */

  /* USER CODE END SysTick_IRQn 0 */
  HAL_IncTick();                            //没过1ms都会产生一次中断
  /* USER CODE BEGIN SysTick_IRQn 1 */
	extern void check_timer(void);
	check_timer();                            //调用check_timer检查按键定时器的时间有没有到了
  /* USER CODE END SysTick_IRQn 1 */
}
cpp 复制代码
void check_timer(void)
{
	if(key_timer.timeout<=HAL_GetTick())            
	/*如果按键定时器的时间是否到了,这里key_timer.timeout的最大值是最后一次按键抖动触发的中断时间+10,
	key_timer.timeout<=HAL_GetTick()就移位着我的按键已经达到稳定状态了
	*/
	{
		key_timer.func(key_timer.args);         //按键达到稳定状态后把案件定时器状态归位
	}
}
cpp 复制代码
void key_timerout_func(void *args)
{
	g_key_cnt++;                                               // 统计按键按下的次数
	key_timer.timeout= ~0;	                                   //每次计数完都给按键定时时间复位
}

完整代码:

main.c:

cpp 复制代码
/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2024 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "i2c.h"
#include "gpio.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "driver_oled.h"
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */  
struct soft_timer{
	uint32_t timeout;           //超时时间
	void *args;                 //给成员func用的参数
	void (*func)(void *);       //超时函数
};
/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */

/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */
int g_key_cnt = 0;
void key_timerout_func(void *args);

struct soft_timer key_timer = {~0,NULL,key_timerout_func};     //按键超时时间结构体定义

void key_timerout_func(void *args)
{
	g_key_cnt++;                                               // 统计按键按下的次数
	key_timer.timeout= ~0;	                                   //每次计数完都给按键定时时间复位
}


void mod_timer(struct soft_timer *pTimer,uint32_t timeout)
{
	pTimer->timeout = HAL_GetTick()+timeout;         //超时时间等于当前计数值加上10,就是每次触发中断都等待10ms再检测        
}

void check_timer(void)
{
	if(key_timer.timeout<=HAL_GetTick())            
	/*如果按键定时器的时间是否到了,这里key_timer.timeout的最大值是最后一次按键抖动触发的中断时间+10,
	key_timer.timeout<=HAL_GetTick()就移位着我的按键已经达到稳定状态了
	*/
	{
		key_timer.func(key_timer.args);         //按键达到稳定状态后把案件定时器状态归位
	}
}

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
	if(GPIO_Pin == GPIO_PIN_14)
	{	
		mod_timer(&key_timer,10);                     //中断函数里修改超时时间为当前时间+10
	}
}
/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
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_I2C1_Init();
  /* USER CODE BEGIN 2 */
	OLED_Init();
  OLED_Clear();
  OLED_PrintString(0, 4, "Key ISR cnt = ");
  /* USER CODE END 2 */
	
  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
//		HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13,GPIO_PIN_SET);          //PC13口置高电平,点亮LED
//		HAL_Delay(500);                                             //延时500ms
//		HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13,GPIO_PIN_RESET);          //PC13口置高电平,点亮LED
//		HAL_Delay(500);
		OLED_PrintSignedVal(14, 4, g_key_cnt);
    /* USER CODE END WHILE */
	
    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }

  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
  {
    Error_Handler();
  }
}

/* USER CODE BEGIN 4 */

/* USER CODE END 4 */

/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */
  __disable_irq();
  while (1)
  {
  }
  /* USER CODE END Error_Handler_Debug */
}

#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

stm32f1xx_it.c :

cpp 复制代码
/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file    stm32f1xx_it.c
  * @brief   Interrupt Service Routines.
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2024 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
/* USER CODE END Header */

/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "stm32f1xx_it.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN TD */

/* USER CODE END TD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */

/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

/* External variables --------------------------------------------------------*/

/* USER CODE BEGIN EV */

/* USER CODE END EV */

/******************************************************************************/
/*           Cortex-M3 Processor Interruption and Exception Handlers          */
/******************************************************************************/
/**
  * @brief This function handles Non maskable interrupt.
  */
void NMI_Handler(void)
{
  /* USER CODE BEGIN NonMaskableInt_IRQn 0 */

  /* USER CODE END NonMaskableInt_IRQn 0 */
  /* USER CODE BEGIN NonMaskableInt_IRQn 1 */
   while (1)
  {
  }
  /* USER CODE END NonMaskableInt_IRQn 1 */
}

/**
  * @brief This function handles Hard fault interrupt.
  */
void HardFault_Handler(void)
{
  /* USER CODE BEGIN HardFault_IRQn 0 */

  /* USER CODE END HardFault_IRQn 0 */
  while (1)
  {
    /* USER CODE BEGIN W1_HardFault_IRQn 0 */
    /* USER CODE END W1_HardFault_IRQn 0 */
  }
}

/**
  * @brief This function handles Memory management fault.
  */
void MemManage_Handler(void)
{
  /* USER CODE BEGIN MemoryManagement_IRQn 0 */

  /* USER CODE END MemoryManagement_IRQn 0 */
  while (1)
  {
    /* USER CODE BEGIN W1_MemoryManagement_IRQn 0 */
    /* USER CODE END W1_MemoryManagement_IRQn 0 */
  }
}

/**
  * @brief This function handles Prefetch fault, memory access fault.
  */
void BusFault_Handler(void)
{
  /* USER CODE BEGIN BusFault_IRQn 0 */

  /* USER CODE END BusFault_IRQn 0 */
  while (1)
  {
    /* USER CODE BEGIN W1_BusFault_IRQn 0 */
    /* USER CODE END W1_BusFault_IRQn 0 */
  }
}

/**
  * @brief This function handles Undefined instruction or illegal state.
  */
void UsageFault_Handler(void)
{
  /* USER CODE BEGIN UsageFault_IRQn 0 */

  /* USER CODE END UsageFault_IRQn 0 */
  while (1)
  {
    /* USER CODE BEGIN W1_UsageFault_IRQn 0 */
    /* USER CODE END W1_UsageFault_IRQn 0 */
  }
}

/**
  * @brief This function handles System service call via SWI instruction.
  */
void SVC_Handler(void)
{
  /* USER CODE BEGIN SVCall_IRQn 0 */

  /* USER CODE END SVCall_IRQn 0 */
  /* USER CODE BEGIN SVCall_IRQn 1 */

  /* USER CODE END SVCall_IRQn 1 */
}

/**
  * @brief This function handles Debug monitor.
  */
void DebugMon_Handler(void)
{
  /* USER CODE BEGIN DebugMonitor_IRQn 0 */

  /* USER CODE END DebugMonitor_IRQn 0 */
  /* USER CODE BEGIN DebugMonitor_IRQn 1 */

  /* USER CODE END DebugMonitor_IRQn 1 */
}

/**
  * @brief This function handles Pendable request for system service.
  */
void PendSV_Handler(void)
{
  /* USER CODE BEGIN PendSV_IRQn 0 */

  /* USER CODE END PendSV_IRQn 0 */
  /* USER CODE BEGIN PendSV_IRQn 1 */

  /* USER CODE END PendSV_IRQn 1 */
}

/**
  * @brief This function handles System tick timer.
  */
void SysTick_Handler(void)
{
  /* USER CODE BEGIN SysTick_IRQn 0 */

  /* USER CODE END SysTick_IRQn 0 */
  HAL_IncTick();                            //没过1ms都会产生一次中断
  /* USER CODE BEGIN SysTick_IRQn 1 */
	extern void check_timer(void);
	check_timer();                            //调用check_timer检查按键定时器的时间有没有到了
  /* USER CODE END SysTick_IRQn 1 */
}

/******************************************************************************/
/* STM32F1xx Peripheral Interrupt Handlers                                    */
/* Add here the Interrupt Handlers for the used peripherals.                  */
/* For the available peripheral interrupt handler names,                      */
/* please refer to the startup file (startup_stm32f1xx.s).                    */
/******************************************************************************/

/**
  * @brief This function handles EXTI line[15:10] interrupts.
  */
void EXTI15_10_IRQHandler(void)
{
  /* USER CODE BEGIN EXTI15_10_IRQn 0 */

  /* USER CODE END EXTI15_10_IRQn 0 */
  HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_14);
  /* USER CODE BEGIN EXTI15_10_IRQn 1 */

  /* USER CODE END EXTI15_10_IRQn 1 */
}

/* USER CODE BEGIN 1 */

/* USER CODE END 1 */
相关推荐
不灭锦鲤23 分钟前
网络安全学习(面试)
学习·安全·web安全
世人万千丶1 小时前
Flutter 框架跨平台鸿蒙开发 - 鸿蒙版本五子棋游戏应用
学习·flutter·游戏·华为·harmonyos·鸿蒙
Aktx20FNz2 小时前
一文学习 Spring AOP 源码全过程
java·学习·spring
Jay Kay2 小时前
生成式推荐模型学习记录part1
学习
jghhh012 小时前
带红外抄板和LCD显示的单相电能表设计
stm32·单片机·嵌入式硬件
正经教主4 小时前
【docker基础】0、系统学习docker之总计划
学习·docker·容器
czhaii4 小时前
STM32 F103 Altium一键下载PCB图
stm32·单片机·嵌入式硬件
雾削木4 小时前
基于STM32F411RET6 + 双路MB85RS2MT的铁电U盘
stm32·单片机·嵌入式硬件
不知名的老吴4 小时前
计算机基础第一阶段:核心基础学习
学习
skywalk81635 小时前
请学习kotti的前端(kotti其实是没有分离的前端的)实现,做到形似kotti那样的前端页面。
前端·学习