只需两步便可生成 51 单片机最精准的延时函数

前言

我们在学习 51 单片机的过程中会用到延时,比如一个简单的流水灯就需要延时来控制依次点亮的时间,或者一些模块在单片机发出读数据指令后,需要延时几十微秒才可以读出数据等等,这些都离不开延时,所以我们需要一个精准的延时函数来满足我们的需求。

本篇介绍一个最简单并且延时最精准的 51 单片机延时函数的生成方法。

STC-ISP

我们说学习 51 单片机,大部分学习的都是国产的 STC89C51 单片机,我就是从这款单片机入门的。

STC89C51 是 STC 这家公司研发生产的,同时 STC 提供了一个下载编程烧录软件——STC-ISP,这款软件可是一个好东西,不会有朋友只用它来下载程序吧?

它有好多强大且实用的功能,本篇介绍一下它的软件延时计算器功能。

如何下载

进入 STC 官网,将页面向下就可以找到下载链接啦。

STC 官网 >> 点击跳转

如何使用

打开软件,找到“ 软件延时计算器 ”,设置参数后,点击生成代码后复制即可。

注意:设置的参数一定要和使用的单片机参数相匹配。

优化代码

void Delay1ms()		//@11.0592MHz
{
	unsigned char i, j;

	_nop_();
	i = 2;
	j = 199;
	do
	{
		while (--j);
	} while (--i);
}

上面是我从软件中生成复制的代码,软件已经自动生成了一个函数供我们调用,短短几步就做好了一个延时函数,确实不错。

但这个函数在调用时只能延时 1ms ,如果说我想延时 2ms、3ms、4ms... 难道要不停的调用函数吗?或者再去软件中生成新的延时函数?那岂不是很麻烦。

其实不必这样,我们只需简单的优化一下代码,就可以实现我们想要的功能。

更改思路如下:

软件所生成的函数是延时 1ms,就是说单片机执行这个函数的程序体时用时为 1ms

理解这个以后,我们便可以优化程序啦。

首先我们用 while 循环把程序体框住,然后每执行一次让控制 while 循环结束的变量减一,这个变量我们通过形参传递到函数中。

注意:当使用 _nop_() 函数(可理解为软件延时)时,必须在开头添加头文件 #include <intrins.h>

_nop_() 函数相当于一个空操作(可以理解为 NOP 空操作指令),而 _nop_() 函数的空操作产生的时间与晶振有关,所以在上文中设置参数要与使用的单片机参数相匹配。

优化后的代码如下:

#include <intrins.h>

void Delay1ms(unsigned int _ms)		//@11.0592MHz
{
    unsigned char i, j;

    while (_ms--)
    {
        _nop_();
        i = 2;
        j = 199;
        do
        {
            while (--j);
        } while (--i);
    }
}

如何调用

经过我们优化后的延时函数在调用时极其简单,只需在调用函数的语句中放入实参就好啦。

调用演示代码如下:

#include <reg52.h>
#include <intrins.h>

void Delay1ms(unsigned int _ms);        /* 声明延时函数 */

void main()
{
    Delay1ms(1);        /* 实参为 1,则延时 1ms */

    Delay1ms(20);       /* 实参为 20,则延时 20ms */

    Delay1ms(500);      /* 实参为 500,则延时 500ms */

    /* ...... */
}


void Delay1ms(unsigned int _ms)		//@11.0592MHz
{
    unsigned char i, j;

    while (_ms--)
    {
        _nop_();
        i = 2;
        j = 199;
        do
        {
            while (--j);
        } while (--i);
    }
}

后记

至此,51 单片机的延时函数就编写完成啦, 快去试着生成一个延时函数,将它应用到你的项目当中吧。

本文作者:main工作室

本文链接:http://www.cnblogs.com/main-studio/p/17059320.html

版权声明:本文为「main工作室」的原创文章,遵循 CC BY-NC-ND 4.0 版权协议,著作权归作者所有,转载请注明出处!

鼓励博主:如果您觉得文章对您有所帮助,可以点击文章右下角【推荐】一下。您的鼓励就是博主最大的动力!

本文转载于网络 如有侵权请联系删除

