STM32F7xx —— Timer
目录
STM32F7xx —— Timer
一、基础定时器配置
二、带回调定时器
作用:输出PWM,测量脉冲长度,定时等。
一、基础定时器配置
// 基本定时器
#define TIMER_CHANNEL TIM3
#define TIMER_PREEMPT_PRIO TIM_PRIORITY
#define TIMER_RCC_FUNC __HAL_RCC_TIM3_CLK_ENABLE
#define TIMER_IRQ TIM3_IRQn
#define TIMER_IRQ_FUNC TIM3_IRQHandler
#define TIMER_DIV (10800 - 1)
#define TIMER_PERIOD (100 - 1)static TIM_HandleTypeDef timer_handler; // 定时器操作句柄// Period:自动重装值。 Prescaler:时钟预分频数
// 定时器溢出时间计算方法:Tout=((Period+1)*(Prescaler+1))/Ft us.
// Ft=定时器工作频率,单位:Mhz
void TimerInit(void)
{timer_handler.Instance = TIMER_CHANNEL;timer_handler.Init.Prescaler = TIMER_DIV;timer_handler.Init.CounterMode = TIM_COUNTERMODE_UP;timer_handler.Init.Period = TIMER_PERIOD;timer_handler.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;HAL_TIM_Base_Init(&timer_handler);HAL_TIM_Base_Start_IT(&timer_handler);
}// 定时器底层驱动 开启时钟 设置中断优先级
// 此函数会被 HAL_TIM_Base_Init()函数调用
void HAL_TIM_Base_MspInit(TIM_HandleTypeDef *timer)
{TIMER_RCC_FUNC();HAL_NVIC_SetPriority(TIMER_IRQ, TIM_PRIORITY, 1);HAL_NVIC_EnableIRQ(TIMER_IRQ);
}void TIMER_IRQ_FUNC(void)
{HAL_TIM_IRQHandler(&timer_handler);
}// 中断服务函数调用
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *timer)
{if(timer == (&timer_handler)){// do something}
}
二、带回调定时器
使用回调函数,以链表的方式管理所有的定时器。检测时间到,执行回调函数。TimerRun定时运行,TimerCreate创建一个定时器,TimerStart开启定时器。这里只是写了一个比较简单的定时器,操作系统里面也有类似的定时接口。
#define TIMER_CHANNEL TIM3
#define TIMER_PREEMPT_PRIO TIM_PRIORITY
#define TIMER_RCC_FUNC __HAL_RCC_TIM3_CLK_ENABLE
#define TIMER_IRQ TIM3_IRQn
#define TIMER_IRQ_FUNC TIM3_IRQHandler
#define TIMER_DIV (10800 - 1)
#define TIMER_PERIOD (100 - 1)static struct
{timer_t *next;
} timer_run;static volatile uint32_t timer_ticks;
static uint32_t timer_ticks_run;static TIM_HandleTypeDef timer_handler; // 定时器操作句柄// Period:自动重装值。 Prescaler:时钟预分频数
// 定时器溢出时间计算方法:Tout=((Period+1)*(Prescaler+1))/Ft us.
// Ft=定时器工作频率,单位:Mhz
void TimerInit(void)
{timer_run.next = NULL;timer_handler.Instance = TIMER_CHANNEL;timer_handler.Init.Prescaler = TIMER_DIV;timer_handler.Init.CounterMode = TIM_COUNTERMODE_UP;timer_handler.Init.Period = TIMER_PERIOD;timer_handler.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;HAL_TIM_Base_Init(&timer_handler);HAL_TIM_Base_Start_IT(&timer_handler);
}// 定时器底层驱动 开启时钟 设置中断优先级
// 此函数会被 HAL_TIM_Base_Init()函数调用
void HAL_TIM_Base_MspInit(TIM_HandleTypeDef *timer)
{TIMER_RCC_FUNC();HAL_NVIC_SetPriority(TIMER_IRQ, TIM_PRIORITY, 1);HAL_NVIC_EnableIRQ(TIMER_IRQ);
}void TIMER_IRQ_FUNC(void)
{HAL_TIM_IRQHandler(&timer_handler);
}// 中断服务函数调用
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *timer)
{if(timer == (&timer_handler)){++timer_ticks;}
}//======================================================================================================
void TimerRun(void)
{timer_t *timer;timer_t *timer_done;timer_done = NULL;while(timer_ticks_run != timer_ticks){timer = timer_run.next;if(timer){if(timer->ticks){++timer_ticks_run;timer->ticks--;}// 将后续超时的定时器都移除while(timer && (0 == timer->ticks)){timer_run.next = timer->next;timer->next = timer_done;timer_done = timer;timer = timer_run.next;}}else{++timer_ticks_run;}}while(timer_done){timer = timer_done;timer_done = timer->next;timer->next = NULL;timer->handler(timer->param);}
}void TimerCreate(timer_t *timer, timer_cb_t handler, void *param)
{timer->handler = handler;timer->param = param;
}void TimerStart(timer_t *timer, uint32_t timeout)
{timer_t *p;uint32_t ticks = (timeout + 9) / 10;TimerCancel(timer);p = (timer_t *)&timer_run;while(p->next){if(ticks <= p->next->ticks){p->next->ticks -= ticks;break;}else{ticks -= p->next->ticks; // ticks 有可能为 0}p = p->next;}timer->ticks = ticks;timer->next = p->next;p->next = timer;
}void TimerCancel(timer_t *timer)
{timer_t *p;if(NULL == timer){return;}p = (timer_t *)&timer_run;while(p->next){if(p->next == timer){if(timer->next){timer->next->ticks += timer->ticks;}p->next = timer->next;timer->next = NULL;break;}p = p->next;}
}
static timer_t timer;
static void handler(void *param)
{TimerStart(&timer, 1000);printf("TimerStart\r\n");
}TimerCreate(&timer, handler, NULL);TimerStart(&timer, 1000);TimerRun(); // 放在10ms任务中运行