视频网站开发背景,网站模板编号,网站建设销售岗位职责,昭通网站建设前言
本驱动运行stm32f407zgt6上已测试ok。基于rtthread的定时器组件源码改编而来.驱动记录
驱动代码
定时器组件
头文件
/*
* Copyright (c) 2006-2023, RT-Thread Development Team** SPDX-License-Identifier: Apache-2.0** Change Logs:* Date Author …前言
本驱动运行stm32f407zgt6上已测试ok。基于rtthread的定时器组件源码改编而来.驱动记录
驱动代码
定时器组件
头文件
/*
* Copyright (c) 2006-2023, RT-Thread Development Team** SPDX-License-Identifier: Apache-2.0** Change Logs:* Date Author Notes*/
#ifndef HWTIMER_H
#define HWTIMER_H
#include stdint.h
#include stdlib.h
#include string.h
#include stdio.h
#include assert.h
#define HWTIMER_CNTMODE_UP 0x01 /* increment count mode */
#define HWTIMER_CNTMODE_DW 0x02 /* decreasing count mode *//* Timing Mode */
typedef enum
{HWTIMER_MODE_ONESHOT 0x01,HWTIMER_MODE_PERIOD
} rt_hwtimer_mode_t;/* Timer Control Command */
typedef enum
{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 */
typedef struct rt_hwtimerval
{int sec; /* second */int usec; /* microsecond */
} rt_hwtimerval_t;struct rt_hwtimer_device;struct rt_hwtimer_ops
{void (*init)(struct rt_hwtimer_device* timer, uint32_t state);int (*start)(struct rt_hwtimer_device* timer, uint32_t cnt, rt_hwtimer_mode_t mode);void (*stop)(struct rt_hwtimer_device* timer);uint32_t (*count_get)(struct rt_hwtimer_device* timer);int (*control)(struct rt_hwtimer_device* timer, uint32_t cmd, void* args);
};/* Timer Feature Information */
struct rt_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) */
};typedef struct rt_hwtimer_device
{const struct rt_hwtimer_ops* ops;const struct rt_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)(struct rt_hwtimer_device* dev);
} rt_hwtimer_t;int rt_hwtimer_init(rt_hwtimer_t* timer);
int rt_hwtimer_open(rt_hwtimer_t* timer);
int rt_hwtimer_close(rt_hwtimer_t* timer);
int rt_hwtimer_read(rt_hwtimer_t* timer, rt_hwtimerval_t* tv);
int rt_hwtimer_write(rt_hwtimer_t* timer, rt_hwtimerval_t* hwtimerval);
int rt_hwtimer_control(rt_hwtimer_t* timer, int cmd, void* args);
void rt_device_hwtimer_isr(rt_hwtimer_t* timer);#endif //HWTIMER_H
源文件
/********************************************************************************* file : hwtimer.c* author : shchl* brief : None* version : 1.0* attention : None* date : 25-6-14******************************************************************************
*/
#include main.h
#include hwtimer.h
#ifndef DISABLE_INT
#define DISABLE_INT() __disable_irq()
#endif // DISABLE_INT
#ifndef ENABLE_INT
#define ENABLE_INT() __enable_irq()
#endif // ENABLE_INTstatic inline uint32_t timeout_calc(rt_hwtimer_t* timer, rt_hwtimerval_t* tv)
{float overflow;float timeout;uint32_t counter;int i, index 0;float tv_sec;float devi_min 1;float devi;/* changed to second */overflow timer-info-maxcnt / (float)timer-freq;tv_sec tv-sec tv-usec / (float)1000000;if (tv_sec (1 / (float)timer-freq)){/* little timeout */i 0;timeout 1 / (float)timer-freq;}else{for (i 1; i 0; i){timeout tv_sec / i;if (timeout overflow){counter (uint32_t)(timeout * timer-freq);devi tv_sec - (counter / (float)timer-freq) * i;/* Minimum calculation error */if (devi devi_min){i index;timeout tv_sec / i;break;}if (devi 0){break;}if (devi devi_min){devi_min devi;index i;}}}}timer-cycles i;timer-reload i;timer-period_sec timeout;counter (uint32_t)(timeout * timer-freq);return counter;
}int rt_hwtimer_init(rt_hwtimer_t* timer)
{if (timer-ops-init NULL) return -1;/* try to change to 1MHz */if ((1000000 timer-info-maxfreq) (1000000 timer-info-minfreq)){timer-freq 1000000;}else{timer-freq timer-info-minfreq;}timer-mode HWTIMER_MODE_ONESHOT;timer-cycles 0;timer-overflow 0;timer-ops-init(timer, 1);return 0;
}int rt_hwtimer_open(rt_hwtimer_t* timer)
{if (timer-ops-control NULL) return -1;timer-ops-control(timer, HWTIMER_CTRL_FREQ_SET, timer-freq);return 0;
}int rt_hwtimer_close(rt_hwtimer_t* timer)
{if (timer-ops-init NULL) return -1;timer-ops-init(timer, 0);timer-rx_indicate NULL;return 0;
}int rt_hwtimer_read(rt_hwtimer_t* timer, rt_hwtimerval_t* tv)
{if (timer-ops-count_get NULL) return -1;DISABLE_INT();uint32_t cnt timer-ops-count_get(timer);int32_t overflow timer-overflow;ENABLE_INT();if (timer-info-cntmode HWTIMER_CNTMODE_DW){cnt (uint32_t)(timer-freq * timer-period_sec) - cnt;}if (timer-mode HWTIMER_MODE_ONESHOT){overflow 0;}float t overflow * timer-period_sec cnt / (float)timer-freq;tv-sec (int32_t)t;tv-usec (int32_t)((t - tv-sec) * 1000000);return 0;
}int rt_hwtimer_write(rt_hwtimer_t* timer, rt_hwtimerval_t* hwtimerval)
{uint32_t t;rt_hwtimer_mode_t opm HWTIMER_MODE_PERIOD;if ((timer-ops-start NULL) || (timer-ops-stop NULL)) return -1;timer-ops-stop(timer);DISABLE_INT();timer-overflow 0;ENABLE_INT();t timeout_calc(timer, hwtimerval);if ((timer-cycles 1) (timer-mode HWTIMER_MODE_ONESHOT)){opm HWTIMER_MODE_ONESHOT;}if (timer-ops-start(timer, t, opm) ! 0) return -2;return 0;
}int rt_hwtimer_control(rt_hwtimer_t* timer, int cmd, void* args)
{int result 0;switch (cmd){case HWTIMER_CTRL_STOP:{if (timer-ops-stop ! NULL){timer-ops-stop(timer);}else{result -1;}}break;case HWTIMER_CTRL_FREQ_SET:{int32_t* f;if (args NULL){result -2;break;}f (int32_t*)args;if ((*f timer-info-maxfreq) || (*f timer-info-minfreq)){// LOG_W(frequency setting out of range! It will maintain at %d Hz, timer-freq);result -3;break;}if (timer-ops-control ! NULL){result timer-ops-control(timer, cmd, args);if (result 0){DISABLE_INT();timer-freq *f;ENABLE_INT();}}else{result -1;}}break;case HWTIMER_CTRL_INFO_GET:{if (args NULL){result -2;break;}*((struct rt_hwtimer_info*)args) *timer-info;}break;case HWTIMER_CTRL_MODE_SET:{rt_hwtimer_mode_t* m;if (args NULL){result -2;break;}m (rt_hwtimer_mode_t*)args;if ((*m ! HWTIMER_MODE_ONESHOT) (*m ! HWTIMER_MODE_PERIOD)){result -3;break;}DISABLE_INT();timer-mode *m;ENABLE_INT();}break;default:{if (timer-ops-control ! NULL){result timer-ops-control(timer, cmd, args);}else{result -1;}}break;}return result;
}void rt_device_hwtimer_isr(rt_hwtimer_t* timer)
{timer-overflow;if (timer-cycles ! 0){timer-cycles--;}if (timer-cycles 0){timer-cycles timer-reload;if (timer-mode HWTIMER_MODE_ONESHOT){if (timer-ops-stop ! NULL){timer-ops-stop(timer);}}if (timer-rx_indicate){timer-rx_indicate(timer);}}
}
定时器组件实现(STM32F407ZGT6)
头文件
/********************************************************************************* file : drv_hwtimer.h* author : shchl* brief : None* version : 1.0* attention : None* date : 25-6-14******************************************************************************
*/#ifndef DRV_HWTIMER_H
#define DRV_HWTIMER_H
#include hwtimer.h
#define TIM_DEV_INFO_CONFIG \
{ \.maxfreq 1000000, \.minfreq 3000, \.maxcnt 0xFFFF, \.cntmode HWTIMER_CNTMODE_UP, \
}enum
{TIM1_INDEX,TIM2_INDEX,TIM3_INDEX,TIM4_INDEX,TIM5_INDEX,TIM6_INDEX,TIM7_INDEX,TIM8_INDEX,TIM9_INDEX,TIM10_INDEX,TIM11_INDEX,TIM12_INDEX,TIM13_INDEX,TIM14_INDEX,TIM15_INDEX,TIM16_INDEX,TIM17_INDEX,
};void stm32_hwtimer_init(void);
rt_hwtimer_t* stm32_hwtimer_get(int index);
#endif //DRV_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.hstruct stm32_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 */
static void pclkx_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;}
}static void timer_init(struct rt_hwtimer_device* timer, uint32_t state)
{assert(timer);uint32_t pclk1_doubler, pclk2_doubler;TIM_HandleTypeDef* tim NULL;struct stm32_hwtimer* tim_device NULL;if (state){uint32_t prescaler_value 0;tim_device (struct stm32_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);}
}static int timer_start(rt_hwtimer_t* timer, uint32_t t, rt_hwtimer_mode_t opmode)
{TIM_HandleTypeDef* tim NULL;assert(timer ! NULL);struct stm32_hwtimer* tim_device (struct stm32_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;return 0;
}static void timer_stop(rt_hwtimer_t* timer)
{TIM_HandleTypeDef* tim NULL;assert(timer ! NULL);const struct stm32_hwtimer* tim_device (struct stm32_hwtimer*)timer;tim tim_device-tim_handle;/* stop timer */HAL_TIM_Base_Stop_IT(tim);/* set tim cnt */__HAL_TIM_SET_COUNTER(tim, 0);
}static uint32_t timer_counter_get(rt_hwtimer_t* timer)
{TIM_HandleTypeDef* tim NULL;assert(timer ! NULL);const struct stm32_hwtimer* tim_device (struct stm32_hwtimer*)timer;tim tim_device-tim_handle;return tim-Instance-CNT;
}static int timer_ctrl(rt_hwtimer_t* timer, uint32_t cmd, void* arg)
{uint32_t pclk1_doubler, pclk2_doubler;TIM_HandleTypeDef* tim NULL;assert(timer ! NULL);const struct stm32_hwtimer* tim_device (struct stm32_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;}}return 0;
}static const struct rt_hwtimer_info _info TIM_DEV_INFO_CONFIG;
static const struct rt_hwtimer_ops _ops
{.init timer_init,.start timer_start,.stop timer_stop,.count_get timer_counter_get,.control timer_ctrl,
};
struct stm32_hwtimer timer14_dev;void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef* htim)
{if (htim-Instance TIM14){rt_device_hwtimer_isr(timer14_dev.time_device);}
}
void TIM8_TRG_COM_TIM14_IRQHandler(void)
{/* enter interrupt */HAL_TIM_IRQHandler(timer14_dev.tim_handle);/* leave interrupt */
}
void stm32_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(const int index)
{if (index TIM14_INDEX) return timer14_dev.time_device;return NULL;
}
测试
主程序
int receive_timeout_callback(rt_hwtimer_t* rt_hwtimer)
{printf(%d\r\n, HAL_GetTick());return 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_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! cant find %s device!, RECEIVE_HWTIMER);return 1;}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 */
}测试结果