呵,你会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,加上函数中的6NOP 指令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,请思考为什么?^_^

#推荐阅读:

    专辑|Linux文章汇总

    专辑|程序人生

    专辑|C语言

嵌入式Linux

微信扫描二维码,关注我的公众号 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/467082.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

SignalR

原址: http://www.cnblogs.com/shanyou/archive/2012/07/28/2613693.html SignalR是什么&#xff1f; SignalR是一个继承的客户端与服务器库&#xff0c;基于浏览器的客户端和基于ASP.NET的服务器组件可以借助它来进行双向多步对话&#xff0c;换句话说&#xff0c;该对话可不…

C语言——数组、函数、指针

C语言——数组、函数、指针 宗旨&#xff1a;技术的学习是有限的&#xff0c;分享的精神是无限的。 1、有什么作用&#xff1f;为什么要使用它们&#xff1f; &#xff08;1&#xff09;数组&#xff1a;提供一段连续的存储空间&#xff0c;存数据和字符串很方便&#xff1b; …

--4、实验室设备管理(表)

--4、实验室设备管理create table Computer( Computer_id int Identity Primary key,--设备编号 Computer_name varchar(50) not null,--设备名称 Computer_num varchar(50) not null,--设备编号,财产号 room_id int not null,--实验室编号 --Computer_IP varchar(128), -…

十六进制转十进制

问题描述从键盘输入一个不超过8位的正的十六进制数字符串&#xff0c;将它转换为正的十进制数后输出。注&#xff1a;十六进制数中的10~15分别用大写的英文字母A、B、C、D、E、F表示。样例输入FFFF样例输出65535 #include<stdio.h> #include<string.h> #include<…

C#中Invoke的用法

在用.NET Framework框架的WinForm构建GUI程序界面时&#xff0c;如果要在控件的事件响应函数中改变控件的状态&#xff0c;例如&#xff1a;某个按钮上的文本原先叫“打开”&#xff0c;单击之后按钮上的文本显示“关闭”&#xff0c;初学者往往会想当然地这么写&#xff1a; v…

三类危险的TXT文件

一。 隐藏HTML扩展名的TXT文件 假如您收到的邮件附件中有一个看起来是这样的文件&#xff1a;QQ 放送.txt&#xff0c;您是不是认为它肯定是纯文本文件&#xff1f;我要告诉您&#xff0c;不一定&#xff01;它的实际文件名可以是QQ 放送.txt{3050F4D8-98B5-11CF-BB82-00AA00BD…

嵌入式如何入门,要不要学习Python

#提问我是你的公众号读者朋友&#xff0c;江苏省在读大学生一名&#xff0c;目前是大四免研。研究生方向是嵌入式系统与应用(导师招这样的学生&#xff0c;但是本身设计这个方向不多)&#xff0c;目前还比较有时间&#xff0c;想要自己深入学习一下嵌入式方面的知识&#xff0c…

13.强符号和弱符号

我们在编写代码的过程中经常会遇到一种叫做符号重复定义&#xff08;Multiple Definition&#xff09;的错误&#xff0c;这是因为在多个源文件中定义了名字相同的全局变量&#xff0c;并且都将它们初始化了。 例如&#xff0c;在 a.c 中定义了全局变量 global&#xff1a; int…

C语言——预编译

C语言——预编译 宗旨&#xff1a;技术的学习是有限的&#xff0c;分享的精神是无限的。 在C 语言中&#xff0c;并没有任何内在的机制来完成如下一些功能&#xff1a;在编译时包含其他源文件、定义宏、根据条件决定编译时是否包含某些代码。要完成这些工作&#xff0c;就需要使…

深入理解cache对写好代码至关重要

There are only two hard things in Computer Science: cache invalidation and naming things.-- Phil Karlton全文目录CACHE基础CACHE的组织TAG,INDEXVIVT,VIPT,PIPTCache别名问题CACHE一致性icache、dcache同步多CPU核cache同步CPU与设备cache同步意识到CACHE的编程perf中的…

[推举]网络工程师必懂的专业术语

路由器问题&#xff1a; 1、什么时候使用多路由协议&#xff1f; 当两种不同的路由协议要交换路由信息时&#xff0c;就要用到多路由协议。当然&#xff0c;路由再分配也可以交换路由信息。下列情况不必使用多路由协议&#xff1a; 从老版本的内部网关协议&#xff08; Interio…

基础练习 特殊回文数

问题描述123321是一个非常特殊的数&#xff0c;它从左边读和从右边读是一样的。输入一个正整数n&#xff0c; 编程求所有这样的五位和六位十进制数&#xff0c;满足各位数字之和等于n 。输入格式输入一行&#xff0c;包含一个正整数n。输出格式按从小到大的顺序输出满足条件的整…

IO流--buffer

示例展示&#xff1a; package buffer;import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.I…

Linux 用户空间和内核空间

最近在微信群里看到有人提这个问题&#xff0c;然后查了下资料&#xff0c;觉得这篇文章是写得最能让人看懂的&#xff0c;分享给大家。欢迎大家评论说出自己的见解&#xff0c;让更多的人更容易理解这部分知识。之前的相关文章Linux内存&#xff0c;先看这篇文章Linux物理内存…

数据库的学习

自从搬到那边学校去了&#xff0c;就好久都没有写过我的学习了。因为没那么多时间上网了&#xff0c;有时候去网吧上网也不想写了。又开始了一本书的学习&#xff0c;那就是数据库。还记得去年那个时候学数据库的时候&#xff0c;大家都说我们学会最多的就是ctrlc和ctrlv&#…

2017.12.20-21

1.今天&#xff0c;继续学习公司产品DDS的开发手册。 首先&#xff0c;其中有几个概念需要认识&#xff1a; CORBA(Common Object Request Broker Architecture):公共对象的请求代理体系结构&#xff0c;OMG组织定义的一种面向对象应用的标准国际规范架构。为简化跨平台应用而提…

C语言——宏定义

C语言——宏定义 宗旨&#xff1a;技术的学习是有限的&#xff0c;分享的精神是无限的。 注意&#xff1a;宏定义不是函数&#xff01;&#xff01; 一般用来简化操作的&#xff0c;但又能避免函数调用那样需要进行切换环境&#xff0c;花费时间。例如&#xff1a; #define ma…

一个深入学习Linux/C/C++的原创技术号

今天给大家推荐一个Linux/C/C领域的公众号&#xff0c;大家都知道这个领域的号不多&#xff0c;而【编程珠玑】就是这样一个专注该领域的原创类公众号&#xff0c;原创占比95%以上&#xff0c;目前已有原创文章200多篇&#xff0c;而且原创间环环相扣&#xff0c;皆有关联。公众…

Redis Java调用

Redis Java调用 package com.stono.redis;import redis.clients.jedis.Jedis;public class RedisJava {public static void main(String[] args) {Jedis jedis new Jedis("localhost");System.out.println("ok");System.out.println("ping "jed…

Linux 资料大全

Hello all&#xff0c;给大家分享一些 Linux 学习资料&#xff0c;包含&#xff1a;社区网站、在线教程、命令大全、在线模拟器、经典书籍、镜像站点等 ...从入门到进阶&#xff0c;应有尽有。无论你是小白&#xff0c;还是 Linux 高手&#xff0c;都不容错过&#xff0c;100% …