点击上方“大鱼机器人”,选择“置顶/星标公众号

福利干货,第一时间送达!

前言

对于某些对时间精度要求较高的程序,用 c 写延时显得有些力不从心,故需用到汇编程序。

本人通过测试,总结了 51 的精确延时函数(在 c 语言中嵌入汇编)分享给大家。至于如何在 c 中嵌入汇编大家可以去网上查查,这方面的资料很多,且很简单。

以 12MHz 晶振为例,12MHz晶振的机器周期为 1us,所以,执行一条单周期指令所用时间就是 1us,如 NOP 指令。下面具体阐述一下。

若要延时 1us,则可以调用_nop_();函数,此函数是一个 c 函数,其相当于一个 NOP 指令

使用时必须包含头文件 intrins.h

例如:

#include <intrins.h>
#include <reg52.h>
void main(void)
{P1 = 0x0;_nop_(); //延时 1usP1 = 0xff;
}

延时 5us,则可以写一个delay_5us()函数

delay_5us()
{#pragma asmnop#pragma endasm
}

这就是一个延时 5us 的函数,只需要在需要延时 5us 时调用此函数即可。或许有人会问,只有一个 NOP 指令,怎么是延时 5us 呢?

答案是:

在调用此函数时,需要一个调用指令,此指令消耗 2个周期(即 2us);函数执行完 毕时要返回主调函数,需要一个返回指令,此指令消耗 2 个周期(2us)。调用和返回消耗了

2us + 2us = 4us。然后再加上一个NOP指令消耗 1us,不就是5us吗?

延时 10us

我们编写一个 delay_10us()函数

delay_10us(){
#pragma asm
nop
nop
nop
nop
nop
nop
#pragma endasm
}

这就是延时 10us 的函数。同延时 5us 函数一样,调用和返回消耗 4us,加上函数中的6个 NOP 指令6us,正好是10us

此时有人不禁要问那么,任意微秒时,函数应该怎么写呢?

看我慢慢道来:首先,延时任意微秒我暂时没有想到,但是,我可以延时任意偶数微秒或延时任意奇数微秒, 也就是说,需要两个函数,一个函数专门实现任意偶数的微秒级延时,另一个函数专门实现 任意奇数的微秒级延时。只要有了这两个函数在,不就可以延时任意的微秒了吗!

首先我们来实现任意偶数的微秒级延时:

void delay_even_us(unsigned char even){ //任意偶数的微秒级延时
#pragma asm
1 mov a, r7 //为什么要用到 r7 呢,因为 r7 里面装的是函数的参数!!!
// ^_^ 这句消耗 1 个周期
2 subb a, #10H //这句看完程序我再解释 这句消耗 1 个周期
3 mov b, #02H //这句看完程序我再解释 这句消耗 2 个周期
4 div ab // 这句意思是 a/b ,商放在 a 里,余数放在 b 里 稍
//后解释 这句消耗 4 个周期
5 mov r0, a //这句消耗 1 个周期
6 nop //这句消耗 1 个周期
7 loop:
8 djnz r0, loop //不等于 0 跳转指令,也就是说 r0 中的值若不为 0 的话,
//就跳转到 loop 处 这句消耗 2 个周期
#pragma endasm
}

下面我们来分析一下为何这样写:为了方便分析,我给句子编上了序号。我们以延时 100us为例(delay_even_us(100))。

首先减去调用和返回的 4 个周期(4us)。再减去参数传递所消耗的2 个周期。因为 c 函数参数传递到汇编是需要消耗周期的。一共消耗了 6 个周期。也就是消 耗了 6us,还剩下 100us-6us=94us。

然后再看我再程序上面注释的各语句消耗时间:

从 1 句到 5 句一共消耗了 10 个周期(不信你数数^_^)。还剩下 94us-10us=84us。

现在就看第 8 句了,这句应该消耗 84 个周期才能达到我们延时 100us。而这句每执行一次消耗 2 个周期,也就是说 r0 的值应该为 84/2=42。

那么,怎样达到 r0=42 的呢?我们从第 1 句开始分析:

第 1 句中,r7 为 c 传递过来的参数,此例子中为 100.执行完此句后 a 的值为 100;

第 2 句中,将 a=a-16 = 100-16=84。此句结束后 a 的值为 84;

第 3 句中,给 b 赋值为 2;

第 4 句中,用 a 来除以 b。结果商存入 a 中,余数存入 b 中,此句结束后 a 的值为 a=a/b = 84/2= 42;

第 5 句,将 a 值赋给 r0,此句结束后 r0 的值为 42。

于是乎, r0 的值为 42 这个目的达到了。结合前面的分析,此程序是不是延时了 100us 呢?

答案当然是 “”了!

这个函数可以实现任意偶数微秒(>=18)的延时的,不信的话可以带一个值进去算的。至于为什么值必须>=18us,用不着我解释了吧。

任意奇数的微秒级延时:

void delay_odd_us(unsigned char odd){
#pragma asm
1 mov a, r7
2 subb a, #0fH
3 mov b, #02H
4 div ab
5 mov r0, a
6 loop1:
7 djnz r0, loop1
#pragma endasm
}

此即为任意奇数微秒的延时,和偶数延时一样的道理,不解释了。^_^

此函数的参数必须大于等于 17,请思考为什么?^_^

-END-

整理文章为传播相关技术,版权归原作者所有 |

| 如有侵权,请联系删除 |