相关文章

  • 滴滴派单规则分析

    大家好,又见面了,我是你们的朋友全栈君。滴滴派单规则1批量匹配(全局最优)派单策略主要的原则是:站在全局视角,尽量去满足尽可能多的出行需求,保证乘客的每一个叫车需求都可以更快更确定的被满足,并同时尽力去提升每一个司机的接单效率,让总的接驾距离和时间最短。这个算法几乎是所有类似派单系统为了解决这个问题的最基础模型,在Uber叫做BatchingMatching,滴滴叫做“全局最优”或者“延迟集中分单”。2基于供需预测的分单(大数据预测)利用对未来的预测:如果我们预测出未来一个区域更有可能有更多的订单/司机,那么匹配的时候就让这个区域的司机/订单更多去等待匹配这同一个区域的订单/司机。3连环派单将订单指派给即将结束服务的司机,条件为如果司机的终点与订单位置很相近。司机在结束上一单服务后,会立刻进入新订单的接单过程中,有效地压缩了订单的应答时间、以及司机的接单距离。4安全派单在一些深夜订单中,如果打车人是女性,订单系统会更多考虑安全因素。根据司机、乘客订单的实际情况,从200多个角度计算司乘双方是否适合一起出行。乘客角度包含:性别、出行习惯、订单时间、订单距离、起止位置等信息。司机角度包括:

  • 如何判断用户的真实需求

    以下文章来源于满赋诸机,作者idealismxxm大家好,我是小满。今天分享一下判断用户真实需求的方法。用户无法描述真实需求用户往往是无法说清楚自己的真实需求,他们通常只能说出自己想要的。而用户想要的一般都经过了加工转换,以为想要的能解决遇到的其他问题,而这个要解决的问题才是用户的真实需求。正如一句著名的话:“用户不是要买钻头,而是要买墙上的洞”。这让小满想起来前几天和产品朋友聊天的内容,他提到我们乘坐的交通工具从古至今换了很多种。 并且每个时代的用户想要的都不一样,从马车到自行车,再到汽车飞机等等。在这些工具出现之前,用户都不知道自己想要这样的交通工具。但用户的真实需求却一直都没有变,也就是从一个地方快速移动到另一个地方。那么以后如果空间传送能实现的话,用户想要的交通工具就会再次变化。 想要和真实需求《乔布斯传》中也提到“人们不知道想要什么,直到你把它摆在他们面前”。以前大家认为平板电脑需要外接键盘和手写笔,但乔布斯发现其中的真实需求是能打字和屏幕上操作。所以其实只要解决了这两个根本问题,想要外设的需求就不存在了。这要求我们不断从用户需求调研中发掘真实需求,这样的需求才有共性,才可以

  • 吐槽下坑爹的主机屋

    大家好! 众所周知 建网站离不开域名和建站主机但这两样东西大多都是需要付费的  这几天打算再建个网站 所以在西部数码里买好了一个域名(因为西数的域名便宜) 现在就差主机了 但钱买域名用光了 所以现在只能去度娘找下有没有免费的空间(碰碰运气) 去度娘一查 果然有而且还不少 但这些网站总感觉不稳定 万一跑路了怎么办(虽然是免费主机 没有成本),但还是希望找一个稳定的主机  突然看到了主机屋 我马上想了起来 之前朋友推荐过 于是打开看看 果真有免费主机于是我就注册了一个 经过一系列程序 包括关注微信公众号什么的 折腾了好长时间最后可算有了一个属于自己的主机 一看 居然是个二级域名 这倒也无所谓反正可以改 只要域名能解析就行了正当我改域名的时候让我生气的第一件事发生了woc 必须用他们的域名(那我西数的域名岂不是白买了) 算了……我还是去域名商那搞个跳转吧 跳转到二级域名(此时换了个浏览器)于是成功跳转……第二件令我气愤的事:woc 需要FTP密码才能访问? 我打算建个论坛或者博客 如果这样的话 每个访客都得和我要FTP密码不成?还是我建网站单纯给自己看呢?算了……好心的我接着忍 毕竟主机是需

  • Rest Notes-REST架构的元素

    摘要:上篇文章是对REST的风格推导,本篇是对REST架构中元素做解释 正文:REST架构的元素数据元素(DataElements)在分布式对象风格中,所有的数据被封装和隐藏在数据的处理组件之中。于分布式对象不同的是,REST的关键方面之一是架构的数据元素的性质和状态。在分布式超媒体的特性中,当用户选择了一个链接后,该链接所指向的信息需要从其存储地移动到其使用地。对于一个分布式超媒体系统的架构师而言,他只能在三种选项中做出选择:在数据所在地对数据进行呈现,并向接收者发送一个固定格式的镜像;把数据和呈现引擎封装起来,一起发送给接收者;发送原始数据可一些描述数据类型的元数据,让接收者自己去呈现。第一种选项对应于传统的客户-服务器风格,将与数据的自然特性有关的所有信息都被隐藏在数据发送者之中,简化了客户端的实现。但是也严重限制了接收者的功能,并且将大部分处理负担都放在了发送者这一边,从来导致伸缩性的问题第二种对应于可移动对象风格,它支持对于信息的隐藏还可以通过唯一的呈现引擎来支持对于数据的专门处理。但是它将接收者的功能限制在引擎所能预测的范围之内,还大幅增加需要移交的数据量第三种选项允许发送

  • 33:计算分数加减表达式的值

    33:计算分数加减表达式的值总时间限制: 1000ms内存限制: 65536kB描述编写程序,输入n的值,求1/1-1/2+1/3-1/4+1/5-1/6+1/7-1/8+...+(-1)n-1·1/n的值。 输入输入一个正整数n。1<=n<=1000。输出输出一个实数,为表达式的值,保留到小数点后四位。样例输入2复制 样例输出0.5000复制1e<iostream> 2#include<cstdio> 3#include<cstring> 4#include<cmath> 5usingnamespacestd; 6intmain() 7{ 8intn; 9cin>>n; 10doubletot=0; 11doublefm=1; 12for(inti=1;i<=n;i++) 13{ 14if(i%2==0) 15{ 16tot=tot-(1/fm); 17fm++; 18} 19else 20{ 21tot=tot+(1/fm); 22fm++; 23} 24} 25printf("%.4lf&qu

  • 腾讯云云点播删除转码模板api接口

    1.接口描述接口请求域名:vod.tencentcloudapi.com。 删除用户自定义转码模板。 默认接口请求频率限制:100次/秒。 APIExplorer提供了在线调用、签名验证、SDK代码生成和快速检索接口等能力。您可查看每次调用的请求内容和返回结果以及自动生成SDK调用示例。 2.输入参数以下请求参数列表仅列出了接口请求参数和部分公共参数,完整公共参数列表见公共请求参数。 参数名称 必选 类型 描述 Action 是 String 公共参数,本接口取值:DeleteTranscodeTemplate。 Version 是 String 公共参数,本接口取值:2018-07-17。 Region 否 String 公共参数,本接口不需要传递此参数。 Definition 是 Integer 转码模板唯一标识。 SubAppId 否 Integer 点播子应用ID。如果要访问子应用中的资源,则将该字段填写为子应用ID;否则无需填写该字段。 3.输出参数 参数名称 类型 描述 RequestId String 唯一请求

  • 腾讯云云游戏计费相关问题

    已购买的机器还能更换地域么?已购买的云游戏并发不支持更换地域。若您有更换地域的需求,可参考以下解决方式:先退还并发,再重新购买并发。 说明: 退还实例的费用请参考退费说明。 云游戏并发支持配置升级么?已购买的云游戏并发暂不支持配置升级。若您有配置升级的需求,可参考以下解决方式:先退还并发,再重新购买并发。 说明: 退还实例的费用,请参见退费说明。 是否支持无理由退款?支持,详情请参见退费说明。

  • 《增长黑客》—— 读后总结

    之前读到四分之三的时候,手机丢了,无奈放弃微信读书就没继续读;后来换了手机,终于把这本书给续上了。 第一章增长黑客的崛起 第二章创造正确的产品 第三章获取用户 第四章激发活跃 第五章提高留存 第六章增加收入 第七章病毒传播 第八章完整案例 附录——关注的指标 作者:xingoo 出处:http://www.cnblogs.com/xing901022 本文版权归作者和博客园共有。欢迎转载,但必须保留此段声明,且在文章页面明显位置给出原文连接!

  • Linux 系统镜像分类和包管理工具

    查看系统版本 cat/proc/version复制 可以看到如下返回,Linux是RedHat系统 Linuxversion4.18.0-372.9.1.el8.x86_64(mockbuild@x86-vm-09.build.eng.bos.redhat.com)(gccversion8.5.020210514(RedHat8.5.0-10)(GCC))#1SMPFriApr1522:12:19EDT2022复制 Linux系统分类 Debian:Debian,Ubuntu,Mint RedHat:RedHat,Fedora,CentOs 其它版本 Linux的包管理工具 RedHat系列的包管理工具:yum Debian系列的包管理工具:apt-get

  • MatConvNet深度学习工具箱安装教程

    @目录前言介绍环境安装过程1.Matlab2015b2.VisualStudio20153.MatConvNet参考 前言 为了跑一个光场重建的代码,不得不用这个matconvnet工具箱,安装过程中碰到点问题,记录一下 介绍 MatConvNet是一个实现卷积神经网络(CNN)的Matlab工具箱,主要应用于计算机视觉。 环境 Win764bit Matlab2015b VisualStudio2015 MatConvNet 安装过程 1.Matlab2015b Matlab2015b的安装就不说了,按网上其他的一些教程安装就行了。使用时最好以管理员身份运行 2.VisualStudio2015 下载地址 安装过程中注意选择编译语言为C++,不然据说后面Matlab和VS编译器连接会报错 3.MatConvNet 下载地址 a.MatConvNet官网下载 b.Github下载 第一个下载地址下的实在慢,我就换Github的地址下了。 将下载得到的ZIP文件夹解压并放入Matlab2015b的安装路径中 我将解压后的文件放在toolbox文件夹下,放在R2015的其他文

  • 02. git基本命令(适合于单机使用)

    1.进入要管理的目录 2. git init           //做初始化,使用git管理当前文件夹 3. gitstatus    //检测当前目录下文件的状态 4.3种状态的变化   · red:新增的文件/ 修改了的原老文件。  --> git add 文件名  /  gitadd.    //添加要管理的文件/添加当前文件夹中的所有文件   · green:git已经管理起来的文件。       -->gitcommit-m"描述信息"   //提交,生成版本,注意这里要准确清晰的进行版本描述   · 生成版本 5. 查看版本记录   · gitlog 6. 

  • JS判断是否是微信打开页面

    functionisWeiXin(){   varua=window.navigator.userAgent.toLowerCase();   if(ua.match(/MicroMessenger/i)=='micromessenger'||ua.match(/_SQ_/i)=='_sq_'){     returntrue;   }else{     returnfalse;   } }   更多内容请点击  

  • Record -「Tricks」记录

    曼哈顿距离\(\text{dist}(A,B)=|x_{A}-x_{B}|+|y_{A}-y_{B}|\)可以拆成\(\max\{x_{A}-x_{B}+y_{A}-y_{B},x_{A}-x_{B}-y_{A}+y_{B},-x_{A}+x_{B}+y_{A}-y_{B},-x_{A}+x_{B}-y_{A}+y_{B}\}\)。agc034d 走步数什么的构造题步数限制大约在\(\log\)级别可考虑二进制拆分(倍增构造)。arc103b \(x\bmodm\)除了拆成\(x-\lfloor\frac{x}{m}\rfloor\timesm\)还可以拆成\(x-km,(k\in\mathbb{Z})\)。arc111b 像什么第\(i\)个人对应第\(p_{i}\)个物品,\(p\)是\(1,\cdots,n\)的一个排列这种,直接连边。arc111c/someabcd 对应上一条,这种情况连边一定是一个这样\(i\rightarrowp_{i}\rightarrowp_{p_{i}}\rightarrow\cdots\rightarrowi\)的环。arc11

  • 2021.11.2-测试T1数独

    痛苦 题目 数独 【问题描述】 给定一个9*9矩阵,对其进行几种操作,分别是插入,删除,合并,查询,输出 主要学到了一些特别的操作。 (1)备份(本蒟蒻第一次了解到) (2)对与数据的一些特别的改动 (3)进行标记  这道题目,直接模拟就可以了,但要注意细节以及一些很妙的操作: 首先是字符组的存入:注意将其他的字符进行排除: 1for(inti=1;i<=19;i++){ 2cin>>s; 3if(i&1)continue;//奇数 4for(intj=1;j<=9;j++) 5c[0][i/2][j]=s[j*2-1]; 6}复制 然后就是分类讨论: charc[105][10][10];//前面用于备份每一次操作后的数独(第一次看到这种操作,太强了)cin>>T; for(inti=1;i<=T;i++){ cin>>s; if(s[0]=='I')x=in,y=in,k=in,insert(i,x,y,k);//in:快读{i记录每一次操作} elseif(s[0]=='D')x=in,y=in,del

  • Word文档分节设置页码

    在一篇论文中需要将摘要和目录作为一部分设置罗马数字页码,正文部分设置阿拉伯数字页码。 大致效果如下图所示:   这里面用到了分节符,步骤如下: 1:点击开始菜单栏下显示/隐藏编辑标记 2:点击插入菜单栏下的页码,先为整个文档设置页码。此时整个文档按照1,2,...,n这样显示页码。 3:在需要分别显示不同页面的中间部分设置分节符;在两节之间的位置点击布局->分隔符->(分节符下的)下一页。    4:在第一页的页码位置设置页码,前面一节设置为罗马数字格式。(注:设置第一节时,选中起始页码,这将只改变本节页码。)   改变效果:     设置完第一节后,设置第二节页码:   5:选中页码位置的编号4,右键选中设置页码格式      改变效果:    

  • 明朝中期一个中产阶级的衣食住行

    ***价格取自《金-ping-梅》和《宛署杂记》两本***   时间:明朝中期。地点:清河县。清河县临着大运河,算是一个发达城市了,起码算是二线上等。 人物:韩道国。   先简单介绍一下主人公。 韩道国,字希尧,30岁,之前是清河县落魄中产,后被西门庆聘做绒线店的掌柜。 个人能力:善写算。 性格:“许人钱,如捉影捕风;骗人财,如探囊取物” 弟弟:韩二。青皮小流氓。 其妻:王六儿,29岁,王屠之女。性淫,和小叔子偷情被抓过。 其女:爱姐,15岁。许配于东京的翟管家做小妾。     先说收入。韩道国管着西门大官人的一个店铺。收入大约2两银子每月。(参考西门大官人生药店的掌柜的收入)一个二线城市能养一家人的工资,就算现在的10000万块钱了吧?以下都以这个来做换算,这样一辆银子差不多算是5000块钱了。 再说支出。 住房:120两银子。折合60万人民币一套带院的房子。这个宅子是西门庆买的,用于和韩道国老婆偷情用的。应该算是普通市民中的住房,不算好,也不算差。按照收入比,韩道国需要花费5年的工资来买。这看起来还不算很贵的。   车马:一匹马50

  • Mysql-自用技巧

    Mysql查询某个字段(有时候想找某个字段在哪里,但是不知道表名等信息) SELECT TABLE_SCHEMA, TABLE_NAME FROM information_schema.`COLUMNS` WHERE COLUMN_NAME='要找的表名'复制 理解LeftJoin,InnerJoin TableA aidadate 1a1 2a2 3a3 TableB bidbdate 1b1 2b2 4b4复制   两个表a,b相连接,要取出id相同的字段 select*froma innerjoin bona.aid=b.bid这是仅取出匹配的数据. 此时的取出的是: 1a1b1 2a2b2 那么leftjoin指: select*froma leftjoin bona.aid=b.bid 首先取出a表中所有数据,然后再加上与a,b匹配的的数据 此时的取出的是: 1a1b1 2a2b2 3a3空字符 

  • 编写一个程序,将连个字符串s1和s2比较,如果s1 &gt; s2,输出一个整数;若s1 = s2,输出0;若s1 &lt; s2,输出一个负数。不要用strcpy函数。两个字符串用gets函数读入。输出的正数或负数的绝对值应是相比较的两个字符串相对应字符的ASCII码的差值。例如,&quot;A&quot;和“C”相比,由于&quot;A&quot; &lt; &quot;C&quot;,应输出负数,同时由于‘A’与‘C’的ASCI

    编写一个程序,将连个字符串s1和s2比较,如果s1>s2,输出一个整数;若s1=s2,输出0;若s1<s2,输出一个负数。不要用strcpy函数。两个字符串用gets函数读入。输出的正数或负数的绝对值应是相比较的两个字符串相对应字符的ASCII码的差值。例如,"A"和“C”相比,由于"A"<"C",应输出负数,同时由于‘A’与‘C’的ASCII码差值为2,因此应输出"-2"。同理:“And”和"Aid"相比较,根据第2个字符比较结果,"n"比"i"大5,因此应输出"5"。 【答案解析】 字符串比较规则:从前往后逐个字符进行比较,相等时继续往后,不相等时返回该位置两个字符差值。 【代码实现】 #include<stdio.h> intmain() { intret=0; intindex=0; chars1[100]={0}; chars2[100]={0}; printf("请输入s1:"); gets(s1); printf("请输入s2:"); gets(s2); //将s1和s2中的字符从前往后逐个进行比较,相等继续往后, //

  • python编程规范

     编写规范 每个import语句只导入一个模块,尽量避免一次导入多个模块。 不要在行尾添加分号“;”,也不要用分号将两条命令放在同一行。 建议每行不超过80个字符,如果超过,建议使用小括号将多行内容隐式地连接起来,而不推荐使用反斜杠进行连接 使用必要的空行可以增加代码的可读性。一般在顶级定义(如函数或者类的定义)之间空两行,而方法定义之间空一行。另外,在用于分隔某些功能的位置也可以空一行。 通常情况,运算符两侧、函数参数之间、逗号两侧建议使用空壳进行分隔。 应该避免在循环中使用+和+=操作符累加字符串。这是因为字符串是不可变的,这样做会创建不必要的临时对象。推荐的做法是将每个子字符串加入列表,然后在循环结束后使用join()方法连接列表。 适当使用异常处理结构提高程序容错性,但不能过多的依赖异常处理结构,适当的显式判断还是必要的。 命名规范 模块名尽量短小,并且使用全部的小写字母,可以使用下划线分隔多个字母。 包名尽量短小,并且使用全部的小写字母,不推荐使用下划线。 类名采用单词首字母大写形式。 模块内部的类采用下划线+Pascal风格的类名组成。 函数、类的属性和方法

  • Oracle误删除数据的恢复方法(转)

    来源:原创网站北京北亚数据恢复中心,转载须注明出处。 学习数据库时,我们只是以学习的态度,考虑如何使用数据库命令语句,并未想过工作中,如果误操作一下,都可能导致无可挽回的损失。当我在工作中真正遇到这些问题时,我开始寻找答案。 今天主要以oracle数据库为例,介绍关于表中数据删除的解决办法。(不考虑全库备份和利用归档日志) 删除表中数据有三种方法:·delete(删除一条记录)·drop或truncate删除表格中数据 1.delete误删除的解决方法原理: 利用oracle提供的闪回方法,如果在删除数据后还没做大量的操作(只要保证被删除数据的块没被覆写),就可以利用闪回方式直接找回删除的数据具体步骤为: *确定删除数据的时间(在删除数据之前的时间就行,不过最好是删除数据的时间点) *用以下语句找出删除的数据:select*from表名asoftimestampto_timestamp('删除时间点','yyyy-mm-ddhh24:mi:ss') *把删除的数据重新插入原表:     insertinto表名(select*from表名aso

  • php的运行原理、cgi对比fastcgi以及php-cgi和php-fpm之间的联系区别

    最近项目中本地测试环境遇到了windows环境下的nginx使用file_get_contents/curl访问php文件导致的阻塞问题,一直在找解决的方案,这个问题研究了三天终于找到了解决方案,特别因为这个我也对php的运行原理产生了兴趣,所以这里对此进行一定程度的记录,可能会有错漏的地方,欢迎指正。   要了解php的运行原理,首先要了解下面几个概念:   CGI:   CGI的英文是(COMMONGATEWAYINTERFACE)公共网关接口,它的作用就是帮助服务器与语言通信,这里就是nginx和php进行通信,因为nginx和php的语言不通,因此需要一个沟通转换的过程,而CGI就是这个沟通的协议。   nginx服务器在接受到浏览器传递过来的数据后,如果请求的是静态的页面或者图片等无需动态处理的则会直接根据请求的url找到其位置然后返回给浏览器,这里无需php参与,但是如果是一个动态的页面请求,这个时候nginx就必须与php通信,这个时候就会需要用到cgi协议,将请求数据转换成php能理解的信息,然后php根据这些信息返回的信息也要通

相关推荐

推荐阅读