精华内容
下载资源
问答
  • STC11F04单片机定时器模拟多任务程序

    千次阅读 2011-10-23 21:09:49
    用STC单片机定时器精确定时,做1秒、1分、1小时的定时任务。由于本人用的是11.0592的晶体,所以时间上不是很精确。如果对定时有精确要求的,请用32.768M的晶振。串口输出采用 printf函数输出。#include"reg51.h"#...

    用STC单片机的定时器精确定时,做1秒、1分、1小时的定时任务。

    由于本人用的是11.0592的晶体,所以时间上不是很精确。如果对定时有精确要求的,请用32.768M的晶振。

    串口输出采用 printf函数输出。

    #include"reg51.h"

    #include "stdio.h"
    #include"intrins.h"  //_nop_()


    unsigned int tick;

    int hh,mm,ss; //时:分:秒
    char putchar (unsigned char i)
    {
        ES     =   0;  //关串口中断
        TI     =   0;  //清零串口发送完成中断请求标志
        SBUF   =   i;
        while(TI ==0); //等待发送完成
        TI     =   0;  //清零串口发送完成中断请求标志
        ES     =   1;  //允许串口中断
    return SBUF;
    }

    void Task_1s()
    {
      printf("S=[%d:%d:%d]\r\n",hh,mm,ss);   
    }

    void Task_1m()
    {  
       printf("M=[%d:%d:%d]\r\n",hh,mm,ss);   
    }

    void Task_1h()
    {
       printf("H=[%d:%d:%d]\r\n",hh,mm,ss); 
    }

    //0.1ms = 100us
    void Timer0(void) interrupt 1 using 1 //定时器0中断外理
    {
       TR0=0;
       TH0=(65536-2000)/256; 
       TL0=(65536-2000)%256; 
        
    tick++;     //计数值+1
        if(tick>999)    //加到10次即1秒
        {           
          tick=0;
          ss++;
           if(ss>59){
                mm++;
                ss=0;
               if(mm>59){
                 hh++;
                 mm=0;
               if(hh>11){
                  hh=0;
               }
              Task_1h();//1小时定时任务
             }
            Task_1m(); //1分钟定时任务
      }
      Task_1s();//1s定时任务
    }
    TR0=1;
    }

    void main()
    {
      SCON=0x50; //0101,0000 8位可变波特率,无奇偶校验位
      TMOD=0X21;
      TH1=TL1=-(11059200L/12/32/9600);
      TR1=1;
      tick=0;
      hh=0;
      mm=0;
      ss=0;
      TH0=(65536-2000)/256; 
      TL0=(65536-2000)%256; 
      TR0=1;
      ET0=1;
      ES=1;    //允许串口中断
      EA=1;    //开总中断 
      printf("SystemStart...\r\n");
      
      while(1)
      {
        _nop_();
      }
    }


    程序运行后结果如图:



    代码详解:

    (1)串口波特率计算

          TH1=TL1=-(11059200L/12/32/9600);

          由于采用11.0592晶振,所以这里是11059200L

         由于采用9600波特率和计算机通信,所以采用9600

    (2)串口输出为什么可以用“printf"函数?

          例如:   printf("S=[%d:%d:%d]\r\n",hh,mm,ss); 可以很方便的输出要的数据

         原因是要自己实现printf的底层通信代码,即在你的代码里加入

           

       这个函数的原型定义在:#include "stdio.h" 里,感兴趣的朋友,还可以把其他函数也实现。这样C51编程就可以和计算机上的C语言编程类似了。


      (3)定时器初值说明:

                TH0=(65536-2000)/256;   高8位
                TL0=(65536-2000)%256;  低8位

    (4) 定时任务


       任务的调用在定时器中断里,详细见定时器中断。

             void Timer0(void) interrupt 1 using 1 //定时器0中断外理


    希望对大家有用!错误在所难免,诸位看官自己调试把。。。。

    呵呵!

    展开全文
  • 用STC单片机定时器精确定时,做1秒、1分、1小时的定时任务。由于本人用的是11.0592的晶体,所以时间上不是很精确。如果对定时有精确要求的,请用32.768M的晶振。串口输出采用 printf函数输出。#include"reg51.h"#...

    用STC单片机的定时器精确定时,做1秒、1分、1小时的定时任务。

    由于本人用的是11.0592的晶体,所以时间上不是很精确。如果对定时有精确要求的,请用32.768M的晶振。

    串口输出采用 printf函数输出。

    #include"reg51.h"

    #include "stdio.h"

    #include"intrins.h"  //_nop_()

    unsigned int tick;

    int hh,mm,ss; //时:分:秒

    char putchar (unsigned char i)

    {

    ES     =   0;  //关串口中断

    TI     =   0;  //清零串口发送完成中断请求标志

    SBUF   =   i;

    while(TI ==0); //等待发送完成

    TI     =   0;  //清零串口发送完成中断请求标志

    ES     =   1;  //允许串口中断

    return SBUF;

    }

    void Task_1s()

    {

    printf("S=[%d:%d:%d]\r\n",hh,mm,ss);

    }

    void Task_1m()

    {

    printf("M=[%d:%d:%d]\r\n",hh,mm,ss);

    }

    void Task_1h()

    {

    printf("H=[%d:%d:%d]\r\n",hh,mm,ss);

    }

    //0.1ms = 100us

    void Timer0(void) interrupt 1 using 1 //定时器0中断外理

    {

    TR0=0;

    TH0=(65536-2000)/256;

    TL0=(65536-2000)%256;

    tick++;     //计数值+1

    if(tick>999)    //加到10次即1秒

    {

    tick=0;

    ss++;

    if(ss>59){

    mm++;

    ss=0;

    if(mm>59){

    hh++;

    mm=0;

    if(hh>11){

    hh=0;

    }

    Task_1h();//1小时定时任务

    }

    Task_1m(); //1分钟定时任务

    }

    Task_1s();//1s定时任务

    }

    TR0=1;

    }

    void main()

    {

    SCON=0x50; //0101,0000 8位可变波特率,无奇偶校验位

    TMOD=0X21;

    TH1=TL1=-(11059200L/12/32/9600);

    TR1=1;

    tick=0;

    hh=0;

    mm=0;

    ss=0;

    TH0=(65536-2000)/256;

    TL0=(65536-2000)%256;

    TR0=1;

    ET0=1;

    ES=1;    //允许串口中断

    EA=1;    //开总中断

    printf("SystemStart...\r\n");

    while(1)

    {

    _nop_();

    }

    }

    程序运行后结果如图:

    a651a36d9d04bf267804c788386a84dc.gif

    代码详解:

    (1)串口波特率计算

    TH1=TL1=-(11059200L/12/32/9600);

    由于采用11.0592晶振,所以这里是11059200L

    由于采用9600波特率和计算机通信,所以采用9600

    (2)串口输出为什么可以用“printf"函数?

    例如:   printf("S=[%d:%d:%d]\r\n",hh,mm,ss); 可以很方便的输出要的数据

    原因是要自己实现printf的底层通信代码,即在你的代码里加入

    87c6b455b340c28974f81a35141228ed.gif

    这个函数的原型定义在:#include "stdio.h" 里,感兴趣的朋友,还可以把其他函数也实现。这样C51编程就可以和计算机上的C语言编程类似了。

    (3)定时器初值说明:

    TH0=(65536-2000)/256;   高8位

    TL0=(65536-2000)%256;  低8位

    (4) 定时任务

    aae6fffb557f4573da717ad3283952bd.gif

    任务的调用在定时器中断里,详细见定时器中断。

    void Timer0(void) interrupt 1 using 1 //定时器0中断外理

    希望对大家有用!错误在所难免,诸位看官自己调试把

    展开全文
  • 经过这几天做的程序,和以前做电子钟时的感悟,现在对单片机的整个程序结构做一下总结。相信这个总结是很有必要的,在组织大型复杂程序结构时需要有一个正确的理论指导。 感觉这种程序结构的很想法和操作系统非常...
  • 在刚开始学习单片机的时候,那时候由于简单的51单片机资源比较少所以一直就觉得单片机定时器资源不够用。 在深度学习各种知识后发现其实很情况下并不需要那么多定时器。 那么解决方法是啥呢? 方法就是:...

    在刚开始学习单片机的时候,那时候由于简单的51单片机资源比较少所以一直就觉得单片机的定时器资源不够用。

    在深度学习各种知识后发现其实很多情况下并不需要那么多定时器。

    那么解决方法是啥呢?

    方法就是:定时器复用

    定时器复用指的是,比如你需要两个定时器一个定时器任务A时间间隔是1s,一个定时器任务B时间间隔是0.5s,那么你的定时器可以设置触发时间为0.1s然后对定时器的进入次数进行计数,当计数到10的时候执行任务A,当计数到5s的时候执行任务B。

    这样一个定时器可以监控多个任务的状态,其实linux上很多就是采用这样的方式来执行的,这个复用的方式和思考习惯很有用,在以后代码的编写过程中可以大量的使用这种方式,包括套接字使用的时候等等;

     

     

    展开全文
  • 单片机定时器2使用

    2014-06-11 16:01:00
    定时器T2 reg52.h没有T2MOD寄存器 regx55.h有T2MOD寄存器而且sbit已经定义 概述 定时器2是一个16位通用计数器,其具有两种操作模式:16位自动重载模式和16位捕获模式。 如果预分频功能被禁止,定时器2工作时,...

    定时器T2

    reg52.h没有T2MOD寄存器

    regx55.h有T2MOD寄存器而且sbit已经定义

    概述

    定时器2是一个16位通用计数器,其具有两种操作模式:16位自动重载模式和16位捕获模式。

    如果预分频功能被禁止,定时器2工作时,16位通用加法计数器以12分频的周期脉冲计数,每个周期16位通用加法计数器加1或减1。

    定时器2由T2MOD寄存器、T2CON存器、功能存器TH2、TL2、RC2H、RC2L等电路构成。

    TH2、TL2构成16位通用计数器。

    RC2H、RC2L作为16位寄存器,在自动重载模式中RC2H、RC2L作为16位通用计数器的16位初值寄存器

    捕捉模式中,当引脚T2EX上出现下降沿跳变时,把TH2、TL2的当前值捕捉到RC2H、RC2L中去。

      1.控制寄存器T2CON

    T2CON(T2的控制寄存器),字节地址0C8H:

    位地址   0CFH    0CEH   0CDH   0CCH   0CBH   0CAH   0C9H   0C8H

    符  号   TF2     EXF2   RCLK   TCLK   EXEN2  TR2    C/T2   CP/RT2

    各位的定义如下:

    TF2:定时/计数器2溢出标志,T2溢出时置位,并申请中断。只能用软件清除,但T2作为波特率发生器使用的时候,(即RCLK=1或TCLK=1),T2溢出时不对TF2置位。

    EXF2:当EXEN2=1时,且T2EX引脚(P1.0)出现负跳变而造成T2的捕获或重装的时候,EXF2置位并申请中断。EXF2也是只能通过软件来清除的。

    RCLK:串行接收时钟标志,只能通过软件的置位或清除;用来选择T1(RCLK=0)还是T2(RCLK=1)来作为串行接收的波特率产生器

    TCLK:串行发送时钟标志,只能通过软件的置位或清除;用来选择T1(TCLK=0)还是T2(TCLK=1)来作为串行发送的波特率产生器

    EXEN2:T2的外部允许标志,只能通过软件的置位或清除;EXEN2=0:禁止外部时钟触发T2;EXEN2=1:当T2未用作串行波特率发生器时,允许外部时钟触发T2,当T2EX引脚输入一个负跳变的时候,将引起T2的捕获或重装,并置位EXF2,申请中断。

    TR2:T2的启动控制标志;TR2=0:停止T2;TR2=1:启动T2

    C/T2:T2的定时方式或计数方式选择位。只能通过软件的置位或清除;C/T2=0:选择T2为定时器方式;C/T2=1:选择T2为计数器方式,下降沿触发。

    CP/RT2:捕获/重装载标志,只能通过软件的置位或清除。CP/RT2=0时,选择重装载方式,这时若T2溢出(EXEN2=0时)或者T2EX引脚(P1.0)出现负跳变(EXEN2=1时),将会引起T2重装载;CP/RT2=1时,选择捕获方式,这时若T2EX引脚(P1.0)出现负跳变(EXEN2=1时),将会引起T2捕获操作。但是如果RCLK=1或TCLK=1时,CP/RT2控制位不起作用的,被强制工作于定时器溢出自动重装载模式。

     2.模式寄存器T2MOD

    寄存器T2MOD用来选择定时器2的工作模式。其组成如图8-8所示。

     

    T2MOD(方式寄存器),字节地址0C9H:

     

    D7     D6     D5     D4     D3     D2     D1     D0

    --      --      --      --       --      --      T2OE   DCEN

    T2OE:T2输出允许位,当T2OE=1的时候,允许时钟输出到P1.0。(仅对80C54/80C58有效)

    DCEN:向下计数允许位。DCEN=1是允许T2向下计数,否则向上计数。

     

    T2的数据寄存器TH2、TL2和T0、T1的用法一样,而捕获寄存器RCAP2H、RCAP2L只是在捕获方式下,产生捕获操作时自动保存TH2、TL2的值。

        以上是T2的相关寄存器的描述,其实用法上跟T0、T1是差不多的,只是功能增强了,设置的东西多了而已。

    定时/计数器2其实用到最多的就是T2CON这个寄存器啦,它设定的定时和计数的方式。有三种工作方式,捕获,自动重装,波特率发生器

     

     

    定时器T2工作模式

    波特率发生器:

      当T2CON(表3)中的TCLK 和RCLK 置位时,定时/计数器2 作为波特率发生器使用。如果定时/计数器2 作为发送器或接收器,其发送和接收的波特率可以是不同的,定时器1 用于其它功能,如图7 所示。若RCLK 和TCLK 置位,则定时器2工作于波特率发生器方式。

      波特率发生器的方式与自动重装载方式相仿,在此方式下,TH2 翻转使定时器2 的寄存器用RCAP2H 和RCAP2L 中的16位数值重新装载,该数值由软件设置。

      在方式1 和方式3 中,波特率由定时器2 的溢出速率根据下式确定:

    方式1和3的波特率=定时器的溢出率/16

    定时器既能工作于定时方式也能工作于计数方式,在大多数的应用中,是工作在定时方式(C/T2=0)。定时器2 作为波特率发生器时,与作为定时器的操作是不同的,通常作为定时器时,在每个机器周期(1/12 振荡频率)寄存器的值加1,而作为波特率发生器使用时,在每个状态时间(1/2 振荡频率)寄存器的值加1。波特率的计算公式如下:

      方式1和3的波特率=振荡频率/{32*[65536-(RCP2H,RCP2L)]}式中(RCAP2H,RCAP2L)是RCAP2H和RCAP2L中的16 位无符号数。

      定时器2 作为波特率发生器使用的电路如图7 所示。T2CON 中的RCLK 或TCLK=1 时,波特率工作方式才有效。在波特率发生器工作方式中,TH2 翻转不能使TF2 置位,故而不产生中断。但若EXEN2 置位,且T2EX 端产生由1 至0 的负跳变,则会使EXF2 置位,此时并不能将(RCAP2H,RCAP2L)的内容重新装入TH2 和TL2 中。所以,当定时器2 作为波特率发生器使用时,T2EX 可作为附加的外部中断源来使用。需要注意的是,当定时器2 工作于波特率器时,作为定时器运行(TR2=1)时,并不能访问TH2 和TL2。因为此时每个状态时间定时器都会加1,对其读写将得到一个不确定的数值。

      然而,对RCAP2 则可读而不可写,因为写入操作将是重新装载,写入操作可能令写和/或重装载出错。在访问定时器2或RCAP2 寄存器之前,应将定时器关闭(清除TR2)。

    产生11.0592MHz, 9600bps

    void Inituart(void)//11.0592MHz,9600bps

    {TH2=RCAP2H=0Xff;
     TL2=RCAP2L=0XDC;
     T2MOD=0;//reg52没有
    T2CON=0X34;

    }

    2.自动重载模式

    控制寄存器T2CON中的     置“0”时,定时器2被选择为自动重载模式。

    该模式下,定时器2计数至溢出时,将寄存器RC2H、RC2L中的16位初始值重新装入定时器的TH2、TL2寄存器中,开始新一轮计数循环。

    并置位寄存器T2CON的TF2位表示计数溢出,从而向CPU发送中断请求信号。

    溢出标志TF2必须由程序清零。根据控制寄存器T2MOD中DCEN控制位的设置,自动重载模式可进一步分为两种类型。

    1)禁止递增/递减计数模式

    若DCEN = 0,则递增/递减计数选择被禁止,此时定时器只能递增计数。工作原理如图8-10所示。

    定时器2寄存器:寄存器T2CON和T2MOD包含定时器2的控制位和状态位(如表2和表3所示),寄存器对RCAP2H和RCAP2L是定时器2的捕捉/自动重载寄存器。中断寄存器:各中断允许位在IE寄存器中,六个中断源的两个优先级也可在IE中设置。

     

     

    若EXEN2 = 0,置位TR2定时器开始递增计数,计数至最大值FFFFH后溢出并置位TF2,同时将寄存器RC2中的16位重载值重新装入定时器寄存器。

    重载值由软件预先设置。新一轮计数循环开始,定时器同上一轮计数循环一样,从重载值开始递增计数。

    若EXEN2 = 1,置位TR2定时器开始递增计数至最大值FFFFH。计数溢出或输入引脚T2EX的负/正跳变(由寄存器T2MOD的位EDGESEL选择)均会引起16位重载,将寄存器RC2的内容重新装入定时器寄存器。

    中断标志位:

    若由溢出引起重载,溢出标志TF2置位。

    若由引脚T2EX的负/正跳变引起重载,寄存器T2CON中的EXF2置位。

    这两种情况均产生中断,定时器进入下一轮计数循环。EXF2标志和TF2一样必须由软件清零。

     

    允许硬件启动时(T2RHEN=1)

    T2EX第一个上升沿/下降沿触发TR2=1启动T2;

    上升沿/下降沿的选择由T2REGS选择;

    如果使能外部控制(EXEN2=1),引脚T2EX的边沿跳变完成两个任务:(由T2REGS选择上升沿/下降沿)

    启动T2

    EXF2置位

    2)以递增或递减计数。

    引脚T2EX的逻辑电平为1时

    定时器2递增计数,因此定时器递增计数,计数至最大值FFFFH后溢出并置位TF2,RC2寄存器的16位重载值重新装入定时器寄存器。

    引脚T2EX的逻辑电平为0时

    定时器2递减计数。定时器递减计数并当THL2的值和寄存器RC2中的值相等时发生下溢。下溢后置位TF2,并将值FFFFH重新载入定时器寄存器THL2中

    若允许硬件启动T2(当T2RHEN=1)时,根据T2EX输入的是上升沿/下降沿可将T2设置为递增、递减计数

    T2由上升沿启动,T2只能工作于递增模式

    T2由下降沿启动,T2只能工作于递减模式

    定时250us产生2kHz方波

    void Inittimer2 (void)//12MHz,2kHz

    {TH2=RCAP2H=0Xff;
     TL2=RCAP2L=0XDC;
     T2MOD=0;//reg52没有

    IE=0XA0;

    T2CON=0X04;

    }

    void timer2(void) interrupt 5 using 2
    { TF2=0;
        P1_2=!P1_2;
    }

    main()
    {  inittimer2();
     while(1);

    }

    3.捕获模式

    控制寄存器T2CON中的     及EXEN2置位时,定时器进入16位捕获模式。

    此模式下,递减计数功能必须禁止。16位计数器始终递增计数,计数至最大值FFFFH后溢出,TF2置位并将0000H重新载入定时器寄存器TH2、TL2中。

    溢出后TF2置位,则定时器向CPU发送中断请求。

    在引脚T2EX的下降沿/上升沿(由T2MOD.EDGESEL选择),将定时器寄存器(THL2)的值捕获到寄存器RC2中。如果在计数器加1时检测到捕获信号,计数器先加1然后执行捕获操作,从而确保总能捕获到定时计数器的最新值。执行完捕获操作,EXF2置位、可用来产生中断请求

    若允许硬件启动T2(当T2RHEN=1)时,引脚T2EX输入的第一个下降沿/上升沿(由T2MOD.EDGESEL选择)启动T2

    在启动T2的同时,置位EXF2。

    在下一个下降沿/上升沿到来时,将进行捕获操

    引脚号第二功能  P1.0 T2(定时器/计数器T2的外部计数输入),时钟输出

     P1.1 T2EX(定时器/计数器T2的捕捉/重载触发信号和方向控制)

    展开全文
  • 51单片机定时器0中断方式点亮LED灯 此程序采用的模块化编程,模块化在编程中很重要。要想学号单片机,请务必掌握。案例实际使用的STC15单片机,但是对于51单片机也同样的使用。只需要将15单片机的头文件更改为51...
  • 这里将涉及到单片机中断的应用,在 cpu 的一步步按照指令运行的过程中(主程序),可能会有其它的更紧急的需要做的事情(中断服务程序), 需要 cpu 暂时停止当前的程序(主程序),做完了(中断服务程序)之后,又可以继续...
  •  很时候,应用场景,是需要分时处理各个事件。本文章就编写点亮LED与打印输出的示例来讲解使用方法。在这直接进入正题。(在此不做创建项目的步骤介绍) 1、STM32CubeIDE 配置 LED管脚配置 串口1配置(也就是...
  • 题目大概就是:在单片机裸机开发时,单片机要处理任务,此时你的程序框架是怎样的呢?这其实是个经典面试问题,我以前面试也被问过。答案一:轮询系统代码结构如:int 这种结构大概是我们初学单片机的时候的代码...
  • 一、 51单片机串行口工作原理MCS-51系列单片机片内有一个串行I/O端口,通过引脚RXD(P3.0)和TXD(P3.1)可与外设电路进行全双工的串行异步通信。...方式1用于双机之间或与外设电路的通信;方式2...
  • 单片机系统中,有许多情况下需要等待某个事件的发生,来继续下一步操作,如果有一个任务还好说,单片机可以无限等待事件的发生,但是如果单片机要处理个事件时,这种系统一般不能实现,除非用中断,对!...
  • 我们都知道单片机定时器,但我们使用到个需要定时的任务的时候,往往是在定时器中断中,加入定时时间以及标志,至少需要三个部分 :用来计时的cnt :表示计时上限的定时时间 :定时完成标志 传统写法如下: void ...
  • 前段时间,做一个项目,有串口收发指令判断,按键类型判断,长短按之类,power的定时关电,...可能大家都只能用变量在定时中断函数去做任务就行了,但是我总是感觉这样会导致代码看起来太不具有条理性,而且对于
  • 51单片机——定时器

    2021-06-15 22:33:26
    51单片机——定时器为什么使用定时器定时器原理?定时器设置中断配置源代码 为什么使用定时器? 之前我们的led灯每隔1s循环左移点亮的时候,使用的定时方法是在c程序执行若干次空循环,这样会耗费很cpu资源,...
  • 51单片机定时器计数器中断总结

    千次阅读 2010-07-14 23:33:00
      一.TMOD:定时器计数度器模式寄存器       M1M0:定时/计数器一共有四种工作方式,就是用M1M0来控制的,2位正好是四种组合。   1. 工作方式1   工作...
  • 任务一,点亮-熄灭LED灯 ##1.按下一个按钮 一个LED灯亮 按下另一个按钮改LED灯灭 LED (Light Emitting Diode )即发光二极管,是半导体=极管的一种, 可以把电能转化成光能。 LED与普通二极管一样由1个PN结组成,具有...
  • 这是关于基于单片机功能定时器代码,定时器课程设计最终功能是:首先设置计数初值,因为设计时考虑到倒计时时可以设置任意值,所以并没有在程序中设置成自动的增减模式,也并没有内置确定的计时初值,如正计时...
  • 最近失业在家心情郁闷,想想又很久没更新了,把这个相对比较“复杂”的多任务定时器写写吧,之前在csdn的帖子里(《单片机C语言程序该这样写!不是教科书上教的那样!》)就是用的这个定时器来支持我的论点的。又经过...
  • 代码是用STC51单片机编写的定时器中断循环切换多个任务的例程,实现了51单片机多任务运行的功能,大家需要可以下载学习,程序已经在开发板中调试好。

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 4,129
精华内容 1,651
关键字:

单片机定时器多任务