历史上的今天

今天是:2024年08月31日(星期六)

2018年08月31日 | 单片机软件定时器的使用方法

发布者:JoyousJourney 来源: eefocus关键字:单片机  软件定时器  使用方法 手机看文章 扫描二维码
随时随地手机看文章

特别声明:文章是原创但是本文讲述的思想是在国外的开源代码中借鉴的


初学者在编写单片机程序时经常会用到延时函数,但是当系统逐步复杂以后(没有复杂到使用操作系统)延时会因为延时降低MCU的利用率,更严重的会影响系统中的“并行”操作例如一个既有按键又有蜂鸣器的系统中,如果要求按下按键发出不同的声音,每次发声时间在1秒-2秒之间, 如果用延时来做代码很简单:


//蜂鸣器发出“哔-哔-哔”声音时间约1s

void BeepFuction(void)

{

  unsigned char i;

  for(i=0;i<3;i=++)

  {

    BeepEn(); //开启蜂鸣器

    Delayms(220);//延时220ms

    BeepDis();//关闭蜂鸣器  

    Delayms(110);//延时110ms  

  }

}


当这段代码执行时MCU不可能同时处理按键检查程序因为它大部分时间在执行Delayms()函数中的nop指令,这样就不可能去执行检查按键了(不使用中断时),如果把程序改成流程形式的写法则结果会大为不同,下面先介绍一下基本原理。


我们都知道一般的定时器为16位或8位循环计数,例如对于16位的计数器当计数器数值从0增加到65535时再加一就会回到0那么我们来比较下面两种情况(不考虑计数器在记录当前时刻T后再次回到或超过T这种情况我暂且称它为“压圈”): 

情况1: 

T1时刻计数器数值为300 

T2时刻计数器数值为400 

则T1时刻到T2为100个计数单位。 

这段时间差也为100个计数单位。 

情况2: 

T1时刻计数器数值为65535 

T2时刻计数器数值为99 

则T1到T2 可以算出为65535到0的1个计数单位再加上 0到99的99个计数单位总共为100个计数单位。 

所以时间差还是100个计数单位。 

在C语言中如果使用两个无符号数作减法会得到如下结果:99-65535=100,这个很好理解就和10进制的借位一样只不过借位后不用管高位了也就相当于99+65536-65535结果是100了,当然这些前提条件都是计数器不会出现“压圈”。 

有了上面对定时器的了解就可以从新写这个Beep函数了


//蜂鸣器发出“哔-哔-哔”声音时间约1s

bit BeepFlag = 0;//蜂鸣流程忙标志位

bit BeepCtrl = 0;//蜂鸣器流程控制标志位

void BeepProc(void)

{

  static unsigned int BeepTimer;

  static unsigned char BeepStatus = 0;

  static unsigned char i;

  switch(BeepStatus)

  {

    case 0://

       if(BeepCtrl)

       {

        i = 3;//蜂鸣次数

        BeepFlag = 1;//置位忙标志位

        BeepCtrl = 0;//清除控制标志位

        BeepTimer = TIMER;//这里TIMER为系统定时器计数时钟为1ms

        BeepEn(); //开启蜂鸣器

        BeepStatus = 1;//进入下一个状态

       }

    break;

    case 1://蜂鸣状态

       if(TIMER-BeepTimer>220)//220ms

       {

         BeepDis(); //关闭蜂鸣器

         BeepTimer = TIMER;//记录时刻

         BeepStatus = 2;//进入下一个状态

       }

    break;

    case 2://停止蜂鸣状态

       if(TIMER-BeepTimer>110)//110ms

       {

         if(i!=0)

         {

           i--;

           BeepTimer = TIMER;//记录时刻

           BeepEn(); //开启蜂鸣器

           BeepStatus = 2;//回到蜂鸣状态

         }

         else

         {

           BeepStatus = 0;//回到初始状态

           BeepFlag = 0;//清除忙标志位

         }

       }    

    break;

    default:

      BeepFlag = 0;//清除忙标志位

      BeepStatus = 0;//回到初始状态

    break;

  }

}


用这样的方法实现的蜂鸣程序在使用时也有不同的地方,因为使用的switch状态所有在主循环中要一直调用:


void main()

{

  SystemInitial();//系统初始化

  ...............


  //主循环

  while(1)

  {

     Fun1Proc();//功能1流程

     Fun2Proc();//功能2流程

     ....     

     BeepProc();//蜂鸣流程

     ....

  }


}


16

在别的函数中需要使蜂鸣器工作时只需要下面代码即可:


if(!BeepFlag)//检查是否忙

 BeepCtrl = 1;//启动蜂鸣器


用这种方法能充分利用MCU,在蜂鸣器发声或发声间隔的等待时间MCU可以处理别的函数,但是还要有几点需要注意


第一,主循环while(1)的循环周期最好小于定时器计数时钟周期 

第二,主循环中尽量不要使用硬延时Delayms 

第三,代码中如果存在多个地方需要控制一个流程时一定要先读取标志位再控制


关键字:单片机  软件定时器  使用方法 引用地址:单片机软件定时器的使用方法

上一篇:51单片机自定义多个软件定时器
下一篇:基于C8051F040单片机的CAN总线通信

推荐阅读

本月初,Intel发布了首款消费级QLC固态硬盘——660p。性能上达到主流M.2 NVMe的水准,最高连续读写速度可达1800MB/s。同时,价格相当给力,512GB卖99.99美元(约合683元)。不过,澳媒报道称,接近IMFlash闪存工厂(Intel/美光合资)的人士透露,目前第一代64层QLC闪存的良率只有48%,也就是生产出来的成片过半报废。对比之下,64层TLC闪存的良率已经达到...
楼宇经济是近年来中国城市经济发展中涌现的一种新型经济形态。浦东区一项最新调查显示,陆家嘴金融贸易区、外高桥保税区等地的105栋新建楼宇,去年每栋高楼平均营业收入超过16亿元,楼均上缴税超过6000万元,一幢大楼的经济规模相当一家大型企业。楼宇经济的爆发也让智慧楼宇的发展进入了快车道。8月29 日-31日,世界人工智能大会在上海举行。作为世界范...
  某个午夜时分的沉静被打破———远在欧洲的用户要买一台“中国制造”的洗衣机,随手在手机下单。几乎同一时间,这条订单信息被推送到洗衣机原材料供应商、组装制造部门、物流运输部门等生产链条所涉及的各个环节。这并不是科幻电影或小说中的情形,而是发生在中国家电企业海尔“黑灯车间”的真实场景。  就在近日,备受瞩目的《中国制造2025》规划正...
  我们都知道,耐压测试是用来检测设备电压是否安全使用。因为它的操作对象是电,所以它在操作的时候就要更加的小心谨慎,以免造成一些伤害。专业生产耐压测试仪的厂家会明确地告诉每一个顾客使用耐压测试仪要注意的事项。下面国电西高跟大家介绍一下在使用测试仪时的注意事项。  一、人们在使用耐压测试仪的时候,一定要在脚下和座椅上垫好绝缘橡皮,...

史海拾趣

问答坊 | AI 解惑

请教一个频率加减的问题。

我有一个信号源是0~2kHz,但我想把它转变成8~10kHz,也就是想在原来的基础上+8kHz。请问有没有可能实现这个功能的相关电路或者芯片?谢谢!…

查看全部问答∨

MM的工作态度

早晨听交通台,今天的主打话题是“斗气”。结果一位MM说,斗气最不好了,又伤身体又花钱,每次斗气都要疯狂采购一番。听到这里,我觉得很正常,因为很多MM都是这样。一个朋友就因为和老公闹翻了,立刻跑到商场里花6000多买了一个LV的小手包。没想到 ...…

查看全部问答∨

关于数码管的问题

有一个题,要求这样:用一个按键来控制数码管计数。每按键一下就加1,从00到99,到99后,在按键又返回00,如此循环下去。。    先说一下我的板子上数码管,他的段选我、由P0控制,位选是P3控制。没有什么芯片间接控制。 但是我烧写进板 ...…

查看全部问答∨

请教wince 微秒延时

CE驱动程序里跟某外部设备通信,需用到微秒级延时。现在实验用简单的程序循环方式来实现中间的延时: V_pIoPregs->rGPBDAT &= ~(1<<1);  //GPB1 set 1 Delay1us(4);  //delay 4 us V_pIoPregs->rGPBDAT |= (1< ...…

查看全部问答∨

关于LM393应用中输出不成方波的问题

我用到了LM393但使用中用此原理做的板子,有一块之前的板子输出信号没有问题,但这块板子LM393输出电压为0V,1.25V,5V三种状态,只有输入端电压差很多时才输出5V电压,接近时输出1.25V,而之前的那块板只输出0和5V.把CD4541断掉也是一样.为什么会有这种现 ...…

查看全部问答∨

三合一板上STLink的工作指示灯插上USB是亮的吗

                                 最近拿到一块三合一板,用MDK4.1无法连接,观察STlink板上有个LED,插上USB就亮的吗?还是要连接上?…

查看全部问答∨

请教F2812的FLASH下载问题

第一次向2812的FLASH内下载程序是成功的,且程序也能够执行;第二天擦除后,在下载就不行了,报告: Flash API Error #31: There was a Aero Bit Error on the Program Operation. First Fail Address=0x003D7801 在开发板上和其他产品的板子上 ...…

查看全部问答∨

大家有没有在lm3s8962申请板上解析过GPS数据

刚开始学,弄了很久没成功,有没有工程分享个...…

查看全部问答∨
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
随便看看

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved