找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2163|回复: 9
收起左侧

stc单片机怎么用定时器写有参延时器?

[复制链接]
ID:72649 发表于 2021-10-7 08:26 | 显示全部楼层 |阅读模式
怎么用stc单片机写有参延时子程序,可以调用单位为秒的延时,miao(s),调用时可以1-n秒。
回复

使用道具 举报

ID:624769 发表于 2021-10-7 15:52 | 显示全部楼层
首先,针对你的标题, 延时,不要用定时器。

其次,如果没有必要不要用有参延时子程序,一旦有参,就不会精准。(建议)

延时子程序,需要牵涉到  系统主频,以及你的编译软件(尤其是STC的单片机),其实精准的延时最好用汇编写,尤其是STC的单片机,理由下面会讲。
主频就不说了,应该能理解,下面将延时子程序的时间计算。
延时主要就是让程序在某地反复做一些没意义的事情,延缓下一步操作开始的时间,常用的方法是:
while(--i);          编译的时候,一般会转成汇编    DJNZ   R7,$     或者 DJNZ    07,$
R7, 是寄存器地址,  07 是直接地址,  在STC不同型号下 这个操作的时钟数是不同的。
比如  STC89 , 这个操作是 24个时钟 相当于 2个NOP
STC 15 系列, 如果 DJNZ R7  那么是 4个时钟,即 4个NOP,  DJNZ 07 那么就是5个时钟,即5个NOP
STC 8 系列, 则是 3个时钟, 最后0的时候 2个时钟, 即 3或 2 个NOP
现在发现 要 计算延时时间的复杂程度了吧? 不同的型号的STC 要写不同的延时函数,
这还只是 针对 while(--i); 的, 如果你 调皮 用 for 来写延时函数, 好要牵涉到  DEC 或者 INC 还要牵涉到 CJNE 这些汇编代码的时钟周期。所以,如果你会汇编,可以考虑 用汇编写 延时 ,然后 PUBLIC 让C程序调用,这样比较精准。  如果不会, 那么建议,延时的时间种类不多的话,就用STC的ISP软件自带的延时计算,做几个延时子函数,会更好一点。
回复

使用道具 举报

ID:624769 发表于 2021-10-7 16:14 | 显示全部楼层
居然忘了正事……
带参延时程序写法:

首先,用STC-ISP自带的的 延时程序生成器 生成出 5微秒延时子程序,delay5us();  1毫秒延时子程序,delay1ms();
然后,制作如下两个带参子程序:
void  delay_us(unsigned char i)      // 这里一定要用char 不然精准度会差很多
{
        while(i--)   delay5us();
}

void  delay_ms(unsigned char i)      // 这里一定要用char 不然精准度会差很多
{
        while(i--)   delay1ms();
}

那么,主程序中只要:
delay_ms(10);         //就是延时10毫秒

delay_us(10);      //就是延时50微秒

切记,作为基准的延时子函数,尽量不要小于4微秒,不然精准度会差很多,传参在微秒级别必须用单字节(char) , 毫秒级别的,可以酌情双字节。

回复

使用道具 举报

ID:161164 发表于 2021-10-7 16:44 | 显示全部楼层
  1. void Miao(u8 Sec)
  2. {
  3.         while(Sec)
  4.         {
  5.                 if(!u16_Delayms_Pre)//在一微秒定时器中减一,直到零
  6.                 {u16_Delayms_Pre = 1000;
  7.                         Sec--;
  8.                 }
  9.         }
  10. }
复制代码
回复

使用道具 举报

ID:881715 发表于 2021-10-7 17:08 来自手机 | 显示全部楼层
188610329 发表于 2021-10-7 15:52
首先,针对你的标题, 延时,不要用定时器。

其次,如果没有必要不要用有参延时子程序,一旦有参,就不 ...

老师为什么有参数不会很精准
回复

使用道具 举报

ID:624769 发表于 2021-10-7 17:16 | 显示全部楼层
创造生活 发表于 2021-10-7 17:08
老师为什么有参数不会很精准

传参牵涉到很多 代码, 比如:
PUSH  07
MOV  R7,#10
CALL delay
POP  07

而这些,都是占用时钟数的,你要精准的话,要把这些时间都算上去,而这些可能就要超过1微秒的时间了,你说你延时 2微秒,光这些准备时间就1~2 微秒了,你的核心延时程序怎么写法才能精准?所以,没有10微秒以上延时,是非常不建议传参延时的。
回复

使用道具 举报

ID:951974 发表于 2022-12-21 14:55 | 显示全部楼层
188610329 发表于 2021-10-7 15:52
首先,针对你的标题, 延时,不要用定时器。

其次,如果没有必要不要用有参延时子程序,一旦有参,就不 ...

简直是胡说八道啊,,应该是能不用延时就不用延时,延时就是在浪费CPU,一直在做无用功。所以最好一个延时都不用。这样才能增强实时性。
回复

使用道具 举报

ID:1034262 发表于 2022-12-23 11:30 | 显示全部楼层
楼主,STC官方例子就有定时器0~4的用法。举个例子:
#define         MAIN_Fosc                24000000UL        //定义主时钟

//========================================================================
// 函数: u8        Timer0_Config(u32 time)
// 描述: timer0初始化函数.
// 参数: time: 时间us.
// 返回: 0: 初始化正确, 1: 重装值过大, 初始化错误.
// 版本: V1.0, 2018-3-5
//========================================================================
u8        Timer0_Config(u32 time)        //time值是时间(单位us)
{
        TR0 = 0;        //停止计数
        TMOD &= 0xf0;
       
        time = (u32)(((float)MAIN_Fosc * (float)time)/1000000UL);        //重装的是时间(us), 计算所需要的系统时钟数.
        if(time >= (65536UL * 12))        return 1;        //值过大, 返回错误
        if(time < 65536UL)        AUXR |= 0x80;                //1T mode
        else
        {
                AUXR &= ~0x80;        //12T mode
                time = time / 12;
        }
        time = 65536UL - time;
        TH0 = (u8)(time >> 8);
        TL0 = (u8)(time);

        ET0 = 1;        //允许中断
//        PT0 = 1;        //高优先级中断
        TMOD = (TMOD & ~0x03) | 0;        //工作模式, 0: 16位自动重装, 1: 16位定时/计数, 2: 8位自动重装, 3: 16位自动重装, 不可屏蔽中断
        TR0 = 1;        //开始运行
        return 0;
}

初始化调用:
        Timer0_Config(10000);        //定时时间 us

//========================================================================
// 函数: void timer0_ISR (void) interrupt TIMER0_VECTOR
// 描述:  timer0中断函数.
// 参数: none.
// 返回: none.
// 版本: V1.0, 2016-5-12
//========================================================================
void timer0_ISR (void) interrupt TIMER0_VECTOR
{
   P32 = ~P32;
}

回复

使用道具 举报

ID:308903 发表于 2023-1-3 10:02 | 显示全部楼层
用 ISP自带的
回复

使用道具 举报

ID:1060350 发表于 2023-1-4 21:40 | 显示全部楼层
编写一段关于延时的函数,主要利用for循环,代码如下: void delay_ms(unsigned int ms) { unsigned int i; unsigned char j;     for(i=0;i<ms;i++)     {         for(j=0;j<200;j++);         for(j=0;j<102;j++);     }  }
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表