一些比较好的笔记
原作者网址:https://github.com/0x1abin/MultiTimer
网上有很多教程,但是原作者已经重新开发了一套,但是博客作者没有更新
https://blog.csdn.net/qq_36075612/article/details/115636523?utm_medium=distribute.pc_relevant.none-task-blog-2
本来想去找基于HAL开发MultiTimer,却让我找到一个关于HAL库Systick-系统滴答定时器详解,文章确实写的很不错
https://blog.51cto.com/u_12968763/5078642

找了很久才找到一个新的教程,但是这个教程乍一看有点乱,其实细看还好,结尾还说了一些实现的原理
https://blog.csdn.net/Mculover666/article/details/124359206
接下来我将我移植的步骤记录下来,作为纯开发记录


  • 移植.h 和 .c文件
    这个我相信大家都是懂的,并且在你的main.c文件中include进来

  • 在main函数开始后的初始化中,安装tick函数
MultiTimerInstall(PlatformTicksGetFunc);

  • 在main函数前面定义的地方,获取系统 tick
/* USER CODE BEGIN 0 */uint64_t PlatformTicksGetFunc(void){  return (uint64_t)HAL_GetTick();}/* USER CODE END 0 */

  • 在定义变量的地方,创建Timer对象
MultiTimer timer1;

  • 在声明函数的地方,声明Timer回调函数
void timer1_callback(MultiTimer* timer, void* userData);

  • 在函数定义的地方,实现Timer回调函数功能
void timer1_callback(MultiTimer* timer, void* userData){    HAL_GPIO_TogglePin(LED1_GPIO_Port,LED1_Pin);                 //需要做的任务    MultiTimerStart(&timer1, test_timer1, timer1_callback, NULL);    //这里要将任务重新开始,不然函数只会执行一次,第二个参数就是定时时间,默认1000}

  • 在main函数while开始前面,启动定时器
MultiTimerStart(&timer1, 1000, timer1_callback, NULL);

  • 在主循环while中调用Timer对象处理函数
MultiTimerYield();

至此,函数已经分类实现完毕,接下来给一份完整main.c文件,作为参考
/* USER CODE BEGIN Header *//**  ******************************************************************************  * @file           : main.c  * @brief          : Main program body  ******************************************************************************  * @attention  *  * Copyright (c) 2023 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 */#include "MultiTimer.h"/* USER CODE END Includes *//* Private typedef -----------------------------------------------------------*//* USER CODE BEGIN PTD */#define TIMER1  2#define TIMER2  500/* 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 ---------------------------------------------------------*/MultiTimer timer1;MultiTimer timer2;/* USER CODE BEGIN PV *//* USER CODE END PV *//* Private function prototypes -----------------------------------------------*/void SystemClock_Config(void);/* USER CODE BEGIN PFP */void timer1_callback(MultiTimer* timer, void* userData);void timer2_callback(MultiTimer* timer, void* userData);/* USER CODE END PFP *//* Private user code ---------------------------------------------------------*//* USER CODE BEGIN 0 */uint64_t PlatformTicksGetFunc(void){  return (uint64_t)HAL_GetTick();}/* USER CODE END 0 *//**  * @brief  The application entry point.  * @retval int  */int main(int argc, char *argv[]){  /* 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 */    MultiTimerInstall(PlatformTicksGetFunc);  /* USER CODE END 2 */  /* Infinite loop */  /* USER CODE BEGIN WHILE */    MultiTimerStart(&timer1, TIMER1, timer1_callback, NULL);    MultiTimerStart(&timer2, TIMER2, timer2_callback, NULL);  while (1)  {    /* USER CODE END WHILE */        /* USER CODE BEGIN 3 */          MultiTimerYield();        }  /* 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 */void timer1_callback(MultiTimer* timer, void* userData){    HAL_GPIO_TogglePin(LED1_GPIO_Port,LED1_Pin);    MultiTimerStart(&timer1, TIMER1, timer1_callback, NULL);}void timer2_callback(MultiTimer* timer, void* userData){    MultiTimerStart(&timer2, TIMER2, timer2_callback, NULL);}/* 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 */