往期好文合集

为什么很多单片机的工作电压是5V?

只有6个引脚的单片机,居然可以玩游戏。

单片机这个知识点一定要会!两大延时方法总结

最 后

 

若觉得文章不错,转发分享,也是我们继续更新的动力。

5T资源大放送!包括但不限于:C/C++,Linux,Python,Java,PHP,人工智能,PCB、FPGA、DSP、labview、单片机、等等

在公众号内回复「更多资源」,即可免费获取,期待你的关注~

呵,你会51单片机的精确延时吗?相关推荐

  1. 51单片机的nop延时延时函数

    nop()–延时函数 1.C语言中没有_nop_()函数,在51C中一般包含在头文件中 #include "intrins.h" 2.该函数是在51单片机中用的延时函数,nop() ...

  2. 51c语言延时作用,51单片机C语言延时函数怎么定义和使用

    描述 51单片机C语言延时函数怎么定义 C语言定义延时函数主要通过无意义指令的执行来达到延时的目的.C程序中可使用不同类型的变量来进行延时设计.经实验测试,使用unsigned char类型具有比un ...

  3. 51单片机c语言延时时间计算,单片机定时器延迟时间计算

    关于时间单位1s=1000ms毫秒=10-3秒 1ms=1000us微秒=10-6秒 1us=1000ns纳秒=10-9秒 1ns=1000ps皮秒=10-12秒 1ps=1000fs飞秒=10-15 ...

  4. 8051系列单片机软件精确延时研究(二)

    续前篇 8051单片机软件精确延时研究(一) 由前篇可知,在DelayX10us()函数中用for循环延时会产生10个机器周期的固定误差,其中X传值.调用函数.子函数返回共5个机器周期,这是只要调用带 ...

  5. 51单片机c语言延时计算软件,51单片机精确延时程序大集合+初值计算工具

    在论坛上看到不少不错的延时程序,整理如下共同分享: 精确延时计算公式: 延时时间=[(2*第一层循环+3)*第二层循环+3]*第三层循环+5 ;延时5秒左右 DELAY5S:PUSH   04H;2个 ...

  6. 89C52单片机定时器精确延时

    16位寄存器分为高八位(TH0)和低八位(TLO),取值范围0-65535 也就是低八位255,高八位255(255*255=65535) 问题:89C52开发板 晶振11.0592MHZ    用定 ...

  7. 学习笔记 51单片机通用软件延时方法

    对于STC51单片机来说,延时函数,想必都不陌生.而用的最多的延时基本都是通过软件方法实现的,但由于STC51不同系列的芯片所采用的指令集不同,各指令执行所用机器周期不同.例如STC12Cx的一个振荡 ...

  8. 延时1us程序12mhz晶振c语言,51单片机 Keil C 延时程序的简单(晶振12MHz,一个机器周期1us.)...

    一. 500ms延时子程序 void delay500ms(void) { unsignedchari,j,k;for(i=15;i>0;i--)for(j=202;j>0;j--)for ...

  9. 51单片机c语言延时库,51单片机c语言---延时

    1,_nop_()适用于us级的少量延时 标准的C语言中没有空语句.但在单片机的C语言编程中,经常需要用几个空指令产生短延时的效果. 这在汇编语言中很容易实现,写几个nop就行了.本文引用地址:htt ...

最新文章

  1. 强烈安利8个高质量的办公软件,提高你的办公效率
  2. [Vue.js进阶]从源码角度剖析vue-router(三)
  3. mysql数据库as表恢复_使用flashback database找回被误删除表空间
  4. CSS Overflow属性详解(转)
  5. Java基础day4
  6. 【实践驱动开发3-005】TI WL1835MODCOM8 在android的移植 - SDIO and wifi 基础
  7. 视觉SLAM笔记(63) RGB-D 稠密建图
  8. 小米MIXAlpha将首发1亿像素传感器:1/1.33英寸大底业内无敌
  9. request.getParameterValues与request.getParameter的区别
  10. android新闻客户端实验报告,基于Android平台的新闻客户端设计与实现
  11. 基于Attention Model的Aspect level文本情感分类---用Python+Keras实现
  12. python正则表达式处理文本内容_Python处理txt文本
  13. 5个Web前端开发软件,零基础入门完全够用了!
  14. 批量重命名文件、图片、去除括号
  15. 传智教育|如何转行互联网高薪岗位之一的软件测试?(附软件测试学习路线图)
  16. c语言51单片机调节led亮度,51单片机中用PWM控制LED亮度调节
  17. Java 面向对象(下) 抽象类 继承类 编写Application程序: 定义抽象类Shapes,其中包含抽象方法:
  18. vue 移动端进入页面自动弹出软键盘
  19. 微信小程序 java nodejs校园自动点餐系统
  20. win10误删系统变量path恢复方法

热门文章

  1. 如何把SAP UI5应用部署到SAP云平台的Fiori Launchpad里去
  2. 如何以sandbox模式测试开发好的Fiori Launchpad插件
  3. Fiori Elements value help selection pass back
  4. Provisional headers are shown in Chrome network tab
  5. word自定义模板的存储位置
  6. message show_once这个标志位的用法
  7. 如何处理word document webservice response中奇怪的xml node
  8. 一些使用javap反编译出来的结果分析
  9. Jerry的ABAP, Java和JavaScript乱炖
  10. Win10计算机首次使用时间,如何查看Win10开机运行了多长时间