STM32HAL移植MultiTimer极简美开源软件定时器(裸机开发
神器)
⽬录
概述
MultiTimer 是⼀个软件定时器扩展模块,可⽆限扩展你所需的定时器任务,取代传统的标志位判断⽅式, 更优雅更便捷地管理程序的时间触发时序。
GitHub:
硬件:STM32F103CBT6最⼩系统板
软件:Keil 5.29  + STM32CubeMX6.01
⼀、使⽤⽅法
1.先申请⼀个定时器管理handle
struct Timer timer1;
2.初始化定时器对象,注册定时器回调处理函数,设置延迟启动时间(ms),循环定时触发时间
timer_init(struct Timer* handle, void(*timeout_cb)(), uint32_t timeout, uint32_t repeat);
3.启动定时器
timer_start(&timer1);
4.设置1ms的硬件定时器循环调⽤ timer_ticks() 以提供时间基准
void HAL_SYSTICK_Callback(void)
{
timer_ticks();
}
5.在主循环调⽤定时器后台处理函数
int main()
{
...
while(1) {
...
timer_loop();
}
}
⼆、STM32CubeMx配置
三、Examples
简单粗暴,直接上代码
打开STM32CubeMX⽣成的Keil⼯程,如下所⽰:
把代码下载下来,新建Timer⽂件夹把multi_timer.c,multi_timer.h这两个⽂件添加到项⽬中来即可。
添加.h⽂件路径
1、multi_timer.h⽂件
/*
* Copyright (c) 2016 Zibin Zheng <znbin@qq>
* All rights reserved
*/
#ifndef _MULTI_TIMER_H_
#define _MULTI_TIMER_H_timeout on t2 timer
#include "stdint.h"
#include "stddef.h"
typedef struct Timer {
uint32_t timeout;      // 超时时间(⽤来与定时器⼼跳⽐较)
uint32_t repeat;      // 循环定时触发时间(周期定时设置),为0时代表单次定时
void (*timeout_cb)(void);  // 定时器回调处理函数
struct Timer* next;    // 指向下⼀个定时器节点
}Timer;
#ifdef __cplusplus
extern "C" {
#endif
void timer_init(struct Timer* handle, void(*timeout_cb)(), uint32_t timeout, uint32_t repeat); int  timer_start(struct Timer* handle);
void timer_stop(struct Timer* handle);
void timer_ticks(void);
void timer_loop(void);
// void timer_again(struct Timer* handle);
// void timer_set_repeat(struct Timer* handle, uint32_t repeat);
#ifdef __cplusplus
}
#endif
#endif
2、multi_timer.c⽂件
/*
* Copyright (c) 2016 Zibin Zheng <znbin@qq>
* All rights reserved
*/
#include "multi_timer.h"
//timer handle list head.
static struct Timer* head_handle = NULL;
//Timer ticks
static uint32_t _timer_ticks = 4294967290;
/**
* @brief  Initializes the timer struct handle.
* @param  handle: the timer handle strcut.
* @param  timeout_cb: timeout callback.
* @param  repeat: repeat interval time.
* @retval None
*/
void timer_init(struct Timer* handle, void (*timeout_cb)(), uint32_t timeout, uint32_t repeat) {
// memset(handle, sizeof(struct Timer), 0);
handle->timeout_cb = timeout_cb;
handle->timeout_cb = timeout_cb;
handle->timeout    = _timer_ticks + timeout;
handle->repeat    = repeat;
}
/**
* @brief  Start the timer work, add the handle into work list.
* @param  btn: target handle strcut.
* @retval 0: succeed. -1: already exist.
*/
int timer_start(struct Timer* handle)
{
struct Timer* target = head_handle;  // 设置⼀个临时变量就不会改变
// 遍历查判断该节点是否已存在
while(target)
{
if(target == handle)
return -1;  //already exist.
target = target->next;      // 不断遍历下⼀个节点
}
// 采⽤链表前插的⽅式,最新的定时器放在前⾯并作为头结点
handle->next = head_handle;
head_handle  = handle;
return 0;
}
/**
* @brief  Stop the timer work, remove the handle off work list.
* @param  handle: target handle strcut.
* @retval None
*/
void timer_stop(struct Timer* handle)
{
struct Timer** curr;
for(curr = &head_handle; *curr;)
{
struct Timer* entry = *curr;
if(entry == handle)
{
*curr = entry->next;      // 将当前节点脱离队列
//  free(entry);
}
else
curr = &entry->next;      // ⼆级指针curr不断后移
}
}
/**
* @brief  main loop.
* @param  None.
* @retval None
*/
void timer_loop()              // 在While循环中使⽤,定时器才会起作⽤
{
struct Timer* target;
for(target = head_handle; target; target = target->next)
{
#if 1
if(_timer_ticks >= target->timeout)
#else
//_timer_ticks 这个变量会出现溢出的情况,因为它是32位的,所以不能⼤于0xFFFFFFFF = 4,294,967,295,
//⼀天有多少s, 24*60*60*1000 = 86,400,000s,也就是改变了⼀直累加49.7天就会溢出,4,294,967,295 / 86,400,000 = 49.71026961805556天    if((int)((uint32_t)(target->timeout -_timer_ticks)) <= 0)
#endif
{

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。