找回密码
 立即注册
查看: 1787|回复: 28

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

[复制链接]
  • 打卡等级:偶尔看看I
  • 打卡总天数:16
  • 最近打卡:2025-04-30 08:41:32

105

主题

1215

回帖

1万

积分

荣誉版主

积分
12882
发表于 2024-10-14 19:32:11 | 显示全部楼层 |阅读模式
本帖最后由 杨为民 于 2024-10-14 19:35 编辑

(1)用C51语言编写51单片机程序,软件延迟函数是最基本的函数之一,通常是用空循环语句来实现。
(2)用C51语言编写的延迟函数有一个重要的缺点就是其延迟时间依赖于C51项目的编译模式和优化等级。Small的编译模式将循环变量安排在DATA空间,Large的编译模式将循环变量安排在XDATA空间,即使对同一个C语言延时函数的它们的运行时间是不同的。优化等级也会影响延迟时间,最极端的情况是将延迟函数的全部局部变量优化在寄存器中,这时由于不涉及内存变量存取,延迟函数的运行速度最快。
(3)因此最通用的软件延迟函数应该是用汇编语言编写的,这样就不会受编译模式和优化等级的影响了。本文介绍一种在C51程序中用内嵌汇编语言方式编写的毫秒和微秒软件延迟函数。
(4)下图是对AI8051U单片机的8Bit模式写的毫秒软件延迟函数的具体程序:
Fig_01_毫秒延时.jpg
其中第42行是以KHz为单位的单片机运行主频。
(5)该函数的参数MS是16位无符号整数,因此该函数的最大延迟时间是65535毫秒=65.535秒,对一般应用是足够了。
(6)该函数采用双层循环的方法来实现,外层循环的次数就是要延时的毫秒数,内层循环的次数是对应主频下消耗1毫秒时间需要进行的循环次数。内层循环次数R2R3由第57和58行计算,其中的除数10是根据实际测试得到的。
(7)在AI8051U单片机上对上面毫秒延迟函数的延时精度测试结果如下:
给定值(毫秒)    测试值(毫秒)
1.000          1.00091
5.000          5.00200
10.000         10.0045
50.000         50.0207
100.000        100.051
500.000        500.205
这个测试结果表明该毫秒软件延时函数的精度高于1%

(8)微秒级的延迟在单片机对低速外设的输入输出函数中也是必须的,它用于维持外部总线信号以便外设能正确读取和等待外设信号稳定后再读。本文介绍的微秒级软件延迟函数也是用双层空循环的方法实现的。
(9)下图是对AI8051U单片机的8Bit模式写的微秒软件延迟函数的具体程序:
Fig_02_微秒延时.jpg
其中内层循环次数R2由第94行程序计算,其中的除数3500是根据实际测试得到的。
同样该函数的参数uS是16位无符号整数,因此该函数的最大延迟时间是65535微秒=65.535毫秒,可以与上面的毫秒延迟函数进行衔接了。
(10)在AI8051U单片机上对上面微秒延迟函数的延时精度测试结果如下:
给定值(微秒)    测试值(微秒)
1.000          1.5833
5.000          5.467
10.000         10.000
50.00          47.333
100.00         94.000
500.00         467.25
(11)测试结论:对于微秒软件延迟函数而言,由于除了双层延迟循环外,还附加了调用函数对参数的赋值和对函数的访问等额外指令,所以对16位这样大范围的延迟函数是难以在全程范围都准确的

(12)考虑到51单片机大多数低速外设的信号速度在100KHz左右,因此本文第94行程序内循环次数的计算公式中的除数是根据10微秒校准的

附件:0101_软件延时_AI8051U_8Bit.rar (62.93 KB, 下载次数: 110)

回复

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:422
  • 最近打卡:2025-05-01 09:54:52
已绑定手机

19

主题

3190

回帖

4866

积分

论坛元老

积分
4866
发表于 2024-10-14 20:24:57 来自手机 | 显示全部楼层
感觉如果定时器足够还是定时器延时好点,资源占用方面也好很多。
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:422
  • 最近打卡:2025-05-01 09:54:52
已绑定手机

19

主题

3190

回帖

4866

积分

论坛元老

积分
4866
发表于 2024-10-14 20:25:00 来自手机 | 显示全部楼层
感觉如果定时器足够还是定时器延时好点,资源占用方面也好很多。
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:417
  • 最近打卡:2025-04-30 21:39:09
已绑定手机

34

主题

2096

回帖

2206

积分

荣誉版主

积分
2206
发表于 2024-10-14 22:05:10 | 显示全部楼层
定时器周期中断+软定时器+状态机,能解决90%以上需要延时的场合,非阻塞、高效、扩展性能好。
1 喜欢他/她就送朵鲜花吧,赠人玫瑰,手有余香!
睁开眼睛做场梦~~~
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:229
  • 最近打卡:2025-05-01 13:30:16
已绑定手机

3

主题

45

回帖

682

积分

高级会员

积分
682
发表于 2024-10-14 23:34:31 | 显示全部楼层
C语言里面还能执行汇编的吗,我是小白有点不懂
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:常住居民III
  • 打卡总天数:142
  • 最近打卡:2025-04-30 09:17:52

11

主题

71

回帖

573

积分

高级会员

积分
573
发表于 2024-10-15 08:45:14 | 显示全部楼层
汇编不受优化等级影响

点评

学到了,谢谢  发表于 2024-10-15 09:32
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:440
  • 最近打卡:2025-04-30 08:02:54
已绑定手机

4

主题

269

回帖

1246

积分

金牌会员

积分
1246
发表于 2024-10-15 09:14:31 | 显示全部楼层
YYY*** 发表于 2024-10-14 23:34
C语言里面还能执行汇编的吗,我是小白有点不懂

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

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:520
  • 最近打卡:2025-05-01 08:06:21

109

主题

1897

回帖

5204

积分

论坛元老

积分
5204
发表于 2024-10-15 09:20:04 | 显示全部楼层
能用汇编语言来作软件延时是比较准确的
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:383
  • 最近打卡:2025-04-30 09:42:19

40

主题

194

回帖

601

积分

高级会员

积分
601
发表于 2024-10-15 10:06:58 | 显示全部楼层
我想知道(unsigned int MS)和(unsigned int uS)参数是如何传递给汇编代码的?
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:383
  • 最近打卡:2025-04-30 09:42:19

40

主题

194

回帖

601

积分

高级会员

积分
601
发表于 2024-10-15 11:10:20 | 显示全部楼层
经过仔细查看汇编代码,感觉C涵数内嵌入的汇编代码,参数是固定传给R6和R7的,且高位在R6,低位在R7。
我这样理解对吗?

JZ JSx51_BIOS_Delay_MS_01;
INC R6;
这两句没明白什么意思?如果R7为0,R6为什么要加1呢?

点评

谢谢你的提问,我想这也是其他网友想了解的知识。 (1)C51/C251和金水151编译器的函数调用规范之一,如果函数只有一个参数:如果参数是字节型的,放在R7中,如果参数是2字节型的,放在R6R7中,其中R6是高位字节,  详情 回复 发表于 2024-10-15 12:06
回复 支持 反对

使用道具 举报 送花

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

本版积分规则

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

GMT+8, 2025-5-2 06:28 , Processed in 0.184562 second(s), 113 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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