呵,你会51单片机的精确延时吗?
点击上方“大鱼机器人”,选择“置顶/星标公众号”
福利干货,第一时间送达!
前言
对于某些对时间精度要求较高的程序,用 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单片机的精确延时吗?相关推荐
- 51单片机的nop延时延时函数
nop()–延时函数 1.C语言中没有_nop_()函数,在51C中一般包含在头文件中 #include "intrins.h" 2.该函数是在51单片机中用的延时函数,nop() ...
- 51c语言延时作用,51单片机C语言延时函数怎么定义和使用
描述 51单片机C语言延时函数怎么定义 C语言定义延时函数主要通过无意义指令的执行来达到延时的目的.C程序中可使用不同类型的变量来进行延时设计.经实验测试,使用unsigned char类型具有比un ...
- 51单片机c语言延时时间计算,单片机定时器延迟时间计算
关于时间单位1s=1000ms毫秒=10-3秒 1ms=1000us微秒=10-6秒 1us=1000ns纳秒=10-9秒 1ns=1000ps皮秒=10-12秒 1ps=1000fs飞秒=10-15 ...
- 8051系列单片机软件精确延时研究(二)
续前篇 8051单片机软件精确延时研究(一) 由前篇可知,在DelayX10us()函数中用for循环延时会产生10个机器周期的固定误差,其中X传值.调用函数.子函数返回共5个机器周期,这是只要调用带 ...
- 51单片机c语言延时计算软件,51单片机精确延时程序大集合+初值计算工具
在论坛上看到不少不错的延时程序,整理如下共同分享: 精确延时计算公式: 延时时间=[(2*第一层循环+3)*第二层循环+3]*第三层循环+5 ;延时5秒左右 DELAY5S:PUSH 04H;2个 ...
- 89C52单片机定时器精确延时
16位寄存器分为高八位(TH0)和低八位(TLO),取值范围0-65535 也就是低八位255,高八位255(255*255=65535) 问题:89C52开发板 晶振11.0592MHZ 用定 ...
- 学习笔记 51单片机通用软件延时方法
对于STC51单片机来说,延时函数,想必都不陌生.而用的最多的延时基本都是通过软件方法实现的,但由于STC51不同系列的芯片所采用的指令集不同,各指令执行所用机器周期不同.例如STC12Cx的一个振荡 ...
- 延时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 ...
- 51单片机c语言延时库,51单片机c语言---延时
1,_nop_()适用于us级的少量延时 标准的C语言中没有空语句.但在单片机的C语言编程中,经常需要用几个空指令产生短延时的效果. 这在汇编语言中很容易实现,写几个nop就行了.本文引用地址:htt ...
最新文章
- 强烈安利8个高质量的办公软件,提高你的办公效率
- [Vue.js进阶]从源码角度剖析vue-router(三)
- mysql数据库as表恢复_使用flashback database找回被误删除表空间
- CSS Overflow属性详解(转)
- Java基础day4
- 【实践驱动开发3-005】TI WL1835MODCOM8 在android的移植 - SDIO and wifi 基础
- 视觉SLAM笔记(63) RGB-D 稠密建图
- 小米MIXAlpha将首发1亿像素传感器:1/1.33英寸大底业内无敌
- request.getParameterValues与request.getParameter的区别
- android新闻客户端实验报告,基于Android平台的新闻客户端设计与实现
- 基于Attention Model的Aspect level文本情感分类---用Python+Keras实现
- python正则表达式处理文本内容_Python处理txt文本
- 5个Web前端开发软件,零基础入门完全够用了!
- 批量重命名文件、图片、去除括号
- 传智教育|如何转行互联网高薪岗位之一的软件测试?(附软件测试学习路线图)
- c语言51单片机调节led亮度,51单片机中用PWM控制LED亮度调节
- Java 面向对象(下) 抽象类 继承类 编写Application程序: 定义抽象类Shapes,其中包含抽象方法:
- vue 移动端进入页面自动弹出软键盘
- 微信小程序 java nodejs校园自动点餐系统
- win10误删系统变量path恢复方法
热门文章
- 如何把SAP UI5应用部署到SAP云平台的Fiori Launchpad里去
- 如何以sandbox模式测试开发好的Fiori Launchpad插件
- Fiori Elements value help selection pass back
- Provisional headers are shown in Chrome network tab
- word自定义模板的存储位置
- message show_once这个标志位的用法
- 如何处理word document webservice response中奇怪的xml node
- 一些使用javap反编译出来的结果分析
- Jerry的ABAP, Java和JavaScript乱炖
- Win10计算机首次使用时间,如何查看Win10开机运行了多长时间