当前位置:   article > 正文

MCU多组软件定时器的实现

MCU多组软件定时器的实现

结构体定义

#define TMR_COUNT 4 /* 软件定时器的个数 (定时器 ID 范围 0 - 3) */
typedef enum
{
TMR_ONCE_MODE = 0, /* 一次工作模式 */
TMR_AUTO_MODE = 1 /* 自动定时工作模式 */
}TMR_MODE_E;
/* 定时器结构体,成员变量必须增加__IO 即 volatile,因为这个变量在中断和主程序中同时被访问,
有可能造成编译器错误优化。
*/
typedef struct
{
volatile uint8_t Mode; /* 计数器模式,1 次性 */
volatile uint8_t Flag; /* 定时到达标志 */
volatile uint32_t Count; /* 计数器 */
volatile uint32_t PreLoad; /* 计数器预装值 */
}SOFT_TMR;
/* 定于软件定时器结构体变量 */
static SOFT_TMR s_tTmr[TMR_COUNT];
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

初始化

void bsp_InitTimer(void)
 {
	uint8_t i;

	 /* 清零所有的软件定时器 */
	 for (i = 0; i < TMR_COUNT; i++)
	 {
	 s_tTmr[i].Count = 0;
	 s_tTmr[i].PreLoad = 0;
	 s_tTmr[i].Flag = 0;
	 s_tTmr[i].Mode = TMR_ONCE_MODE; /* 缺省是 1 次性工作模式 */
	 }

 /*
23. 配置 systic 中断周期为 1ms,并启动 systick 中断。
24.
25. SystemCoreClock 是固件中定义的系统内核时钟,对于 STM32H7,一般为 400MHz
26.
27. SysTick_Config() 函数的形参表示内核时钟多少个周期后触发一次 Systick 定时中断.
28. -- SystemCoreClock / 1000 表示定时频率为 1000Hz, 也就是定时周期为 1ms
29. -- SystemCoreClock / 500 表示定时频率为 500Hz, 也就是定时周期为 2ms
30. -- SystemCoreClock / 2000 表示定时频率为 2000Hz, 也就是定时周期为 500us
31.
32. 对于常规的应用,我们一般取定时周期 1ms。对于低速 CPU 或者低功耗应用,可以设置定时周期为 10ms
33. */
	SysTick_Config(SystemCoreClock / 1000);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

单次定时器的创建

void bsp_StartTimer(uint8_t _id, uint32_t _period)
{
	if (_id >= TMR_COUNT)
	{
		while(1); 
	}

	DISABLE_INT();  			/* 关中断 */

	s_tTmr[_id].Count = _period;		/* 实时计数器初值 */
	s_tTmr[_id].PreLoad = _period;		/* 计数器自动重装值,仅自动模式起作用 */
	s_tTmr[_id].Flag = 0;				/* 定时时间到标志 */
	s_tTmr[_id].Mode = TMR_ONCE_MODE;	/* 1 次性工作模式 */

	ENABLE_INT();  				/* 开中断 */
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

自动定时器创建

void bsp_StartAutoTimer(uint8_t _id, uint32_t _period)
{
	if (_id >= TMR_COUNT)
	{
		while(1); 
	}

	DISABLE_INT();  		/* 关中断 */

	s_tTmr[_id].Count = _period;		
	s_tTmr[_id].PreLoad = _period;		
	s_tTmr[_id].Flag = 0;				
	s_tTmr[_id].Mode = TMR_AUTO_MODE;

	ENABLE_INT();  			
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

停止定时器

void bsp_StopTimer(uint8_t _id)
{
	if (_id >= TMR_COUNT)
	{
	/* 打印出错的源代码文件名、函数名称 */
	 while(1); /* 参数异常,死机等待看门狗复位 */
	}
	
	DISABLE_INT(); /* 关中断 */
	
	s_tTmr[_id].Count = 0; /* 实时计数器初值 */
	s_tTmr[_id].Flag = 0; /* 定时时间到标志 */
	s_tTmr[_id].Mode = TMR_ONCE_MODE; /* 自动工作模式 */
	ENABLE_INT(); /* 开中断 */
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

定时器到时间返回1

uint8_t bsp_CheckTimer(uint8_t _id)
 {
	 if (_id >= TMR_COUNT)
		{
		 return 0;
		}
	if (s_tTmr[_id].Flag == 1)
	{
		s_tTmr[_id].Flag = 0;
		 return 1;
	}
	 else
	{
	 return 0;
	}
 }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

滴答定时器中断计数减一

static void bsp_SoftTimerDec(SOFT_TMR *_tmr)
{
	if (_tmr->Count > 0)
	{

		if (--_tmr->Count == 0)
		{
			_tmr->Flag = 1;

			if(_tmr->Mode == TMR_AUTO_MODE)
			{
				_tmr->Count = _tmr->PreLoad;
			}
		}
	}
}

void SysTick_Handler(void)
{
	for (i = 0; i < TMR_COUNT; i++)
	{
		bsp_SoftTimerDec(&s_tTmr[i]);
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

总结

本篇通过滴答定时器中断实现了一个方便可移植的多组软件定时器,主要借鉴于安富莱-V7开发板bsp文档,供个人学习用。

声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号