最简单的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();                                    //串口初始化1soft_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:100usu16 tick;            //当前计数值     0~65535 units:100usTIMER_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));  //结构体清除,就是参数全部清0Timer3Init();                                //初始化定时器
}//获取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单片机软件定时器的编写相关推荐

  1. 【51单片机】定时器/计数器的工作原理和结构(一)

    [51单片机]定时器/计数器的工作原理和结构 回看下单片机中断系统内部结构: 分析内部中断触发: 先看图 TCON:和外部中断相比少了IT位设置触发方式 :1跳沿触发 0电平触发:此处我的理解是:就好 ...

  2. 51单片机学习--定时器--中断--串口通信

    51单片机学习–定时器–中断–串口通信 定时器–中断–串口通信 中断分类 定时器中断 外部中断 串口中断 基本概念 对于单片机来讲, 中断是指 CPU 在处理某一事件 A 时, 发生了另一事件 B, ...

  3. 51单片机计算定时器初值

    51单片机计算定时器初值 前言 理论分析 工作方式寄存器 TMOD GATE 门控位 C/T' 计数器模式和定时器模式选择位 M1 M0 工作方式选择位 定时器/计数器控制寄存器 TCON TCON补 ...

  4. 关于用51单片机内部定时器实现时钟和闹钟功能的概述

    关于用51单片机内部定时器实现时钟和闹钟功能的概述 仅个人观点,欢迎大家相互学习和讨论 STC89C52单片机,内部配置了三个定时器,T0\T1\T2,其中T2定时器我们几乎不用,或者说很少用到.我们 ...

  5. 单片机软件定时器的使用方法

    单片机软件定时器的使用方法 特别声明:文章是原创但是本文讲述的思想是在国外的开源代码中借鉴的 初学者在编写单片机程序时经常会用到延时函数,但是当系统逐步复杂以后(没有复杂到使用操作系统)延时会因为延时 ...

  6. (六)51单片机基础——定时器

    定时器介绍:51单片机的定时器属于单片机的内部资源,其电路的连接和运转均在单片机内部完成. 定时器主要作用: 用于计时系统,可实现软件计时,或者使程序每隔一固定时间完成一项操作. 替代长时间的Dela ...

  7. 51单片机之定时器\计数器的工作原理

    51单片机之定时器\计数器的工作原理 定时器/计数器的结构: 何时处于计数器方式?何时处于定时器方式? TCON和TMOD特殊功能寄存器: 定时器/计数器工作方式: 方式0:13位的定时器/计数器 方 ...

  8. 三菱梯形图转换c语言软件,三菱梯形图转51单片机软件使用程序超过100步又要使用软件的朋友.pdf...

    三菱梯形图转51单片机软件使用程序超过100步又要使用软件的朋友 三菱梯形图转51单片机软件使用 希望这个软件 能降低你的电气控制成本. 1:运行三菱软件,选择PLC型号为FX1N,画好梯形图并保存. ...

  9. 51单片机用定时器0实现流水灯

    51单片机用定时器0实现流水灯的代码如下,用P1口接led灯,代码如下都有注释就不具体解释了,英语不怎么好,有的地方将就一下喽,本次主要讲一下P1口怎么赋值.原先写的都是用查表来移位的,个人感觉不怎么 ...

  10. 51单片机内部定时器/计数器实验

    51单片机内部定时器/计数器实验 一.实验内容 使用MCS-51内部定时/计数器,定时1秒钟,CPU运用定时中断方式,实现每1秒钟输出状态发生一次反转,即发光管每隔1秒钟亮一次(P1.7接LED). ...

最新文章

  1. Oracle数据库表导出和导入csv文件操作
  2. Java 基础入门随笔(1) JavaSE版——java语言三种技术架构
  3. go基本语法:channel未关闭遍历结束后会报错deadlock
  4. python使用matplotlib绘制k线图
  5. PHP-CGI, FastCGI, PHP-FPM的关系和区别
  6. 32位hex转浮点 python_python——int()、hex()、oct()、bin()、float()数值类型转换函数
  7. ZigBee网络架构详解
  8. matlab界area_Matlab的数据科学界
  9. java安装和环境配置
  10. 动态规划实战篇--斐波那契数列
  11. 完全卸载VS 2015各版本
  12. OpenCV——LBP特征
  13. JavaScript笔记
  14. 生物医学数据统计分析-回归分析
  15. 计算机桌面壁纸被锁定,Win10桌面壁纸被锁定无法修改咋办? win10官网
  16. Windows7 64位安装EPLAN P8 2.6教程
  17. win8计算机休眠的区别,win8系统的休眠和睡眠有什么区别?如何用?
  18. opencv切割视频:把长视频切割成固定时间的短视频
  19. EasyExcel 固定(冻结)单元格
  20. win10+ubuntu双系统之三步彻底删除ubuntu系统

热门文章

  1. Prophet(预言者)facebook时序预测----论文总结以及调参思路
  2. (爱斯维尔期刊:遇到问题已解决) 使用elsarticle-harv的style引文格式时报错 mand\Nat@force@numbers{}\NAT@force@numbers
  3. TCGA数据库ensembl id 转为 gene Symbol,提取出需要的RNA种类表达谱列表信息
  4. 分享-IE游览器升级工具
  5. C语言 AES算法 加密解密
  6. 一些服务器常见漏洞的修复方法
  7. 扑克牌游戏“快算24”算法
  8. Kruise Rollout:灵活可插拔的渐进式发布框架
  9. mysql横切竖切_MySQL常用操作 - cheney-f的个人空间 - OSCHINA - 中文开源技术交流社区...
  10. 利用pandas进行数据分析