/*
* Copyright (c) 2006-2023, RT-Thread Development Team** SPDX-License-Identifier: Apache-2.0** Change Logs:* Date Author Notes*/#ifndefHWTIMER_H#defineHWTIMER_H#include<stdint.h>#include<stdlib.h>#include<string.h>#include<stdio.h>#include<assert.h>#defineHWTIMER_CNTMODE_UP0x01/* increment count mode */#defineHWTIMER_CNTMODE_DW0x02/* decreasing count mode *//* Timing Mode */typedefenum{HWTIMER_MODE_ONESHOT =0x01,HWTIMER_MODE_PERIOD
}rt_hwtimer_mode_t;/* Timer Control Command */typedefenum{HWTIMER_CTRL_FREQ_SET =0x01,/* set the count frequency */HWTIMER_CTRL_STOP =0x02,/* stop timer */HWTIMER_CTRL_INFO_GET =0x03,/* get a timer feature information */HWTIMER_CTRL_MODE_SET =0x04/* Setting the timing mode(oneshot/period) */}rt_hwtimer_ctrl_t;/* Time Value */typedefstructrt_hwtimerval{int sec;/* second */int usec;/* microsecond */}rt_hwtimerval_t;structrt_hwtimer_device;structrt_hwtimer_ops{void(*init)(structrt_hwtimer_device* timer,uint32_t state);int(*start)(structrt_hwtimer_device* timer,uint32_t cnt,rt_hwtimer_mode_t mode);void(*stop)(structrt_hwtimer_device* timer);uint32_t(*count_get)(structrt_hwtimer_device* timer);int(*control)(structrt_hwtimer_device* timer,uint32_t cmd,void* args);};/* Timer Feature Information */structrt_hwtimer_info{int maxfreq;/* the maximum count frequency timer support */int minfreq;/* the minimum count frequency timer support */uint32_t maxcnt;/* counter maximum value */uint32_t cntmode;/* count mode (inc/dec) */};typedefstructrt_hwtimer_device{conststructrt_hwtimer_ops* ops;conststructrt_hwtimer_info* info;int freq;/* counting frequency set by the user */int overflow;/* timer overflows */float period_sec;int cycles;/* how many times will generate a timeout event after overflow */int reload;/* reload cycles(using in period mode) */rt_hwtimer_mode_t mode;/* timing mode(oneshot/period) */int(*rx_indicate)(structrt_hwtimer_device* dev);}rt_hwtimer_t;intrt_hwtimer_init(rt_hwtimer_t* timer);intrt_hwtimer_open(rt_hwtimer_t* timer);intrt_hwtimer_close(rt_hwtimer_t* timer);intrt_hwtimer_read(rt_hwtimer_t* timer,rt_hwtimerval_t* tv);intrt_hwtimer_write(rt_hwtimer_t* timer,rt_hwtimerval_t* hwtimerval);intrt_hwtimer_control(rt_hwtimer_t* timer,int cmd,void* args);voidrt_device_hwtimer_isr(rt_hwtimer_t* timer);#endif//HWTIMER_H
/********************************************************************************* @file : drv_hwtimer.c* @author : shchl* @brief : None* @version : 1.0* @attention : None* @date : 25-6-14******************************************************************************
*/#include"main.h"#include"tim.h"#include"drv_hwtimer.h"structstm32_hwtimer{rt_hwtimer_t time_device;TIM_HandleTypeDef* tim_handle;IRQn_Type tim_irqn;char* name;};/* APBx timer clocks frequency doubler state related to APB1CLKDivider value */staticvoidpclkx_doubler_get(uint32_t* pclk1_doubler,uint32_t* pclk2_doubler){uint32_t flatency =0;RCC_ClkInitTypeDef RCC_ClkInitStruct ={0};HAL_RCC_GetClockConfig(&RCC_ClkInitStruct,&flatency);*pclk1_doubler =1;*pclk2_doubler =1;if(RCC_ClkInitStruct.APB1CLKDivider != RCC_HCLK_DIV1){*pclk1_doubler =2;}if(RCC_ClkInitStruct.APB2CLKDivider != RCC_HCLK_DIV1){*pclk2_doubler =2;}}staticvoidtimer_init(structrt_hwtimer_device* timer,uint32_t state){assert(timer);uint32_t pclk1_doubler, pclk2_doubler;TIM_HandleTypeDef* tim =NULL;structstm32_hwtimer* tim_device =NULL;if(state){uint32_t prescaler_value =0;tim_device =(structstm32_hwtimer*)timer;tim = tim_device->tim_handle;pclkx_doubler_get(&pclk1_doubler,&pclk2_doubler);if(tim->Instance == TIM9 || tim->Instance == TIM10 || tim->Instance == TIM11){prescaler_value =(uint32_t)(HAL_RCC_GetPCLK2Freq()* pclk2_doubler /10000)-1;}else{prescaler_value =(uint32_t)(HAL_RCC_GetPCLK1Freq()* pclk1_doubler /10000)-1;}tim->Init.Period =10000-1;tim->Init.Prescaler = prescaler_value;tim->Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;if(timer->info->cntmode == HWTIMER_CNTMODE_UP){tim->Init.CounterMode = TIM_COUNTERMODE_UP;}else{tim->Init.CounterMode = TIM_COUNTERMODE_DOWN;}tim->Init.RepetitionCounter =0;// LOG_E("%s init failed", tim_device->name);if(HAL_TIM_Base_Init(tim)!= HAL_OK)return;/* set the TIMx priority */HAL_NVIC_SetPriority(tim_device->tim_irqn,0,0);/* enable the TIMx global Interrupt */HAL_NVIC_EnableIRQ(tim_device->tim_irqn);/* clear update flag */__HAL_TIM_CLEAR_FLAG(tim, TIM_FLAG_UPDATE);/* enable update request source */__HAL_TIM_URS_ENABLE(tim);}}staticinttimer_start(rt_hwtimer_t* timer,uint32_t t,rt_hwtimer_mode_t opmode){TIM_HandleTypeDef* tim =NULL;assert(timer !=NULL);structstm32_hwtimer* tim_device =(structstm32_hwtimer*)timer;tim = tim_device->tim_handle;/* set tim cnt */__HAL_TIM_SET_COUNTER(tim,0);/* set tim arr */__HAL_TIM_SET_AUTORELOAD(tim, t -1);if(opmode == HWTIMER_MODE_ONESHOT){/* set timer to single mode */tim->Instance->CR1 |= TIM_OPMODE_SINGLE;}else{tim->Instance->CR1 &=(~TIM_OPMODE_SINGLE);}/* start timer */if(HAL_TIM_Base_Start_IT(tim)!= HAL_OK)return-1;return0;}staticvoidtimer_stop(rt_hwtimer_t* timer){TIM_HandleTypeDef* tim =NULL;assert(timer !=NULL);conststructstm32_hwtimer* tim_device =(structstm32_hwtimer*)timer;tim = tim_device->tim_handle;/* stop timer */HAL_TIM_Base_Stop_IT(tim);/* set tim cnt */__HAL_TIM_SET_COUNTER(tim,0);}staticuint32_ttimer_counter_get(rt_hwtimer_t* timer){TIM_HandleTypeDef* tim =NULL;assert(timer !=NULL);conststructstm32_hwtimer* tim_device =(structstm32_hwtimer*)timer;tim = tim_device->tim_handle;return tim->Instance->CNT;}staticinttimer_ctrl(rt_hwtimer_t* timer,uint32_t cmd,void* arg){uint32_t pclk1_doubler, pclk2_doubler;TIM_HandleTypeDef* tim =NULL;assert(timer !=NULL);conststructstm32_hwtimer* tim_device =(structstm32_hwtimer*)timer;tim = tim_device->tim_handle;switch(cmd){case HWTIMER_CTRL_FREQ_SET:{uint16_t val;/* set timer frequence */uint32_t freq =*((uint32_t*)arg);pclkx_doubler_get(&pclk1_doubler,&pclk2_doubler);if(tim->Instance == TIM9 || tim->Instance == TIM10 || tim->Instance == TIM11){val =HAL_RCC_GetPCLK2Freq()* pclk2_doubler / freq;}else{val =HAL_RCC_GetPCLK1Freq()* pclk1_doubler / freq;}__HAL_TIM_SET_PRESCALER(tim, val -1);/* Update frequency value */tim->Instance->EGR |= TIM_EVENTSOURCE_UPDATE;}break;default:{return-2;}}return0;}staticconststructrt_hwtimer_info _info = TIM_DEV_INFO_CONFIG;staticconststructrt_hwtimer_ops _ops ={.init = timer_init,.start = timer_start,.stop = timer_stop,.count_get = timer_counter_get,.control = timer_ctrl,};structstm32_hwtimer timer14_dev;voidHAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef* htim){if(htim->Instance == TIM14){rt_device_hwtimer_isr(&timer14_dev.time_device);}}voidTIM8_TRG_COM_TIM14_IRQHandler(void){/* enter interrupt */HAL_TIM_IRQHandler(timer14_dev.tim_handle);/* leave interrupt */}voidstm32_hwtimer_init(void){timer14_dev.tim_handle =&htim14;timer14_dev.name ="timer14";timer14_dev.tim_irqn = TIM8_TRG_COM_TIM14_IRQn;timer14_dev.time_device.ops =&_ops;timer14_dev.time_device.info =&_info;}rt_hwtimer_t*stm32_hwtimer_get(constint index){if(index == TIM14_INDEX)return&timer14_dev.time_device;returnNULL;}
测试
主程序
intreceive_timeout_callback(rt_hwtimer_t* rt_hwtimer){printf("%d\r\n",HAL_GetTick());return0;}/* USER CODE END 0 *//*** @brief The application entry point.* @retval int*/intmain(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_DMA_Init();MX_USART1_UART_Init();MX_TIM14_Init();/* USER CODE BEGIN 2 */// 开启串口dma接收usart1_open_receive();stm32_hwtimer_init();rt_hwtimer_mode_t mode;uint32_t freq =100000;rt_hwtimerval_t receive_time;rt_hwtimer_t* receive_time_dev =stm32_hwtimer_get(TIM14_INDEX);if(receive_time_dev ==NULL){LOG_E("hwtimer sample run failed! can't find %s device!", RECEIVE_HWTIMER);return1;}rt_hwtimer_init(receive_time_dev);rt_hwtimer_open(receive_time_dev);receive_time_dev->rx_indicate = receive_timeout_callback;rt_hwtimer_control(receive_time_dev, HWTIMER_CTRL_FREQ_SET,&freq);mode = HWTIMER_MODE_PERIOD;rt_hwtimer_control(receive_time_dev, HWTIMER_CTRL_MODE_SET,&mode);receive_time.sec =5;receive_time.usec =0;rt_hwtimer_write(receive_time_dev,&receive_time);/* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while(1){/* USER CODE END WHILE *//* USER CODE BEGIN 3 */HAL_Delay(1000);}/* USER CODE END 3 */}