【裸板驱动】定时器模块分享

一、源代码

首先是mod_timer.c文件

/*
文件功能:
	提供统一的时间节点
用法介绍:
	1.使用Mod_Timer_Init函数进行相关变量初始化
	2.将Mod_Timer_1ms_Loop放于1ms循环的中断中
	3.通过Mod_Timer_Set_AnyTf设置自由标志的高低电平时间
作者:
	春风催雪
	
更新记录:
	2021-11-6>>V0.1:初次使用
	2021-12-24>>V0.2:添加任意电平计数的当前电平标志
	2022-9-7>>V0.3:将函数Mod_Timer_Set_AnyTf的返回,修改为0或-1
*/
#include "include.h"  //头文件统一管理文件

MODTIMER ModTimer;

/*
	描述:初始化结构体变量
*/
void Mod_Timer_Init(void)
{
	ModTimer.Timer1msTf = 0;  //1ms标志
	
	ModTimer.Timer2msTf = 0;  //2ms标志
	ModTimer.Timer2msCnt = 1;  //2ms计数
	
	ModTimer.Timer5msTf = 0;  //5ms标志
	ModTimer.Timer5msCnt = 2;  //5ms计数
	
	ModTimer.Timer10msTf = 0;  //10ms标志
	ModTimer.Timer10msCnt = 3;  //10ms计数
	
	ModTimer.Timer50msTf = 0;  //50ms标志
	ModTimer.Timer50msCnt = 4;  //50ms计数
	
	ModTimer.Timer100msTf = 0;  //100ms标志
	ModTimer.Timer100msCnt = 5;  //100ms计数
	
	ModTimer.Timer200msTf = 0;  //200ms标志
	ModTimer.Timer200msCnt = 6;  //200ms计数
	
	ModTimer.Timer500msTf = 0;  //500ms标志
	ModTimer.Timer500msReverse = 0;  //500ms取反
	ModTimer.Timer500msCnt = 7;  //500ms计数
	
	ModTimer.Timer1sTf = 0;  //1s标志
	ModTimer.Timer1sCnt = 8;  //1s计数
	
	ModTimer.TimerAnyTf = 0;  //任意电平计数重置标志
	ModTimer.TimerAnyCnt = 9;  //任意电平计数
	ModTimer.TimerAnyHighMs = 1;  //任意电平标志的置高时间
	ModTimer.TimerAnyLowMs = 1;  //任意电平标志的置低时间
	ModTimer.TimerAnyLevel = 0;  //任意电平的当前电平
}

/*
	描述:1ms循环执行函数,此函数需要放入1ms的中断中
*/
void Mod_Timer_1ms_Loop(void)
{
	ModTimer.Timer1msTf = 1;
	
	ModTimer.Timer2msCnt++;
	if(ModTimer.Timer2msCnt > 2)
	{
		ModTimer.Timer2msTf = 1;
		ModTimer.Timer2msCnt = 1;
	}
	
	ModTimer.Timer5msCnt++;
	if(ModTimer.Timer5msCnt > 5)
	{
		ModTimer.Timer5msTf = 1;
		ModTimer.Timer5msCnt = 1;
	}
	
	ModTimer.Timer10msCnt++;
	if(ModTimer.Timer10msCnt > 10)
	{
		ModTimer.Timer10msTf = 1;
		ModTimer.Timer10msCnt = 1;
	}
	
	ModTimer.Timer50msCnt++;
	if(ModTimer.Timer50msCnt > 50)
	{
		ModTimer.Timer50msTf = 1;
		ModTimer.Timer50msCnt = 1;
	}
	
	ModTimer.Timer100msCnt++;
	if(ModTimer.Timer100msCnt > 100)
	{
		ModTimer.Timer100msTf = 1;
		ModTimer.Timer100msCnt = 1;
	}
	
	ModTimer.Timer200msCnt++;
	if(ModTimer.Timer200msCnt > 200)
	{
		ModTimer.Timer200msTf = 1;
		ModTimer.Timer200msCnt = 1;
	}
	
	ModTimer.Timer500msCnt++;
	if(ModTimer.Timer500msCnt > 500)
	{
		ModTimer.Timer500msTf = 1;
		ModTimer.Timer500msReverse = (ModTimer.Timer500msReverse == 1)? 0:1;
		ModTimer.Timer500msCnt = 1;
	}
	
	ModTimer.Timer1sCnt++;
	if(ModTimer.Timer1sCnt > 1000)
	{
		ModTimer.Timer1sTf = 1;
		ModTimer.Timer1sCnt = 1;
	}
	
	ModTimer.TimerAnyCnt++;
	if(ModTimer.TimerAnyCnt > (ModTimer.TimerAnyHighMs + ModTimer.TimerAnyLowMs))  //大于总时间归零
	{
		ModTimer.TimerAnyTf = 1;
		ModTimer.TimerAnyCnt = 1;
	}
	if(ModTimer.TimerAnyCnt > ModTimer.TimerAnyHighMs)  //判断高低电平
	{
		ModTimer.TimerAnyLevel = 0;
	}
	else
	{
		ModTimer.TimerAnyLevel = 1;
	}
}

