作用:输出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("TimerStartrn");
}
TimerCreate(&timer, handler, NULL);
TimerStart(&timer, 1000);
TimerRun(); // 放在10ms任务中运行
上一篇:STM32F7xx —— LAN8720(FreeRTOS+LWIP)
下一篇:STM32F7xx —— FatFS(W25QXX)
推荐阅读最新更新时间:2024-11-05 20:49