我是靠谱客的博主 土豪诺言,最近开发中收集的这篇文章主要介绍最简单的51单片机软件定时器的编写为什么要使用软件定时器?不说废话,上代码讲解说明:本程序是在学习的时候编写,适当参考网上代码,如涉及到版权问题,可以联系我。,觉得挺不错的,现在分享给大家,希望可以做个参考。
概述
最简单的51单片机软件定时器的编写
- 为什么要使用软件定时器?
- 不说废话,上代码讲解
- main.c
- soft_timer.h
- soft_timer.c
- 说明:本程序是在学习的时候编写,适当参考网上代码,如涉及到版权问题,可以联系我。
为什么要使用软件定时器?
- 定时器在我们单片机编程时必不可少,虽然现在已经有很多单片机的定时器数量功能数量十分的丰富。但是在一些环境下(例如一些系统),总不能一个任务调一个硬件定时器中断吧?那如果有几十个任务呢?
- 所以就有了软件定时器存在的必要。软件定时器的优点在于,数量可以根据用户需求而定,不需要频繁的配置,维护性较高。缺点在于时间误差较大。
但是,对于一些延时要求不是特别高的任务来说,软件定时器无疑是一个不错的选择。 - 我最近学习了一下软件定时器的实现原理,自己在51单片机上面实现了,软件定时器的主要功能(已经可以使用)。
- 初识者,只需阅读本文章,即可知道软件定时器的一个原理,紧接着可以尝试自己去编写一个软件定时器。(希望文章可以帮到你,大佬可以直接划过了,另外大家有什么意见可以在评论区下留言讨论,一个人的思维是有限的)
不说废话,上代码讲解
main.c
读者只需要关心add_soft_timer()以及soft_timer_process()函数
u16 led_cb(void)//led引脚翻转函数
{
static u8 flag=0;
flag=!flag;
Write_GPIO_Value(GPIO2,PIN_5,flag);
return 0;
}
void main(void)
{
GPIO_Init(); //IO口初始化
Timer_Init(); //定时器初始化
Uart_Init(); //串口初始化1
soft_timer_init(); //软件定时器初始化
SET_ALL_IRQ(IRQ_ENABLE); //打开总中断
add_soft_timer(&led_cb,200,FOREVER);//添加一个200ms的软件定时器回调函数
while(1)
{
soft_timer_process();//软件定时器轮询函数
}
}
soft_timer.h
#ifndef __SOFT_TIMER_H
#define __SOFT_TIMER_H
#include "user.h"
#include "timer.h"
#define SOFT_TIMER_NUM 10 //定时器最大个数
/*
1)TIMER_START:记录定时器的状态(无效态、运行态、溢出态);
2)TIMER_MODE:记录定时器时的模式(单次、循环);
3)TIMER_STR:定时器的所有参数都包含在该结构体内;
4)typedef u16 (*timer_cb)(void) :为一个返回值为u16,无形参的函数指针类型,定义新名;
*/
typedef u16 (*timer_cb)(void);
typedef enum {
INVALID=0,//无效态,表示定时器不存在
RUNING, //运行态
TIMEOUT, //超时态
}TIMER_START;
typedef enum {
ONCE = 0, //单次
FOREVER, //循环
}TIMER_MODE;
typedef struct{
u16 cycle; //定时器周期 0~65535 units:100us
u16 tick; //当前计数值 0~65535 units:100us
TIMER_START status; //定时器状态 运行/停止/溢出
TIMER_MODE mode; //定时器模式 1次/无限次
timer_cb cb; //回调函数
}TIMER_STR;
void soft_timer_init(void);
int add_soft_timer(timer_cb *cb,u16 cyc,TIMER_MODE mode);
void soft_timer_process(void);
#endif
soft_timer.c
#include "soft_timer.h"
#include "uart.h"
#include "gpio.h"
//我使用51单片机内存不够,其它芯片无需放在外部存储器
xdata TIMER_STR timer_real[SOFT_TIMER_NUM];//定义结构体数组,10个。用于存放每个定时器的参数
u16 base_timer_cnt;//计数变量
//中断服务,获取时间 :计数单位1ms
void Soft_Timer_Base_Function(void) interrupt 19
{ //1ms自加1,周而复始。溢出后会重0开始继续加
base_timer_cnt++;
}
//初始化定时器时基设置
void soft_timer_init(void)
{
memset(&timer_real,0,sizeof(timer_real)); //结构体清除,就是参数全部清0
Timer3Init(); //初始化定时器
}
//获取base_timer_cnt计数器的值,该值在定时器中断内不断加1
u16 get_cur_tick(void)
{
return base_timer_cnt;
}
//添加定时器
int add_soft_timer(timer_cb cb,u16 cyc,TIMER_MODE mode) //回调、定时周期、定时模式
{
u8 i;
u16 cur_tick=get_cur_tick();//获取计数值
//遍历数组,查找是否存在空位,可以被插
for(i=0;i<SOFT_TIMER_NUM;i++)
{
if(INVALID==timer_real[i].status)
{
//寻找位置插空
timer_real[i].cycle = cyc;
timer_real[i].tick = cur_tick+cyc;
timer_real[i].cb = cb; //添加回调函数
timer_real[i].mode = mode;
timer_real[i].status= RUNING;//添加后进入运行态
return 0;
}
}
return -1;//没有空位置了
}
//轮询处理:核心函数
void soft_timer_process(void)
{
u8 i;
u16 get_tick=get_cur_tick();//获取当前计数值
int diff;
for(i=0;i<SOFT_TIMER_NUM;i++)//数组的每一项遍历
{
if(INVALID==timer_real[i].status)continue;//此定时器不存在,则结束本次循环,开始新循环
if(RUNING==timer_real[i].status)//如果,定时器i,处于运行态
{
/*
此处,我定义了一个int类型的diff变量,表示差值
没有直接比较base_timer_cnt与timer_real[i].tick值的原因在于
base_timer_cnt变量存在溢出的情况(就是到达65535后,接着变为0)
那么此时比较大小显然是不行的。
而用差值原因在于,a-b实际上是被当做a+(-b)来处理的。
那么即使是存在变量溢出,最终得到的差值也是理想差值。(具体读者可以去查补码的知识)
*/
diff=get_tick-timer_real[i].tick;//int类型
if(diff > 0)//溢出了
{
timer_real[i].status=TIMEOUT;//标记溢出
}
}
if(TIMEOUT==timer_real[i].status)//如果,定时器i被标记溢出,则进行如下处理
{
timer_real[i].cb(); //执行回调任务(执行我们的任务)
if(ONCE==timer_real[i].mode)//单次模式
{
memset(&timer_real[i],0,sizeof(TIMER_STR));//清除定时器i的结构体
}
else if(FOREVER==timer_real[i].mode)//循环模式
{
timer_real[i].status=RUNING;//状态跳转会运行态
timer_real[i].tick=base_timer_cnt+timer_real[i].cycle;//记录下一个周期值
}
}
}
}
//定时器删除,不一定使用到
int delete_soft_timer(u8 idex)
{
//判断是否存在
if(INVALID==timer_real[idex].status)
{
memset(&timer_real[idex],0,sizeof(TIMER_STR)); //结构体清除
}
return -1;//定时器不存在,所以无法删除
}
说明:本程序是在学习的时候编写,适当参考网上代码,如涉及到版权问题,可以联系我。
最后
以上就是土豪诺言为你收集整理的最简单的51单片机软件定时器的编写为什么要使用软件定时器?不说废话,上代码讲解说明:本程序是在学习的时候编写,适当参考网上代码,如涉及到版权问题,可以联系我。的全部内容,希望文章能够帮你解决最简单的51单片机软件定时器的编写为什么要使用软件定时器?不说废话,上代码讲解说明:本程序是在学习的时候编写,适当参考网上代码,如涉及到版权问题,可以联系我。所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复