找回密码
 立即注册
查看: 825|回复: 1

学习冲哥视频(6):1ms延时函数为什么要循环6000次?为什么有误差?

[复制链接]
  • 打卡等级:以坛为家I
  • 打卡总天数:395
  • 最近打卡:2025-05-07 07:52:03

45

主题

381

回帖

1591

积分

金牌会员

静坐常思己过,闲谈莫论人非

积分
1591
发表于 2023-11-18 21:42:36 | 显示全部楼层 |阅读模式
本帖最后由 rengran 于 2023-11-21 16:23 编辑

1、 为什么delay_ms()函数中的1ms定时的循环次数是6000?
在视频中,我们看到有一个延时函数delay_ms,其中一毫秒的计算方法中使用到了一个while(--i)的空循环,其中循环次数i=系统时钟频率SYSclk/6000,(见图6.1,)z至于为什么是6000,可能有人就会说一点点的试出来的,其实不然。如果从1试到6000,那得多大的工作量啊。本质上还得从程序运行指令中入手,确定循环次数,然后通过实验进行调整。
          图6.1.png
                                   图6.1
在KEIL中有调试功能,利用调试功能,查看汇编指令的运行,我们就能得出6000这个数是怎么来的了。
首先,程序运行到delay_ms(3)函数处,会运行两个指令:
         MOV  WR6  #0x0003;               (1)
         LCALL  delay_ms(C:0x1EF9);        (2)
(1)指令是将立即数3存到WR6寄存器当中;(2)指令是一个调用指令,就是下一步将要进入到0x1EF9处去执行,这也就是说,delay_ms函数入口就在0x1EF9处(见图6.2)
            图6.2.png
                                       图6.2
其次就是进入到延时函数delay_ms中去执行。如图6.3所示,延时函数的执行位置在0x1EF9处,首先执行了一条语句:MOV  WR4 WR6;然后就进入了i的赋值语句,其后的四条语句就是1ms的循环,循环的次数就是i的值。
            

图6.3

图6.3

                                   图6.3
①0xFF1EFF  7D13        MOV      WR2,WR6
②0xFF1F01  1B14        DEC        WR2,#0x01
③xFF1F03  7D31        MOV     WR6,WR2
④0xFF1F05  78F8        JNE         C:0x1EFF
查询STC32G的手册得知,从寄存器到寄存器的MOV的指令需要的时钟数是1个时钟数,一个减一指令DEC也需要一个时钟数,不等跳转指令JNE需要三个时钟数,所以每一次循环需要6个时钟。假设一个时钟周期为T0,那么i次循环的总时长就是6*T0*i。T0=1/Fosc,i=Fosc/N,总时长若为0.001秒,即6*T0*i=0.001,带入后为:6*1/Fosc*Fosc/N=0.001,所以N的值为6000。

2、 delay_ms()函数为什么不准确?
有以下几个方面:
①    从进入delay_ms(J)函数到跳出该函数,要执行
     MOV  WR6  #0x0003;                  1次                每次1个T0
     LCALL     delay_ms(C:0x1EF9);       1次                每次3个T0
     MOV  WR4 WR6;                           J次                每次1个T0
    1ms的循环语句                                  假定这地方的1ms是准确的
    还有下面判断J是否为0的四个语句语句
    MOV      WR2,WR4                            J次               每次1个T0
          DEC       WR2,#0x01                          J次               每次1个T0
          MOV      WR4,WR2                             J次               每次1个T0
          JNE        C:0x1EFB                             J次               每次3个T0
     计时Jms,其实总时间为J(毫秒)+(10*J+4)*T0。所以说定时时间越长的话,J就要越大,多用的时间(10*J+4)*T0也就越大。这就是导致这个函数不准确的地方之一。
②     由于i=Fosc/N,i和N都是整数,如果Fosc/N的结果不是整数的话,系统会自动舍去小数的部分,舍去的部分也是导致定时时间越长误差越大的原因之一。


处事要代人所想,读书需切己用功
回复

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:395
  • 最近打卡:2025-05-07 07:52:03

45

主题

381

回帖

1591

积分

金牌会员

静坐常思己过,闲谈莫论人非

积分
1591
发表于 2023-11-19 06:39:04 | 显示全部楼层
delay_ms延时函数有误差的第三个原因:
③由于delay_ms延时函数需要在主程序中调用,当程序中含有中断,延时函数执行过程中会被中断打断去系统去执行中断,此时的delay_ms会停止运行,所以定时的实际时间就会延长,导致定时不准。
处事要代人所想,读书需切己用功
回复 支持 反对

使用道具 举报 送花

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

本版积分规则

QQ|手机版|小黑屋|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2025-5-7 10:58 , Processed in 0.109752 second(s), 54 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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