当前位置: 首页 > news >正文

HAL STM32通过multi_button库处理按键事件

HAL STM32通过multi_button库处理按键事件

  • 📍作者:0x1abin的multi_button库:https://github.com/0x1abin/MultiButton

📘MultiButton简介

MultiButton 是一个小巧简单易用的事件驱动型按键驱动模块,可无限量扩展按键,按键事件的回调异步处理方式可以简化你的程序结构,去除冗余的按键处理硬编码,让你的按键业务逻辑更清晰。

  • 🔖 该库驱动代码纯C语言实现,可以移植到任意需要使用的地方。

🔑使用方法

  1. 先申请一个按键结构
struct Button button1;
  1. 初始化按键对象,绑定按键的GPIO电平读取接口read_button_pin() ,后一个参数设置有效触发电平。
button_init(&button1, read_button_pin, 0, 0);//绑定按键,读取按键引脚状态,有效触发电平、按键ID
  1. 注册按键事件
button_attach(&button1, SINGLE_CLICK, Callback_SINGLE_CLICK_Handler);
button_attach(&button1, DOUBLE_CLICK, Callback_DOUBLE_Click_Handler);


4. 启动按键

button_start(&button1);
  1. 设置一个5ms间隔的定时器循环调用后台处理函数
while(1) {...if(timer_ticks == 5) {timer_ticks = 0;button_ticks();}
}

🛠按键引脚配置

  • 🌿通过STM32CubeMX,将按键引脚配置成上拉,那么有效触发电平就需要设置为0.
    在这里插入图片描述

📗通过按键事件查询,获取按键状态

  • 🌿在滴答定时器中断函数(SysTick_Handler)中添加button_tick();