/*
	描述:设置自由时间标志的置位时间和清空时间
	Hight:ModTimer.TimerAnyTf的置位时间,单位ms,范围 1~0x7fffffff
	Low:ModTimer.TimerAnyTf的清空时间,单位ms,范围 1~0x7fffffff
	返回:0表示设置成功,-1表示设置失败
*/
int8_t Mod_Timer_Set_AnyTf(uint32_t Hight, uint32_t Low)
{
	if((Hight == 0) || (Hight > 0x7fffffff) || (Low == 0) || (Low > 0x7fffffff))  //确保设置数据不会超范围
	{
		return -1;
	}
	
	ModTimer.TimerAnyHighMs = Hight;
	ModTimer.TimerAnyLowMs = Low;
	ModTimer.TimerAnyCnt = 1;
	ModTimer.TimerAnyTf = 0;
	ModTimer.TimerAnyLevel = 0;
	return 0;
}


其次是mod_timer.h文件

#ifndef __MOD_TIMER_H__
#define __MOD_TIMER_H__


typedef struct MODTIMERSTRUCT
{
	uint8_t Timer1msTf;  //1ms标志
	
	uint8_t Timer2msTf;  //2ms标志
	uint8_t Timer2msCnt;  //2ms计数
	
	uint8_t Timer5msTf;  //5ms标志
	uint8_t Timer5msCnt;  //5ms计数
	
	uint8_t Timer10msTf;  //10ms标志
	uint8_t Timer10msCnt;  //10ms计数
	
	uint8_t Timer50msTf;  //50ms标志
	uint8_t Timer50msCnt;  //50ms计数
	
	uint8_t Timer100msTf;  //100ms标志
	uint8_t Timer100msCnt;  //100ms计数
	
	uint8_t Timer200msTf;  //200ms标志
	uint8_t Timer200msCnt;  //200ms计数
	
	uint8_t Timer500msTf;  //500ms标志
	uint8_t Timer500msReverse;  //500ms取反
	uint16_t Timer500msCnt;  //500ms计数
	
	uint8_t Timer1sTf;  //1s标志
	uint16_t Timer1sCnt;  //1s计数
	
	uint8_t TimerAnyTf;  //任意电平计数重置标志
	uint8_t TimerAnyCnt;  //任意电平计数
	uint32_t TimerAnyHighMs;  //任意电平的置高时间
	uint32_t TimerAnyLowMs;  //任意电平的置低时间
	uint8_t TimerAnyLevel;  //任意电平的当前电平
}MODTIMER;


extern MODTIMER ModTimer;


extern void Mod_Timer_Init(void);
extern void Mod_Timer_1ms_Loop(void);
extern int8_t Mod_Timer_Set_AnyTf(uint32_t Hight, uint32_t Low);

#endif


二、功能描述

1、一般情况下,我们的裸板程序是怎么写的呢?

a、刚开始学习的时候,我们会把所有的功能塞到主函数中执行,把需要定时执行的功能放到定时器中执行。

b、然后随着学习的加深,学会了把功能打包成子函数,这样增加了代码的可读性。

c、再后来,知道了定时器可能因为执行代码太多导致阻塞,所以学会了使用时间标志位(定时器中置位标志,主循环检测对应标志位然后执行对应代码)。

d、使用了标志位之后,就会发现,主循环中的函数并不是都需要一直执行,考虑到CPU占用率,于是给所有的函数都加了标志位。

经过上面一番操作,于是我们的裸板程序结构就变成了,定时器中定时给各个时间标志置位,然后在主循环中循环检测对应的标志,执行对应的函数。

2、今天分享的“定时器模块”,就是实现这种程序结构的一个功能文件。经过相关的配置之后,在主函数中就可以愉快的定时执行函数了。

三、用法介绍

1、第一步,当然是把文件添加到工程里面,然后配置对应的加载。

2、第二步,将函数Mod_Timer_Init放置到初始化的位置,对结构体里面的数据进行初始化。

3、第三步,借助定时器,将函数Mod_Timer_1ms_Loop放置到1ms的循环中。

4、第四步,如果有需要,可以使用函数Mod_Timer_Set_AnyTf,设置一个高低电平定时变化的变量。用来应对特殊的需求。

5、第五步,这时候,在main主循环中,只需要如下使用。

/*10ms例子*/
if(ModTimer.Timer10msTf != 0)
{
	...  //这里是需要定时执行的代码

	ModTimer.Timer10msTf = 0;
}

四、重点介绍

1、如果仔细看了代码,就会发现500ms定时执行还有一个变量Timer500msReverse,它其实是一个定时反转的变量,因为很多的小家电需要定时或者读秒的功能,有了它就不需要单独再去处理。

2、任意电平功能,实际上是定义了两个计数变量,一个代表高电平,另一个代表低电平。两者之和是一个循环,功能相对比较简单。

博客内容均系原创,未经允许严禁转载!
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