【stm32】软件定时器

【stm32】软件定时器


为什么

为什么会想着搞个软件定时器呢?

之前的esp8266模块的通信,用的延时阻塞去实现的,对主程序影响挺大的。想着改改,不想上freertos啥的操作系统,就想着之前看4G模块厂家提供有的4G模块使用例程有用到软件延时去实验通信,随即就有了仿写的想法。

软件定时器

本人理解,其实是对定时器+状态机的一个封装,不阻塞的情况下,实现延时的效果。参考解释可见参考链接,代码实现也几乎全部参考此链接。

相关代码

bsp_soft_timer.h

/**
 * author:临木木
 * 适用于stm32裸机的软件定时器
 * 主程序启用前运行bsp_soft_timer_init()函数初始化软件定时器
 * bsp_soft_timer_start()函数开启你所需要的软件定时器,bsp_soft_timer_stop()函数停止,注意SOFT_TIMER_NUM
 * bsp_soft_timer_update()函数用于更新软件定时器状态,建议放置在主循环内
 * bsp_soft_timer_state_get()函数可用于获取软件定时器现所处的运行状态
 * 如无需调用回调函数,可选择设置调用函数为soft_timer_nop_callback()函数来实现
 */
#ifndef __BSP_SOFT_TIMER_H__
#define __BSP_SOFT_TIMER_H__


#define SOFT_TIMER_NUM		3		/* 最大 255 */

typedef enum SOFT_TIMER_STATE
{
    SOFT_TIMER_STOPPED = 0,  		/* 停止 */
    SOFT_TIMER_RUNNING = 1, 	 	/* 运行 */
    SOFT_TIMER_TIMEOUT = 2   		/* 超时 */
} SOFT_TIMER_STATE;					/* 软件定时器状态 */

typedef enum SOFT_TIMER_MODE
{
    SOFT_TIMER_MODE_ONE_SHOT = 0,   /* 单次模式 */
    SOFT_TIMER_MODE_PERIODIC = 1,	/* 周期模式 */
} SOFT_TIMER_MODE;					/* 运行模式 */	

typedef void (*soft_timer_callback)(void *argv, unsigned short int argc);


void bsp_soft_timer_init
	(
	void
	);
	
void bsp_soft_timer_start
	(
	unsigned char 		id,
	unsigned char		mode,
	unsigned int		delay,
	soft_timer_callback	callback,		
	void 				*argv,			
	unsigned short int	argc		
	);
	
void bsp_soft_timer_stop
	(
	unsigned char id
	);
	
void bsp_soft_timer_update
	(
	void
	);
	
unsigned char bsp_soft_timer_state_get
	(
	unsigned char id
	);
	
void bsp_soft_timer_nop_callback
	(
	void 				*argv, 
	unsigned short int 	argc
	);


#endif

bsp_soft_timer.c

#include "./soft_timer/bsp_soft_timer.h"

#include <stdio.h>
#include "main.h"


typedef struct stru_soft_timer
{
    unsigned char 		state; 			/* 状态 */
    unsigned char		mode;       	/* 模式 */
	unsigned int 		delay;			/* 定时时间 */
	unsigned int 		end_tick;		/* 到期时间 */
	soft_timer_callback	callback;		/* 回调函数指针 */
	void 				*argv; 			/* 回调函数参数指针 */
	unsigned short int	argc;			/* 回调函数参数个数 */
} stru_soft_timer_t;


static stru_soft_timer_t timer[SOFT_TIMER_NUM];


/* bsp_soft_timer_init:初始化软件定时器 */
void bsp_soft_timer_init
	(
	void
	)
{
	for (int i = 0; i < SOFT_TIMER_NUM; i++)
	{
		timer[i].state 		= SOFT_TIMER_STOPPED;
		timer[i].mode  		= SOFT_TIMER_MODE_ONE_SHOT;
		timer[i].delay		= 0;
		timer[i].end_tick 	= 0;
		timer[i].callback 	= NULL;
		timer[i].argv		= NULL;
		timer[i].argc		= 0;
	}
}

/* bsp_soft_timer_start:开启软件定时器 
 * id			启用的软件定时器编号
 * mode			运行模式
 * delay		定时时间
 * callback		回调函数
 * argv			参数
 * arvc 		参数个数 */
void bsp_soft_timer_start
	(
	unsigned char 		id,
	unsigned char		mode,
	unsigned int		delay,
	soft_timer_callback	callback,		
	void 				*argv,			
	unsigned short int	argc		
	)
{
	assert_param(id < SOFT_TIMER_NUM);
	assert_param(mode == SOFT_TIMER_MODE_ONE_SHOT || mode == SOFT_TIMER_MODE_PERIODIC);
	
	timer[id].state 	= SOFT_TIMER_RUNNING;
	timer[id].mode  	= mode;
	timer[id].delay		= delay;
	timer[id].end_tick 	= HAL_GetTick() + delay;
	timer[id].callback 	= callback;
	timer[id].argv		= argv;
	timer[id].argc		= argc;
}

/* bsp_soft_timer_update:停止软件定时器 
 * id		停止的软件定时器编号 */
void bsp_soft_timer_stop
	(
	unsigned char id
	)
{
	assert_param(id < SOFT_TIMER_NUM);
	
	timer[id].state = SOFT_TIMER_STOPPED;
}
		
/* bsp_soft_timer_update:软件定时器状态更新 */
void bsp_soft_timer_update
	(
	void
	)
{
	for (int i = 0; i < SOFT_TIMER_NUM; i++)
	{
		switch (timer[i].state)
		{
			/* 停止状态 */
			case SOFT_TIMER_STOPPED:
				break;
			
			/* 运行状态 */
			case SOFT_TIMER_RUNNING:
				if (timer[i].end_tick <= HAL_GetTick())
				{
					timer[i].state = SOFT_TIMER_TIMEOUT;
					timer[i].callback(timer[i].argv, timer[i].argc);	/* 调用回调函数 */
				}
				break;
			
			/* 超时状态 */
			case SOFT_TIMER_TIMEOUT:
				if (timer[i].mode == SOFT_TIMER_MODE_ONE_SHOT)
				{
					timer[i].state = SOFT_TIMER_STOPPED;
				}
				else if (timer[i].mode == SOFT_TIMER_MODE_PERIODIC)
				{
					timer[i].state = SOFT_TIMER_RUNNING;
					timer[i].end_tick = HAL_GetTick() + timer[i].delay;
				}
				break;
				
			default:
				break;
		}
		
	}
}

/* bsp_soft_timer_update:获取软件定时器状态
 * id		获取软件定时器编号 */
unsigned char bsp_soft_timer_state_get
	(
	unsigned char id
	)
{
	return timer[id].state;
}

/* soft_timer_nop_callback:空回调函数 */
void bsp_soft_timer_nop_callback
	(
	void 				*argv, 
	unsigned short int 	argc
	)
{
	__NOP();
}
使用例程
// 初始化
bsp_soft_timer_init();
bsp_soft_timer_start(0, SOFT_TIMER_MODE_PERIODIC, 500, bsp_soft_timer_nop_callback, NULL, 0);

// 主函数
while (1)
{
    ...
    bsp_soft_timer_update();
	if (bsp_soft_timer_state_get(0) == SOFT_TIMER_TIMEOUT)
	{
		HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13);		// 翻转指示灯
	} 
    ...
}
参考链接
  • 7
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值