/* 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 "usart.h"
#include "usb_device.h"
#include "gpio.h"/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "stdio.h"
#include <stdarg.h>
#include "usbd_cdc_if.h"
#include "multi_button.h"/* 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 */
struct Button btn1;
/* 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 */
void usb_printf(const char *fmt, ...)
{char buf[128];//自定义缓冲区大小va_list args;va_start(args, fmt);vsnprintf(buf, sizeof(buf), fmt, args);va_end(args);CDC_Transmit_FS((uint8_t *)buf, strlen(buf));
}void button_tick(void)
{static uint8_t tickstart = 0;tickstart++;if(tickstart < 5)return;tickstart = 0;button_ticks();
}
//按键状态读取接口  按键输入模式 ReadInputDataBit
uint8_t Read_Button_GPIO(uint8_t button_id)
{// you can share the GPIO read function with multiple Buttonsswitch(button_id) {case 1:return HAL_GPIO_ReadPin(KEY1_GPIO_Port, KEY1_Pin);case 2:return HAL_GPIO_ReadPin(KEY2_GPIO_Port, KEY2_Pin);default:return 0;}
}/* USER CODE END 0 *//*** @brief  The application entry point.* @retval int*/
int main(void)
{/* USER CODE BEGIN 1 */uint32_t TimerUART;static PressEvent btn1_event_val;/* 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_USART1_UART_Init();MX_USB_DEVICE_Init();/* USER CODE BEGIN 2 */uint32_t Main_Fosc = HAL_RCC_GetSysClockFreq();printf("Main_Fosc:%dHz \r\n", Main_Fosc);TimerUART = HAL_GetTick();usb_printf("STM32F427 SysClockFreq:%d \r\n", Main_Fosc);button_init(&btn1, Read_Button_GPIO, 0, 1);button_start(&btn1);/* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while(1) {/* USER CODE END WHILE *//* USER CODE BEGIN 3 */if((HAL_GetTick() - TimerUART) > 1000) {HAL_GPIO_TogglePin(LED1_GPIO_Port, LED1_Pin | LED2_Pin | LED3_Pin); //翻转电平,LED翻转printf("STM32F427 SysClockFreq:%d \r\n", Main_Fosc);usb_printf("STM32F427 SysClockFreq:%d \r\n", Main_Fosc);TimerUART = HAL_GetTick();}if(btn1_event_val != get_button_event(&btn1)) {btn1_event_val = get_button_event(&btn1);if(btn1_event_val == PRESS_DOWN) {// printf("STM32F427 KEY1 PRESS_DOWN \r\n");usb_printf("STM32F427 KEY1 PRESS_DOWN \r\n");} else if(btn1_event_val == PRESS_UP) {// printf("STM32F427 KEY1 PRESS_UP \r\n");usb_printf("STM32F427 KEY1 PRESS_UP \r\n");} else if(btn1_event_val == LONG_PRESS_HOLD) {// printf("STM32F427 LONG_PRESS_HOLD\r\n"/);usb_printf("STM32F427 LONG_PRESS_HOLD\r\n");}}}/* 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_SCALE3);/** 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.PLL.PLLState = RCC_PLL_ON;RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;RCC_OscInitStruct.PLL.PLLM = 16;RCC_OscInitStruct.PLL.PLLN = 384;RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV4;RCC_OscInitStruct.PLL.PLLQ = 8;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_DIV4;RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;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 */

📓通过注册按键事件,获取按键状态

/* 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 "usart.h"
#include "usb_device.h"
#include "gpio.h"/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "stdio.h"
#include <stdarg.h>
#include "usbd_cdc_if.h"
#include "multi_button.h"/* 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 */
struct Button btn1;
/* USER CODE END PV *//* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */
void BTN1_PRESS_DOWN_Handler(void* btn);
void BTN1_PRESS_UP_Handler(void* btn);
void BTN1_SINGLE_Click_Handler(void* btn);
void BTN1_DOUBLE_Click_Handler(void* btn);
void BTN1_LONG_RRESS_START_Handler(void* btn);
void BTN1_LONG_PRESS_HOLD_Handler(void* btn);
/* USER CODE END PFP *//* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
void usb_printf(const char *fmt, ...)
{char buf[128];//自定义缓冲区大小va_list args;va_start(args, fmt);vsnprintf(buf, sizeof(buf), fmt, args);va_end(args);CDC_Transmit_FS((uint8_t *)buf, strlen(buf));
}void button_tick(void)
{static uint8_t tickstart = 0;tickstart++;if(tickstart < 5)return;tickstart = 0;button_ticks();
}
//按键状态读取接口  按键输入模式 ReadInputDataBit
uint8_t Read_Button_GPIO(uint8_t button_id)
{// you can share the GPIO read function with multiple Buttonsswitch(button_id) {case 1:return HAL_GPIO_ReadPin(KEY1_GPIO_Port, KEY1_Pin);case 2:return HAL_GPIO_ReadPin(KEY2_GPIO_Port, KEY2_Pin);default:return 0;}
}/* USER CODE END 0 *//*** @brief  The application entry point.* @retval int*/
int main(void)
{/* USER CODE BEGIN 1 */uint32_t TimerUART;// static PressEvent btn1_event_val;/* 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_USART1_UART_Init();MX_USB_DEVICE_Init();/* USER CODE BEGIN 2 */uint32_t Main_Fosc = HAL_RCC_GetSysClockFreq();printf("Main_Fosc:%dHz \r\n", Main_Fosc);TimerUART = HAL_GetTick();usb_printf("STM32F427 SysClockFreq:%d \r\n", Main_Fosc);button_init(&btn1, Read_Button_GPIO, 0, 1);// button_attach(&btn1, PRESS_DOWN, BTN1_PRESS_DOWN_Handler); //按下// button_attach(&btn1, PRESS_UP, BTN1_PRESS_UP_Handler);  //按起//	button_attach(&btn1, PRESS_REPEAT,     BTN1_PRESS_REPEAT_Handler);button_attach(&btn1, SINGLE_CLICK, BTN1_SINGLE_Click_Handler); //单击button_attach(&btn1, DOUBLE_CLICK, BTN1_DOUBLE_Click_Handler);  //双击button_attach(&btn1, LONG_PRESS_START, BTN1_LONG_RRESS_START_Handler); //长按开始// button_attach(&btn1, LONG_PRESS_HOLD, BTN1_LONG_PRESS_HOLD_Handler);//一直长按状态button_start(&btn1);/* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while(1) {/* USER CODE END WHILE *//* USER CODE BEGIN 3 */if((HAL_GetTick() - TimerUART) > 1000) {HAL_GPIO_TogglePin(LED1_GPIO_Port, LED1_Pin | LED2_Pin | LED3_Pin); //翻转电平,LED翻转printf("STM32F427 SysClockFreq:%d \r\n", Main_Fosc);usb_printf("STM32F427 SysClockFreq:%d \r\n", Main_Fosc);TimerUART = HAL_GetTick();}}/* 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_SCALE3);/** 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.PLL.PLLState = RCC_PLL_ON;RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;RCC_OscInitStruct.PLL.PLLM = 16;RCC_OscInitStruct.PLL.PLLN = 384;RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV4;RCC_OscInitStruct.PLL.PLLQ = 8;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_DIV4;RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;if(HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_3) != HAL_OK) {Error_Handler();}
}/* USER CODE BEGIN 4 */
void BTN1_PRESS_DOWN_Handler(void* btn)
{// printf("STM32F427 KEY1 PRESS_DOWN \r\n");usb_printf("STM32F427 KEY1 PRESS_DOWN \r\n");
}void BTN1_PRESS_UP_Handler(void* btn)
{// printf("STM32F427 KEY1 PRESS_UP \r\n");usb_printf("STM32F427 KEY1 PRESS_UP \r\n");
}
void BTN1_SINGLE_Click_Handler(void* btn)
{// printf("STM32F427 KEY1 SINGLE_Click \r\n");usb_printf("STM32F427 KEY1 SINGLE_Click \r\n");
}
void BTN1_DOUBLE_Click_Handler(void* btn)
{// printf("STM32F427 KEY1 DOUBLE_Click \r\n");usb_printf("STM32F427 KEY1 DOUBLE_Click \r\n");
}
void BTN1_LONG_RRESS_START_Handler(void* btn)
{// printf("STM32F427 KEY1 LONG_RRESS_START \r\n");usb_printf("STM32F427 KEY1 LONG_RRESS_START \r\n");
}
void BTN1_LONG_PRESS_HOLD_Handler(void* btn)
{// printf("STM32F427 KEY1 LONG_PRESS_HOLD \r\n");usb_printf("STM32F427 KEY1 LONG_PRESS_HOLD \r\n");
}
/* 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 */

📝通过注册按键事件,统一查询获取按键状态

/* 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 "usart.h"
#include "usb_device.h"
#include "gpio.h"/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "stdio.h"
#include <stdarg.h>
#include "usbd_cdc_if.h"
#include "multi_button.h"/* 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 */
struct Button btn1;
/* USER CODE END PV *//* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */
//void BTN1_PRESS_DOWN_Handler(void* btn);
//void BTN1_PRESS_UP_Handler(void* btn);
//void BTN1_SINGLE_Click_Handler(void* btn);
//void BTN1_DOUBLE_Click_Handler(void* btn);
//void BTN1_LONG_RRESS_START_Handler(void* btn);
//void BTN1_LONG_PRESS_HOLD_Handler(void* btn);
void button_callback(void *btn);//
/* USER CODE END PFP *//* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
void usb_printf(const char *fmt, ...)
{char buf[128];//自定义缓冲区大小va_list args;va_start(args, fmt);vsnprintf(buf, sizeof(buf), fmt, args);va_end(args);CDC_Transmit_FS((uint8_t *)buf, strlen(buf));
}void button_tick(void)
{static uint8_t tickstart = 0;tickstart++;if(tickstart < 5)return;tickstart = 0;button_ticks();
}
//按键状态读取接口  按键输入模式 ReadInputDataBit
uint8_t Read_Button_GPIO(uint8_t button_id)
{// you can share the GPIO read function with multiple Buttonsswitch(button_id) {case 1:return HAL_GPIO_ReadPin(KEY1_GPIO_Port, KEY1_Pin);case 2:return HAL_GPIO_ReadPin(KEY2_GPIO_Port, KEY2_Pin);default:return 0;}
}/* USER CODE END 0 *//*** @brief  The application entry point.* @retval int*/
int main(void)
{/* USER CODE BEGIN 1 */
//    uint32_t TimerUART;// static PressEvent btn1_event_val;/* 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_USART1_UART_Init();MX_USB_DEVICE_Init();/* USER CODE BEGIN 2 */uint32_t Main_Fosc = HAL_RCC_GetSysClockFreq();printf("Main_Fosc:%dHz \r\n", Main_Fosc);
//    TimerUART = HAL_GetTick();usb_printf("STM32F427 SysClockFreq:%d \r\n", Main_Fosc);button_init(&btn1, Read_Button_GPIO, 0, 1);// button_attach(&btn1, PRESS_DOWN, button_callback); //按下// button_attach(&btn1, PRESS_UP, button_callback);  //按起//	button_attach(&btn1, PRESS_REPEAT,button_callback);button_attach(&btn1, SINGLE_CLICK, button_callback); //单击button_attach(&btn1, DOUBLE_CLICK, button_callback);  //双击button_attach(&btn1, LONG_PRESS_START, button_callback); //长按开始// button_attach(&btn1, LONG_PRESS_HOLD, button_callback);//一直长按状态button_start(&btn1);/* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while(1) {/* USER CODE END WHILE *//* USER CODE BEGIN 3 */
//        if((HAL_GetTick() - TimerUART) > 1000) {
//            HAL_GPIO_TogglePin(LED1_GPIO_Port, LED1_Pin | LED2_Pin | LED3_Pin); //翻转电平,LED翻转
//            printf("STM32F427 SysClockFreq:%d \r\n", Main_Fosc);
//            usb_printf("STM32F427 SysClockFreq:%d \r\n", Main_Fosc);
//            TimerUART = HAL_GetTick();
//        }/*if(btn1_event_val != get_button_event(&btn1)) {btn1_event_val = get_button_event(&btn1);if(btn1_event_val == PRESS_DOWN) {// printf("STM32F427 KEY1 PRESS_DOWN \r\n");usb_printf("STM32F427 KEY1 PRESS_DOWN \r\n");} else if(btn1_event_val == PRESS_UP) {// printf("STM32F427 KEY1 PRESS_UP \r\n");usb_printf("STM32F427 KEY1 PRESS_UP \r\n");} else if(btn1_event_val == LONG_PRESS_HOLD) {// printf("STM32F427 LONG_PRESS_HOLD\r\n"/);usb_printf("STM32F427 LONG_PRESS_HOLD\r\n");}}*/}/* 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_SCALE3);/** 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.PLL.PLLState = RCC_PLL_ON;RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;RCC_OscInitStruct.PLL.PLLM = 16;RCC_OscInitStruct.PLL.PLLN = 384;RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV4;RCC_OscInitStruct.PLL.PLLQ = 8;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_DIV4;RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;if(HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_3) != HAL_OK) {Error_Handler();}
}/* USER CODE BEGIN 4 */
void BTN1_PRESS_DOWN_Handler(void* btn)
{// printf("STM32F427 KEY1 PRESS_DOWN \r\n");usb_printf("STM32F427 KEY1 PRESS_DOWN \r\n");
}void BTN1_PRESS_UP_Handler(void* btn)
{// printf("STM32F427 KEY1 PRESS_UP \r\n");usb_printf("STM32F427 KEY1 PRESS_UP \r\n");
}
void BTN1_SINGLE_Click_Handler(void* btn)
{// printf("STM32F427 KEY1 SINGLE_Click \r\n");usb_printf("STM32F427 KEY1 SINGLE_Click \r\n");
}
void BTN1_DOUBLE_Click_Handler(void* btn)
{// printf("STM32F427 KEY1 DOUBLE_Click \r\n");usb_printf("STM32F427 KEY1 DOUBLE_Click \r\n");
}
void BTN1_LONG_RRESS_START_Handler(void* btn)
{// printf("STM32F427 KEY1 LONG_RRESS_START \r\n");usb_printf("STM32F427 KEY1 LONG_RRESS_START \r\n");
}
void BTN1_LONG_PRESS_HOLD_Handler(void* btn)
{// printf("STM32F427 KEY1 LONG_PRESS_HOLD \r\n");usb_printf("STM32F427 KEY1 LONG_PRESS_HOLD \r\n");
}void button_callback(void *btn)
{
static PressEvent btn1_event_val;
//    uint32_t btn_event_val;    
//    btn_event_val = get_button_event((struct Button *)btn);
//	btn_event_val = get_button_event(&btn1);
if(btn1_event_val != get_button_event(&btn1)) {btn1_event_val = get_button_event(&btn1);switch(btn1_event_val){case PRESS_DOWN:printf("---> KEY1 press down! <---\r\n"); usb_printf("---> KEY1 press down! <---\r\n"); break; case PRESS_UP: printf("***> KEY1 press up! <***\r\n");usb_printf("---> KEY1 press up! <---\r\n");break; case PRESS_REPEAT: printf("---> KEY1 press repeat! <---\r\n");break; case SINGLE_CLICK: printf("---> KEY1 single click! <---\r\n");usb_printf("---> KEY1 single click! <---\r\n");break; case DOUBLE_CLICK: printf("***> KEY1 double click! <***\r\n");usb_printf("---> KEY1 double click! <---\r\n");break; case LONG_PRESS_START: printf("---> KEY1 long press start! <---\r\n");usb_printf("---> KEY1 long press start! <---\r\n");break; case LONG_PRESS_HOLD: printf("***> KEY1 long press hold! <***\r\n");usb_printf("---> KEY1 press down! <---\r\n");break; default:break;}
}
}
/* 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 */

📚相关测试工程

链接:https://pan.baidu.com/s/1DRqSkKnj6Kznh3izOLrlWQ?pwd=awf4 
提取码:awf4
链接:https://pan.baidu.com/s/1rviDB1MHQTQZkIBr590wXQ?pwd=11tu 
提取码:11tu
链接:https://pan.baidu.com/s/1GkQE7OZJnBn8t6gNXMahEw?pwd=vhw5 
提取码:vhw5

相关文章:

HAL STM32通过multi_button库处理按键事件

HAL STM32通过multi_button库处理按键事件 &#x1f4cd;作者&#xff1a;0x1abin的multi_button库:https://github.com/0x1abin/MultiButton &#x1f4d8;MultiButton简介 MultiButton 是一个小巧简单易用的事件驱动型按键驱动模块&#xff0c;可无限量扩展按键&#xff0c;…...

随机过程及应用学习笔记(一)概率论(概要)

概率是随机的基础&#xff0c;在【概率论&#xff08;概要&#xff09;】这个部分中仅记录学习随机过程及应用的基本定义和结果。 前言 首先&#xff0c;概率论研究的基础是概率空间。概率空间由一个样本空间和一个概率测度组成&#xff0c;样本空间包含了所有可能的结果&…...

洛谷_P1059 [NOIP2006 普及组] 明明的随机数_python写法

这道题的关键在于去重和排序&#xff0c;去重可以联想到集合&#xff0c;那排序直接使用sort方法。 n int(input()) data set(map(int,input().split( ))) data list(data) data.sort() print(len(data)) for i in data:print(i,end )...

爆火的人工智能开源open-interpreter源码解析

今天这篇文章带大家一起来阅读下github上爆火的开源项目 open-interpreter的源代码&#xff0c;相当于是一个可以本地部署的openai code-interpreter。 今天这期我们透过现象看本质&#xff0c;一起来剖析下他的源码。 体验open-interpreter的视频地址 open-interpreter&…...

POM设计模式思路,详解POM:概述与介绍,POM思路梳理+代码示例(全)

概述 在UI自动化测试中&#xff0c;POM模式是一种设计思路&#xff0c;它的核心思想是方法的封装。它将方法类和页面元素进行分离&#xff0c;增强了代码的可维护性。值得注意的是&#xff0c;这种分层的设计模式&#xff0c;最好也是从线性代码开始&#xff0c;逐步将代码进行…...

1、学习 Eureka 注册中心

学习 Eureka 注册中心 一、创建 Eureka 微服务0、SpringBoot 和 SpringCloud 版本1、引入 Eureka 服务端依赖2、启动类加 EnableEurekaServer 注解3、配置 yaml 文件&#xff0c;把 Eureka 服务注册到 Eureka 注册中心4、访问 Eureka 服务端&#xff0c;查看注册中心的服务列表…...

何为分账系统?

1、分账系统产生的背景 在数字化浪潮下第三方支付价值凸显&#xff0c;大大提升资金流与信息流流转效率&#xff0c;成为构建产业数字化重要枢纽。近年来&#xff0c;基于云计算、大数据、人工智能、物联网等技术积累&#xff0c;以第三方支付为切点的金融科技创新爆发着强大的…...

机器学习10-特征缩放

特征缩放的目的是确保不同特征的数值范围相近&#xff0c;使得模型在训练过程中更加稳定&#xff0c;加速模型收敛&#xff0c;提高模型性能。具体而言&#xff0c;零均值和单位方差的目标有以下几点好处&#xff1a; 1. 均值为零&#xff08;Zero Mean&#xff09;&#xff1a…...

Java基于微信小程序的医院挂号小程序,附源码

博主介绍&#xff1a;✌程序员徐师兄、7年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;…...

HarmonyOS一杯冰美式的时间 -- 验证码框

一、前言 像是短密码、验证码都有可能需要一个输入框&#xff0c;像是如下&#xff1a; 恰好在写HarmonyOS的时候也需要写一个验证码输入框&#xff0c;但是在实现的时候碰了几次灰&#xff0c;觉得有必要分享下&#xff0c;故有了此篇文章。 如果您有任何疑问、对文章写的不…...

GitLab配置SSHKey

段落一&#xff1a;什么是SSH密钥 SSH&#xff08;Secure Shell&#xff09;是一种网络协议&#xff0c;用于安全地远程登录和执行命令。SSH密钥是一种用于身份验证的加密文件&#xff0c;它允许您在与远程服务器通信时&#xff0c;无需输入密码即可进行认证。在GitLab中配置S…...

通过QT制作一个模仿微信主界面的界面(不要求实现具体通信功能)

main.cpp #include "widget.h" #include "second.h"#include <QApplication>int main(int argc, char *argv[]) {QApplication a(argc, argv);Widget w;w.show();//实例化第二个界面Second s;QObject::connect(&w, &Widget::my_jump, &…...

作物模型狂奔:WOFOST(PCSE) 数据同化思路

去B吧&#xff0c;这里没图 整体思路&#xff1a;PCSE -》 敏感性分析 -》调参 -》同化 0、准备工作 0.0 电脑环境 我用的Win10啦&#xff0c;Linux、Mac可能得自己再去微调一下。 0.1 Python IDE 我用的Pycharm&#xff0c;个人感觉最好使的IDE&#xff0c;没有之一。 …...

腾讯云4核8G服务器能支持多少人访问?

腾讯云4核8G服务器支持多少人在线访问&#xff1f;支持25人同时访问。实际上程序效率不同支持人数在线人数不同&#xff0c;公网带宽也是影响4核8G服务器并发数的一大因素&#xff0c;假设公网带宽太小&#xff0c;流量直接卡在入口&#xff0c;4核8G配置的CPU内存也会造成计算…...

多重背包问题 ⅠⅡ Ⅲ

有 N 种物品和一个容量是 V 的背包。 第 i 种物品最多有 si 件&#xff0c;每件体积是 vi&#xff0c;价值是 wi。 求解将哪些物品装入背包&#xff0c;可使物品体积总和不超过背包容量&#xff0c;且价值总和最大。 输出最大价值。 输入 第一行两个整数&#xff0c;N&#xf…...

挑战杯 python的搜索引擎系统设计与实现

0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; python的搜索引擎系统设计与实现 &#x1f947;学长这里给一个题目综合评分(每项满分5分) 难度系数&#xff1a;3分工作量&#xff1a;5分创新点&#xff1a;3分 该项目较为新颖&#xff…...

【LeetCode: 103. 二叉树的锯齿形层序遍历 + BFS】

&#x1f680; 算法题 &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;…...

C#学习(十三)——多线程与异步

一、什么是线程 程序执行的最小单元 一次页面的渲染、一次点击事件的触发、一次数据库的访问、一次登录操作都可以看作是一个一个的进程 在一个进程中同时启用多个线程并行操作&#xff0c;就叫做多线程 由CPU来自动处理 线程有运行、阻塞、就绪三态 代码示例&#xff1a; cl…...

MySQL 数据库安装教程详解(linux系统和windows系统)

MySQL 数据库是一种广泛使用的开源关系数据库管理系统。在 Linux 和 Windows 系统上安装 MySQL 数据库的步骤略有不同。以下是详细的安装教程。 Linux 系统安装教程 1. **安装前提**&#xff1a;确保你的 Linux 系统已经安装了 wget、unzip、tar 等必要的工具。 2. **下…...

从汇编分析C语言可变参数的原理,并实现一个简单的sprintf函数

C语言可变参数 使用printf等函数的时候函数原型是printf(const char* fmt, ...), 这一类参数的个数不限的函数是可变参数 使用 使用一个头文件stdarg.h, 主要使用以下的宏 typedef char * va_list;// 把 n 圆整到 sizeof(int) 的倍数 #define _INTSIZEOF(n) ( (sizeo…...

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造&#xff0c;完美适配AGV和无人叉车。同时&#xff0c;集成以太网与语音合成技术&#xff0c;为各类高级系统&#xff08;如MES、调度系统、库位管理、立库等&#xff09;提供高效便捷的语音交互体验。 L…...

基于距离变化能量开销动态调整的WSN低功耗拓扑控制开销算法matlab仿真

目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.算法仿真参数 5.算法理论概述 6.参考文献 7.完整程序 1.程序功能描述 通过动态调整节点通信的能量开销&#xff0c;平衡网络负载&#xff0c;延长WSN生命周期。具体通过建立基于距离的能量消耗模型&am…...

ssc377d修改flash分区大小

1、flash的分区默认分配16M、 / # df -h Filesystem Size Used Available Use% Mounted on /dev/root 1.9M 1.9M 0 100% / /dev/mtdblock4 3.0M...

uni-app学习笔记二十二---使用vite.config.js全局导入常用依赖

在前面的练习中&#xff0c;每个页面需要使用ref&#xff0c;onShow等生命周期钩子函数时都需要像下面这样导入 import {onMounted, ref} from "vue" 如果不想每个页面都导入&#xff0c;需要使用node.js命令npm安装unplugin-auto-import npm install unplugin-au…...

《从零掌握MIPI CSI-2: 协议精解与FPGA摄像头开发实战》-- CSI-2 协议详细解析 (一)

CSI-2 协议详细解析 (一&#xff09; 1. CSI-2层定义&#xff08;CSI-2 Layer Definitions&#xff09; 分层结构 &#xff1a;CSI-2协议分为6层&#xff1a; 物理层&#xff08;PHY Layer&#xff09; &#xff1a; 定义电气特性、时钟机制和传输介质&#xff08;导线&#…...

Qt Widget类解析与代码注释

#include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this); }Widget::~Widget() {delete ui; }//解释这串代码&#xff0c;写上注释 当然可以&#xff01;这段代码是 Qt …...

java调用dll出现unsatisfiedLinkError以及JNA和JNI的区别

UnsatisfiedLinkError 在对接硬件设备中&#xff0c;我们会遇到使用 java 调用 dll文件 的情况&#xff0c;此时大概率出现UnsatisfiedLinkError链接错误&#xff0c;原因可能有如下几种 类名错误包名错误方法名参数错误使用 JNI 协议调用&#xff0c;结果 dll 未实现 JNI 协…...

el-switch文字内置

el-switch文字内置 效果 vue <div style"color:#ffffff;font-size:14px;float:left;margin-bottom:5px;margin-right:5px;">自动加载</div> <el-switch v-model"value" active-color"#3E99FB" inactive-color"#DCDFE6"…...

css的定位(position)详解:相对定位 绝对定位 固定定位

在 CSS 中&#xff0c;元素的定位通过 position 属性控制&#xff0c;共有 5 种定位模式&#xff1a;static&#xff08;静态定位&#xff09;、relative&#xff08;相对定位&#xff09;、absolute&#xff08;绝对定位&#xff09;、fixed&#xff08;固定定位&#xff09;和…...

华为云Flexus+DeepSeek征文|DeepSeek-V3/R1 商用服务开通全流程与本地部署搭建

华为云FlexusDeepSeek征文&#xff5c;DeepSeek-V3/R1 商用服务开通全流程与本地部署搭建 前言 如今大模型其性能出色&#xff0c;华为云 ModelArts Studio_MaaS大模型即服务平台华为云内置了大模型&#xff0c;能助力我们轻松驾驭 DeepSeek-V3/R1&#xff0c;本文中将分享如何…...