当前位置: 首页 > 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…...

[2025CVPR]DeepVideo-R1:基于难度感知回归GRPO的视频强化微调框架详解

突破视频大语言模型推理瓶颈,在多个视频基准上实现SOTA性能 一、核心问题与创新亮点 1.1 GRPO在视频任务中的两大挑战 ​安全措施依赖问题​ GRPO使用min和clip函数限制策略更新幅度,导致: 梯度抑制:当新旧策略差异过大时梯度消失收敛困难:策略无法充分优化# 传统GRPO的梯…...

基于FPGA的PID算法学习———实现PID比例控制算法

基于FPGA的PID算法学习 前言一、PID算法分析二、PID仿真分析1. PID代码2.PI代码3.P代码4.顶层5.测试文件6.仿真波形 总结 前言 学习内容&#xff1a;参考网站&#xff1a; PID算法控制 PID即&#xff1a;Proportional&#xff08;比例&#xff09;、Integral&#xff08;积分&…...

cf2117E

原题链接&#xff1a;https://codeforces.com/contest/2117/problem/E 题目背景&#xff1a; 给定两个数组a,b&#xff0c;可以执行多次以下操作&#xff1a;选择 i (1 < i < n - 1)&#xff0c;并设置 或&#xff0c;也可以在执行上述操作前执行一次删除任意 和 。求…...

从零开始打造 OpenSTLinux 6.6 Yocto 系统(基于STM32CubeMX)(九)

设备树移植 和uboot设备树修改的内容同步到kernel将设备树stm32mp157d-stm32mp157daa1-mx.dts复制到内核源码目录下 源码修改及编译 修改arch/arm/boot/dts/st/Makefile&#xff0c;新增设备树编译 stm32mp157f-ev1-m4-examples.dtb \stm32mp157d-stm32mp157daa1-mx.dtb修改…...

unix/linux,sudo,其发展历程详细时间线、由来、历史背景

sudo 的诞生和演化,本身就是一部 Unix/Linux 系统管理哲学变迁的微缩史。来,让我们拨开时间的迷雾,一同探寻 sudo 那波澜壮阔(也颇为实用主义)的发展历程。 历史背景:su的时代与困境 ( 20 世纪 70 年代 - 80 年代初) 在 sudo 出现之前,Unix 系统管理员和需要特权操作的…...

USB Over IP专用硬件的5个特点

USB over IP技术通过将USB协议数据封装在标准TCP/IP网络数据包中&#xff0c;从根本上改变了USB连接。这允许客户端通过局域网或广域网远程访问和控制物理连接到服务器的USB设备&#xff08;如专用硬件设备&#xff09;&#xff0c;从而消除了直接物理连接的需要。USB over IP的…...

Vue ③-生命周期 || 脚手架

生命周期 思考&#xff1a;什么时候可以发送初始化渲染请求&#xff1f;&#xff08;越早越好&#xff09; 什么时候可以开始操作dom&#xff1f;&#xff08;至少dom得渲染出来&#xff09; Vue生命周期&#xff1a; 一个Vue实例从 创建 到 销毁 的整个过程。 生命周期四个…...

MySQL体系架构解析(三):MySQL目录与启动配置全解析

MySQL中的目录和文件 bin目录 在 MySQL 的安装目录下有一个特别重要的 bin 目录&#xff0c;这个目录下存放着许多可执行文件。与其他系统的可执行文件类似&#xff0c;这些可执行文件都是与服务器和客户端程序相关的。 启动MySQL服务器程序 在 UNIX 系统中&#xff0c;用…...

PydanticAI快速入门示例

参考链接&#xff1a;https://ai.pydantic.dev/#why-use-pydanticai 示例代码 from pydantic_ai import Agent from pydantic_ai.models.openai import OpenAIModel from pydantic_ai.providers.openai import OpenAIProvider# 配置使用阿里云通义千问模型 model OpenAIMode…...

Copilot for Xcode (iOS的 AI辅助编程)

Copilot for Xcode 简介Copilot下载与安装 体验环境要求下载最新的安装包安装登录系统权限设置 AI辅助编程生成注释代码补全简单需求代码生成辅助编程行间代码生成注释联想 代码生成 总结 简介 尝试使用了Copilot&#xff0c;它能根据上下文补全代码&#xff0c;快速生成常用…...