杨为民 发表于 2024-10-14 19:32:11

C51语言中的微秒、毫秒软件延迟函数探讨

本帖最后由 杨为民 于 2024-10-14 19:35 编辑

(1)用C51语言编写51单片机程序,软件延迟函数是最基本的函数之一,通常是用空循环语句来实现。(2)用C51语言编写的延迟函数有一个重要的缺点就是其延迟时间依赖于C51项目的编译模式和优化等级。Small的编译模式将循环变量安排在DATA空间,Large的编译模式将循环变量安排在XDATA空间,即使对同一个C语言延时函数的它们的运行时间是不同的。优化等级也会影响延迟时间,最极端的情况是将延迟函数的全部局部变量优化在寄存器中,这时由于不涉及内存变量存取,延迟函数的运行速度最快。(3)因此最通用的软件延迟函数应该是用汇编语言编写的,这样就不会受编译模式和优化等级的影响了。本文介绍一种在C51程序中用内嵌汇编语言方式编写的毫秒和微秒软件延迟函数。(4)下图是对AI8051U单片机的8Bit模式写的毫秒软件延迟函数的具体程序:
其中第42行是以KHz为单位的单片机运行主频。(5)该函数的参数MS是16位无符号整数,因此该函数的最大延迟时间是65535毫秒=65.535秒,对一般应用是足够了。(6)该函数采用双层循环的方法来实现,外层循环的次数就是要延时的毫秒数,内层循环的次数是对应主频下消耗1毫秒时间需要进行的循环次数。内层循环次数R2R3由第57和58行计算,其中的除数10是根据实际测试得到的。(7)在AI8051U单片机上对上面毫秒延迟函数的延时精度测试结果如下:给定值(毫秒)    测试值(毫秒)1.000          1.000915.000          5.0020010.000         10.004550.000         50.0207100.000      100.051500.000      500.205这个测试结果表明该毫秒软件延时函数的精度高于1%。
(8)微秒级的延迟在单片机对低速外设的输入输出函数中也是必须的,它用于维持外部总线信号以便外设能正确读取和等待外设信号稳定后再读。本文介绍的微秒级软件延迟函数也是用双层空循环的方法实现的。(9)下图是对AI8051U单片机的8Bit模式写的微秒软件延迟函数的具体程序:
其中内层循环次数R2由第94行程序计算,其中的除数3500是根据实际测试得到的。同样该函数的参数uS是16位无符号整数,因此该函数的最大延迟时间是65535微秒=65.535毫秒,可以与上面的毫秒延迟函数进行衔接了。(10)在AI8051U单片机上对上面微秒延迟函数的延时精度测试结果如下:给定值(微秒)    测试值(微秒)1.000          1.58335.000          5.46710.000         10.00050.00          47.333100.00         94.000500.00         467.25(11)测试结论:对于微秒软件延迟函数而言,由于除了双层延迟循环外,还附加了调用函数对参数的赋值和对函数的访问等额外指令,所以对16位这样大范围的延迟函数是难以在全程范围都准确的。
(12)考虑到51单片机大多数低速外设的信号速度在100KHz左右,因此本文第94行程序内循环次数的计算公式中的除数是根据10微秒校准的。


soma 发表于 2024-10-14 20:24:57

感觉如果定时器足够还是定时器延时好点,资源占用方面也好很多。

soma 发表于 2024-10-14 20:25:00

感觉如果定时器足够还是定时器延时好点,资源占用方面也好很多。

晓飛飛 发表于 2024-10-14 22:05:10

定时器周期中断+软定时器+状态机,能解决90%以上需要延时的场合,非阻塞、高效、扩展性能好。

YYYYAN 发表于 2024-10-14 23:34:31

C语言里面还能执行汇编的吗,我是小白有点不懂{:4_267:}

tubulvxing 发表于 2024-10-15 08:45:14

汇编不受优化等级影响

xuzeabc 发表于 2024-10-15 09:14:31

YYYYAN 发表于 2024-10-14 23:34
C语言里面还能执行汇编的吗,我是小白有点不懂

C中嵌入汇编是可以的。C语言在编译的时候也会先生成汇编的。嵌入汇编的好处是不会优化汇编代码。

xxkj2010 发表于 2024-10-15 09:20:04

能用汇编语言来作软件延时是比较准确的{:4_250:}

康辉55AA 发表于 2024-10-15 10:06:58

我想知道(unsigned int MS)和(unsigned int uS)参数是如何传递给汇编代码的?

康辉55AA 发表于 2024-10-15 11:10:20

经过仔细查看汇编代码,感觉C涵数内嵌入的汇编代码,参数是固定传给R6和R7的,且高位在R6,低位在R7。
我这样理解对吗?

JZ JSx51_BIOS_Delay_MS_01;
INC R6;
这两句没明白什么意思?如果R7为0,R6为什么要加1呢?
页: [1] 2 3
查看完整版本: C51语言中的微秒、毫秒软件延迟函数探讨