你会51单片机的精确延时吗

发布者:创新思绪最新更新时间:2021-06-22 来源: eefocus关键字:51单片机  精确延时  精度 手机看文章 扫描二维码
随时随地手机看文章

对于某些对时间精度要求较高的程序,用 c 写延时显得有些力不从心,故需用到汇编程序。本人通过测试,总结了 51 的精确延时函数(在 c 语言中嵌入汇编)分享给大家。至于如何在 c 中嵌入汇编大家可以去网上查查,这方面的资料很多,且很简单。以 12MHz 晶振为例,12MHz晶振的机器周期为 1us,所以,执行一条单周期指令所用时间就是 1us,如 NOP 指令。下面具体阐述一下。


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

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


例如:



#include

#include

void main(void)

{

  P1 = 0x0;

  _nop_(); //延时 1us

  P1 = 0xff;

}

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

delay_5us()

{

  #pragma asm

  nop

  #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,请思考为什么?^_^


关键字:51单片机  精确延时  精度 引用地址:你会51单片机的精确延时吗

上一篇:51单片机最小系统电路-设计教程
下一篇:51单片机汇编程序,温度报警项目

推荐阅读最新更新时间:2024-11-06 10:03

51单片机 LCD1602显示
引脚图 #include reg52.h #include intrins.h #define uchar unsigned char #define uint unsigned int #define out P0 sbit RS=P2^7; sbit RW=P2^6; sbit E=P2^5; void lcd_initial(void); //LCD初始化函数 void check_busy(void); //检查是否忙碌函数 void write_command(uchar com); //写命令函数 void write_data(uchar dat); //写数据函数 void string(
[单片机]
<font color='red'>51单片机</font> LCD1602显示
世健推出增强版超宽温度范围、高精度皮安计模块
准确的弱电信号测量是各种科学分析设备、环境监测和过程控制的关键环节之一,尤其是当弱电信号达到pA甚至fA水平时。 如何测量微弱信号?这向来是各大仪器厂商津津乐道的话题。如何设计检测微弱电流的产品?这对设计者来说也是巨大的挑战。 一直以来,基于ADI的JFET放大器AD549芯片方案在微弱电流采样的前端扮演着主力中坚的角色,在仪器仪表行业持续横行了30多年,经久不衰。但由于JFET工艺的芯片短板很明显,它缺少Bipolar型放大器所拥有的低失调、低电压噪声以及低温漂高共模等特性,对于不同温度下的特性补偿很难拿捏得准确。随着科技的进步,ADI基于新型CMOS工艺,通过DigiTrim®技术革新,在2015年发布了ADA4530-1,
[测试测量]
世健推出增强版超宽温度范围、高<font color='red'>精度</font>皮安计模块
80c51单片机的基本配置有哪些 80c51单片机各个引脚及功能
  80c51单片机的基本配置有哪些   80C51单片机的基本配置包括:   CPU:80C51单片机的CPU由一个8位的ALU(算术逻辑单元)、一个8位的累加器、一个8位的B寄存器、一个16位的程序计数器和一个8位的状态寄存器组成。   存储器:80C51单片机的存储器包括程序存储器(ROM)、数据存储器(RAM)和特殊功能寄存器(SFR)。   时钟源:80C51单片机支持多种时钟源,包括外部晶体、外部时钟信号、内部振荡器等。   中断系统:80C51单片机支持多种中断源和中断优先级设置,可以灵活处理各种外部事件。   IO端口:80C51单片机的IO端口由多个可编程的输入输出引脚组成,可以连接各种外部设备。   通信接口:
[单片机]
一种中速高精度模拟电压比较器的设计
1 引言 在A/D转换器中,比较器重要性能指标是工作速度、精度、功耗、输入失调电压、正反馈时产生的回程噪声等,这些指标影响和制约着整个A/D转换器的性能。高速比较器速度较快,一般采用锁存器(Latch)结构,但是失调和回程噪声较大,精度在8位以下,用于闪烁(Flash)、流水线(Pipeline)型等高速A/D转换器。高精度比较器可分辨小电压,但速度相对较慢,一般采用多级结构,且较高的精度决定失调校准的必要性。这里设计的比较器是用于输入范围2.5 V、速度1 MS/s、精度12位的逐次逼近型A/D转换器,为了满足A/D转换器的性能指标,则需采用中速高精度的比较器。 2 比较器的设计 由于该比较器用于输入电压2.5 V、速度1
[电源管理]
一种中速高<font color='red'>精度</font>模拟电压比较器的设计
51单片机(AT89C52)D/A转换
#include reg52.h #define uchar unsigned char #define uint unsigned int sbit cs=P3^0; sbit wr=P3^1; void delayms(uint x) { uint y,z; for(y=x;y 0;y--) for(z=110;z 0;z--); } void main() { uchar temp; cs=0; wr=0; while(1) { P2=temp; delayms(25); temp++; } }
[单片机]
<font color='red'>51单片机</font>(AT89C52)D/A转换
从零开始51单片机教程 —— 27 矩阵式键盘接口技术及程序设计
矩阵式键盘接口技术及程序设计 在单片机系统中键盘中按钮数量较多时,为了减少I/O口的占用,常常将按钮排列成矩阵形式,如图1所示。在矩阵式键盘中,每条水平线和垂直线在交叉处不直接连通,而是通过一个按钮加以连接。这样,一个端口(如P1口)就能组成4*4=16个按钮,比之直接将端口线用于键盘多出了一倍,而且线数越多,区别越明显,比如再多加一条线就能组成20键的键盘,而直接用端口线则只能多出一键(9键)。由此可见,在需要的键数比较多时,采用矩阵法来做键盘是合理的。 单片机矩阵式键盘接口技术及编程接口图 矩阵式结构的键盘显然比直接法要复杂一些,识别也要复杂一些,上图中,列线通过电阻接正电源,并将行线所接的单片机的I/O口作
[单片机]
从零开始<font color='red'>51单片机</font>教程 —— 27 矩阵式键盘接口技术及程序设计
MCS-51单片机外部RAM的地址指针及其应用
MCS-51单片机外部RAM的地址空间为64K , 地址总线为16位,访问外接RAM可执行如下4条指令: MOVX A,@DPTR MOVX @DPTR,A MOVX A,@RI MOVX @RI,A 其中DPTR为16位地址寄存器,地址高8位存于DPH,地址低8位存于DPL;Ri(I=0,1)是8位寄存器,作为地址指针时仅存低8位地址。 MCS-51执行上述指令时分为两个阶段:首先,是从外接程序存储器中取出指令代码,并进行分析。然后,执行对外接RAM的数据读/写操作。在这两个阶段,P0口、P1口上的地址选通是有区别的。 执行“MOVX A,@DPTR”和“MOVX @DPTR,A”指令时,在读指令代码阶段,由程序计
[单片机]
51单片机汇编语言(五)
定时器 计数器 功能说明: 开始时接在单片机P1端口中的P1.7亮,用定时器延时60ms后P1.6亮,如此向右移动,移到最右端P1.0亮后,又回到最左端重新开始向右移动,不断循环。 程序:DS01.ASM 01: START: MOV R0, #8 ;设右移8次 02: MOV A, #01111111B ;存入开始点亮灯位置 03: LOOP: MOV P1, A ;传送到P1并输出 04: ACALL DELAY ;调延时子程序 05: RR A
[单片机]
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved