历史上的今天
返回首页

历史上的今天

今天是:2025年01月22日(星期三)

正在发生

2020年01月22日 | 51单片机基于一个定时器实现多个软件定时器

2020-01-22 来源:51hei

软件定时器是用程序模拟出来的定时器,可以由一个硬件定时器模拟出成千上万个软件定时器,这样程序在需要使用较多定时器的时候就不会受限于硬件资源的不足,这是软件定时器的一个优点,即数量不受限制。但由于软件定时器是通过程序实现的,其运行和维护都需要耗费一定的CPU资源,同时精度也相对硬件定时器要差一些。在RTOS等操作系统中,都带有软件定时器,原理大同小异。典型的实现方法是:通过一个硬件定时器产生固定的时钟节拍,每次硬件定时器中断到,就对一个全局的时间标记加一,每个软件定时器都保存着到期时间,程序需要定期扫描所有运行中的软件定时器,将各个到期时间与全局时钟标记做比较,以判断对应软件定时器是否到期,到期则执行相应的回调函数,并关闭该定时器

程序如下,通过一个硬件定时器产生固定的时钟节拍,用4个LED演示效果:

#include "reg51.h"

//#include "STC89C5xRC.h"


sbit LED1=P1^0;

sbit LED2=P1^1;

sbit LED3=P1^2;

sbit LED4=P1^3;


unsigned char softTimer_8s_flag = 0;        //8s定时器flag


#define NULL        0


#define SOFT_TIMER_MAX                4                //定时器个数


//定义定时器ID

#define ID_1S_LED_TASK                0

#define ID_2S_LED_TASK                1

#define ID_4S_LED_TASK                2

#define ID_8S_LED_TASK                3


typedef void (*pFun)(void);                //callback 函数指针类型


typedef enum tmrMode {

        MODE_ONE_SHOT = 0,       //单次模式

        MODE_PERIODIC,           //周期模式

} tmrMode;


typedef enum tmrState {

        SOFT_TIMER_STOPPED = 0,  //停止

        SOFT_TIMER_RUNNING,      //运行

        SOFT_TIMER_TIMEOUT,      //超时

        SOFT_TIMER_WAITING                 //等待

} tmrState;


typedef struct softTimer {

        unsigned char state;           //状态

        unsigned char mode;            //模式

        unsigned int  period;          //定时周期

        unsigned int  count;                   //定时计数用

        pFun callback;                                   //定时器回调函数

} softTimer;


//定时器结构数组

softTimer softTimerList[SOFT_TIMER_MAX] = {0};


//设定定时器

void softTimer_Creat(unsigned char id,tmrMode mode,unsigned int interval,pFun cb)

{

        softTimerList[id].mode = mode;

        softTimerList[id].period = interval;

        softTimerList[id].count = 0;

        softTimerList[id].callback = cb;

        softTimerList[id].state = SOFT_TIMER_STOPPED;

}


//打开定时器

void softTimer_Start(unsigned int id)

{

        softTimerList[id].state = SOFT_TIMER_RUNNING;

}


//停止定时器

void softTimer_Stop(unsigned int id)

{

        softTimerList[id].state = SOFT_TIMER_STOPPED;

}


//清除定时器状态(用于执行事件后手动清除定时器状态)

void softTimer_Clr(unsigned int id)

{

        if(softTimerList[id].mode == MODE_ONE_SHOT){

                softTimerList[id].state = SOFT_TIMER_STOPPED;

        }else{

                softTimerList[id].state = SOFT_TIMER_RUNNING;

        }

}


//获取定时器状态

unsigned char softTimer_GetState(unsigned int id)

{

        return softTimerList[id].state;

}


void softTimer_Update(void)        //更新定时器状态,在硬件定时器中1ms调用一次

{

        unsigned char id;

        for(id = 0 ;id <= SOFT_TIMER_MAX ; id++ ){

                switch (softTimerList[id].state){

                        case SOFT_TIMER_STOPPED:

                                break;

                        case SOFT_TIMER_RUNNING:

                                if(softTimerList[id].count < softTimerList[id].period){

                                        softTimerList[id].count ++;

                                }else{

                                        softTimerList[id].count = 0;

                                        softTimerList[id].state = SOFT_TIMER_TIMEOUT;

                                        softTimerList[id].callback();

                                }

                                break;

                        case SOFT_TIMER_TIMEOUT:

                                if(softTimerList[id].mode == MODE_ONE_SHOT) {

                                  softTimerList[id].state = SOFT_TIMER_STOPPED;

                                } else {

                                  softTimerList[id].count ++;

                                  softTimerList[id].state = SOFT_TIMER_RUNNING;

                                }

                                break;

                        default:        //state error

                          break;

                }

        }

}


void Timer0Init(void)                //1毫秒@12.000MHz

{

        TMOD = 0x00;                //设置定时器模式

        TL0 = 0xC0;                        //设置定时初值

        TH0 = 0xE0;                        //设置定时初值

        EA = 1;

        ET0 = 1;

        TR0 = 1;                

}


void Interrupt() interrupt 1

{

        TL0 = 0xC0;                //重载定时初值

        TH0 = 0xE0;                //重载定时初值

        

        softTimer_Update();        //1ms更新一次softTimer

}


void Delayms(unsigned int ms)                //@12.000MHz

{

        unsigned char i, j;

        while(--ms) {

                i = 2;

                j = 239;

                do {

                        while (--j);

                } while (--i);

        }

}


void softTimer_1s_cb(void)

{

        LED1 = ~LED1;

}


void softTimer_2s_cb(void)

{

        LED2 = ~LED2;

}


void softTimer_4s_cb(void)

{

        LED3 = ~LED3;

}


void softTimer_8s_cb(void)

{

        softTimer_8s_flag = 1;

}


void main()        //主函数

{

        LED1=0;LED2=0;LED3=0;LED4=0;

        

        //配置相应定时器

        softTimer_Creat(ID_1S_LED_TASK,MODE_PERIODIC,1000,softTimer_1s_cb);

        softTimer_Creat(ID_2S_LED_TASK,MODE_PERIODIC,2000,softTimer_2s_cb);

        softTimer_Creat(ID_4S_LED_TASK,MODE_ONE_SHOT,4000,softTimer_4s_cb);

        softTimer_Creat(ID_8S_LED_TASK,MODE_PERIODIC,8000,softTimer_8s_cb);

        

        //打开相应定时器

        softTimer_Start(ID_1S_LED_TASK);

        softTimer_Start(ID_2S_LED_TASK);

        softTimer_Start(ID_4S_LED_TASK);

        softTimer_Start(ID_8S_LED_TASK);

        

        Timer0Init();//初始化定时器0

        while(1) {

                

                //尽量少用延时,如果事件处理耗时较长,应在main中执行

                if(softTimer_8s_flag == 1)

                {

                        LED4=~LED4;

                        Delayms(200);//模拟耗时事件

推荐阅读

史海拾趣

Hantronix公司的发展小趣事

随着全球对环保问题的日益关注,HANBIT Electronics积极响应,将绿色生产纳入公司发展战略。2020年,公司投资建立了绿色生产线,采用环保材料和清洁能源进行生产,实现了生产过程中的节能减排。同时,公司还推出了多款环保型电子产品,满足消费者对绿色、低碳生活的需求。这一举措不仅提升了公司的品牌形象,也为其在可持续发展的道路上赢得了更多机遇。

DRS Technologies公司的发展小趣事

在21世纪初,DRS接受了价值16亿美元的合同,为美国陆军和海军陆战队的部队现代化计划制造加固式计算机。这一合同不仅展示了DRS在军事领域的实力,也进一步巩固了其在全球电子行业的地位。DRS提供的“探索者”MP加固式轻便多平台工作站,为数字战场提供了强大的支持。

Elpida Memory公司的发展小趣事

尽管Elpida Memory已经不复存在,但其在DRAM领域的技术和经验仍然对全球半导体产业产生了深远的影响。Elpida Memory在技术研发、生产管理和市场营销等方面的经验,为后来的半导体企业提供了宝贵的借鉴和参考。同时,Elpida Memory的失败也提醒了半导体企业需要时刻保持警惕和创新精神,以应对日益激烈的市场竞争和技术变革。

BRIGHT公司的发展小趣事

除了无线耳机和太阳能领域,BRIGHT公司还在健康技术领域取得了重要的突破。他们成功筹集了60万美元的资金,用于推动健康技术的持续增长和扩张。这笔资金使得BRIGHT公司能够在其成功的基础上,进一步研发和推广基于科学的认知健康解决方案。他们的产品,如40赫兹灯,无需医生处方即可普遍使用,为广大消费者提供了更加便捷和科学的健康管理方式。

Fujisoku Corporation公司的发展小趣事

在电子废弃物处理成为全球关注焦点的背景下,“未来电子”积极倡导绿色生产和循环经济理念。公司投入大量资源研发环保型电子产品,并建立了完善的电子废弃物回收处理体系。通过技术创新和科学管理,“未来电子”实现了生产过程中的节能减排和废弃物的有效回收利用,赢得了社会各界的广泛赞誉。这一举措不仅提升了公司的社会形象,还为公司的可持续发展奠定了坚实基础。

DLP Design公司的发展小趣事

DLP创新设计公司,一家专注于DLP技术应用的企业,通过精准的市场定位和灵活的市场策略,成功在电子行业中脱颖而出。公司深入了解消费者需求,针对不同市场推出差异化产品。同时,DLP创新积极寻求合作伙伴,通过渠道拓展和品牌建设,逐渐提高了市场占有率。其独特的商业模式和敏锐的市场洞察力,使DLP创新在激烈的市场竞争中保持了稳健的发展。

问答坊 | AI 解惑

电子电路设计与实践

初学者可以拿去参考参考…

查看全部问答>

protelDXP2004原理图修改元件参数有什么快速方法

protelDXP2004原理图修改元件参数有什么快速方法呀。一个一个改好麻烦呀。:L…

查看全部问答>

基于MSP430 单片机高精度温度测量的补偿方法

用MSP430P315 单片机的A/D 转换器,实现阻性温度传感器的电阻检测;用查表和线性插值结合的方法,简化标度变换的算法结构。对电池电压的降低进行补偿的同时分析补偿电阻的精度对温度检测的影响。 …

查看全部问答>

软件工程师的职位规划

/************************************************ *技术直接转销售还是先转技术支持再转销售好呢? ************************************************/ 我是09年毕业的,毕业的时候,是在一家医疗器材公司工作。 最近换了一家公司,是搞 ...…

查看全部问答>

请教一点关于并口驱动开发的问题

老师让做一个dsp和pc通过并口epp通信的东西,在xp下对并口操作是不是要写个驱动?老板让我用WinDriver,我想问问关于并口开发要怎样调试呢?以前没有做过关于并口通信东西,所以想请问各位老大,希望能给指点一下…

查看全部问答>

请问一下

我的程序 无法进入中断程序 可能是什么原因? 我是用的下降沿有效啊…

查看全部问答>

请教evc中如何快速移动图片

在Wince中添加一个较大的位图,设想有一个相对较小的取景框,当这个框快速移动时,我想显示屏幕上位图移动的动画效果。我在evc中代码如下:          CBitmap m_bitmap;         BITMAP bm; ...…

查看全部问答>

帮我下一个外文文献

Kaiser, J.F., Nonrecursive digital filter design using the I0-sinh window function, Proceedings of the 1974 IEEE International Symposium on Circuits and Systems (1974) 请发送邮件到donghongyong@live.cn …

查看全部问答>

uboot怎样向kenerl传递一个物理地址

现在uboot中有个物理需要传到kernel中! 我该在uboot怎样做?请各位大虾指点下!!谢谢…

查看全部问答>

(北京)迎接Linux时代的到来

4月21日(周六)东方标准特邀请嵌入式软件仿真开源(SkyEye)项目核心成员、AKA 嵌入式小组成员康烁,为大家做《利用SkyEye进行操作系统分析及SkyEye的最新进展》的讲座。 康烁--作为自由软件爱好者,精通嵌入式系统移植,驱动开发,多年嵌入式开发 ...…

查看全部问答>