C及汇编延时程序讲解

合集下载

C语言延时程序

C语言延时程序

C51精确延时程序一、、看了网上延时程序的帖子挺多,我也说点。

用keil调试,void yanshi( uint n ){uchar data i="0";for(i=0;i<N;I++);return;}延时时间=12*(n*12+17)/fosc用keil测时功能很容易得到这个关系,很精确,偏差不过几us.可以自己编一些延时程序,也可以很方便的得到关系式,只是系数不同.二、、//我看到的地方也是从别的地方转贴,所以我不知道原作者是谁,但相信这么成熟的东西转一下他也不会见意。

看到了个好帖,我在此在它得基础上再抛抛砖!有个好帖,从精度考虑,它得研究结果是:void delay2(unsigned char i){while(--i);}为最佳方法。

分析:假设外挂12M(之后都是在这基础上讨论)我编译了下,传了些参数,并看了汇编代码,观察记录了下面的数据:delay2(0):延时518us 518-2*256=6delay2(1):延时7us(原帖写“5us”是错的,^_^)delay2(10):延时25us 25-20=5delay2(20):延时45us 45-40=5delay2(100):延时205us 205-200=5delay2(200):延时405us 405-400=5见上可得可调度为2us,而最大误差为6us。

精度是很高了!但这个程序的最大延时是为518us 显然不能满足实际需要,因为很多时候需要延迟比较长的时间。

那么,接下来讨论将t分配为两个字节,即uint型的时候,会出现什么情况。

void delay8(uint t){while(--t);}我编译了下,传了些参数,并看了汇编代码,观察记录了下面的数据:delay8(0):延时524551us 524551-8*65536=263delay8(1):延时15usdelay8(10):延时85us 85-80=5delay8(100):延时806us 806-800=6delay8(1000):延时8009us 8009-8000=9delay8(10000):延时80045us 80045-8000=45delay8(65535):延时524542us 524542-524280=262如果把这个程序的可调度看为8us,那么最大误差为263us,但这个延时程序还是不能满足要求的,因为延时最大为524.551ms。

汇编延时程序讲解

汇编延时程序讲解

延时程序在单片机编程中使用非常广泛,但一些读者在学习中不知道延时程序怎么编程,不知道机器周期和指令周期的区别,不知道延时程序指令的用法, ,本文就此问题从延时程序的基本概念、机器周期和指令周期的区别和联系、相关指令的用法等用图解法的形式详尽的回答读者我们知道程序设计是单片机开发最重要的工作,而程序在执行过程中常常需要完成延时的功能。

例如在交通灯的控制程序中,需要控制红灯亮的时间持续30秒,就可以通过延时程序来完成。

延时程序是如何实现的呢?下面让我们先来了解一些相关的概念。

一、机器周期和指令周期1.机器周期是指单片机完成一个基本操作所花费的时间,一般使用微秒来计量单片机的运行速度,51 单片机的一个机器周期包括12 个时钟振荡周期,也就是说如果51 单片机采用12MHz 晶振,那么执行一个机器周期就只需要1μs;如果采用的是6MHz 的晶振,那么执行一个机器周期就需要2 μs。

2 .指令周期是指单片机执行一条指令所需要的时间,一般利用单片机的机器周期来计量指令周期。

在51 单片机里有单周期指令(执行这条指令只需一个机器周期),双周期指令(执行这条指令只需要两个机器周期),四周期指令(执行这条指令需要四个机器周期)。

除了乘、除两条指令是四周期指令,其余均为单周期或双周期指令。

也就是说,如果51 单片机采用的是12MHz 晶振,那么它执行一条指令一般只需1~2 微秒的时间;如果采用的是6MH 晶振,执行一条指令一般就需2~4 微秒的时间。

现在的单片机有很多种型号,但在每个型号的单片机器件手册中都会详细说明执行各种指令所需的机器周期,了解以上概念后,那么可以依据单片机器件手册中的指令执行周期和单片机所用晶振频率来完成需要精确延时时间的延时程序。

二、延时指令在单片机编程里面并没有真正的延时指令,从上面的概念中我们知道单片机每执行一条指令都需要一定的时间,所以要达到延时的效果,只须让单片机不断地执行没有具体实际意义的指令,从而达到了延时的效果。

c语言中delay的用法

c语言中delay的用法

c 语言中 delay 的用法C 语言作为一门新型高级编程语言 ,在计算机软件编程中具有较为广泛的应用和实现。

下面小编就跟你们详细介绍下 c 语言中 delay 的用法,希望对你们有用。

c 语言中 delay 的用法如下:假设一个延时函数如下:void delay(){uint i;for(i=0;i<20000;i++);}我们怎么来算呢,先将 20000 转成 16 进制,得到 4E20,然后将高字节 4E 乘以 6 得到 468D,再将 468+2=470,然后将 470D*20HEX (即 32D)=15040;所心这个延时函数总共要执行 15040 个周期,假设所用的晶振为 12MHZ,则该段函数总延时:15.04ms。

有了这个公式我们如果想要设定指定的延时长度就可以用它的己知公式确定。

即:总时间=[(6*i 值的高 8 位)+2]*i 的低 8 位。

例如:设要延时 125ms。

我们将低字节先赋值200D*(即:C8),然后再算高低节的定值,由式中可知 125ms=200*((i 值的高字节*6)+2),又可推算出(高低节*6)+2 的总延迟时间应等于625us,将625/6=104.1666,取整数得到 104,将 104 转成 16 进制得到 68H,再将高字节和低字节组合起来即得到了定值,即:68C8HEX,代入函数即如下:void delay(){uint i;for(i=0;i<0x68C8;i++);}如果写直进行就要将 68C8 转成 10 进制,即:26824,代入后得到:void delay(){uint i;for(i=0;i<0x26824;i++);在 c 语言中嵌入一段汇编的延时程序呀,你自己看看书,很简单的用在单片机里的可以 C 和汇编混合使用,因为用汇编编写延时要准确些,所以你不妨写一个汇编程序,然后再调用它好了,要用C来编精确的延时确实是比较难的哦.呵呵谁说 C 语言不能精确延时,用 51 单片机的定时/计数器一或者用定时/计数器 2 的工作方式 2,自动再装入 8 位计数器,就可以精确延时,别说 1MS 了就是 100um 也能精确做到。

C及汇编延时程序讲解

C及汇编延时程序讲解

有个好帖,从精度考虑,它得研究结果是:void delay2(unsigned char i){while(--i);}为最佳方法。

分析:假设外挂12M(之后都是在这基础上讨论)我编译了下,传了些参数,并看了汇编代码,观察记录了下面的数据:delay2(0):延时518us 518-2*256=6delay2(1):延时7us(原帖写“5us”是错的,^_^)delay2(10):延时25us 25-20=5delay2(20):延时45us 45-40=5delay2(100):延时205us 205-200=5delay2(200):延时405us 405-400=5见上可得可调度为2us,而最大误差为6us。

精度是很高了!但这个程序的最大延时是为518us 显然不能满足实际需要,因为很多时候需要延迟比较长的时间。

那么,接下来讨论将t分配为两个字节,即uint型的时候,会出现什么情况。

void delay8(uint t){while(--t);}我编译了下,传了些参数,并看了汇编代码,观察记录了下面的数据:delay8(0):延时524551us 524551-8*65536=263delay8(1):延时15usdelay8(10):延时85us 85-80=5delay8(100):延时806us 806-800=6delay8(1000):延时8009us 8009-8000=9delay8(10000):延时80045us 80045-8000=45delay8(65535):延时524542us 524542-524280=262如果把这个程序的可调度看为8us,那么最大误差为263us,但这个延时程序还是不能满足要求的,因为延时最大为524.551ms。

那么用ulong t呢?一定很恐怖,不用看编译后的汇编代码了。

那么如何得到比较小的可调度,可调范围大,并占用比较少得RAM呢?请看下面的程序:/*--------------------------------------------------------------------程序名称:50us 延时注意事项:基于1MIPS,AT89系列对应12M晶振,W77、W78系列对应3M晶振例子提示:调用delay_50us(20),得到1ms延时全局变量:无返回:无--------------------------------------------------------------------*/void delay_50us(uint t){uchar j;for(;t>0;t--)for(j=19;j>0;j--);}我编译了下,传了些参数,并看了汇编代码,观察记录了下面的数据:delay_50us(1):延时63us 63-50=13delay_50us(10):延时513us 503-500=13delay_50us(100):延时5013us 5013-5000=13delay_50us(1000):延时50022us 50022-50000=22赫赫,延时50ms,误差仅仅22us,作为C语言已经是可以接受了。

c语言中延时的方法

c语言中延时的方法

c语言中延时的方法C语言中实现延时的方法有多种方式。

下面将介绍两种常用的延时方法:方法一:使用循环实现延时使用循环来进行延时是C语言中常用的方法之一。

通过循环次数来控制延时的时间,代码如下:```#include <stdio.h>void delay(int milliseconds) {for (int i = 0; i < milliseconds * 10000; i++) {// 延时}}int main() {printf("开始延时\n");delay(1000); // 延时1秒printf("延时结束\n");return 0;}```在上述代码中,delay函数使用了一个for循环来实现延时,其中循环次数通过乘以10000与延时时间相乘得到。

这种方法的缺点是无法精确控制延时时间,受系统执行速度的影响较大。

方法二:使用<time.h>库函数实现延时另一种常用的延时方法是利用<time.h>头文件中的库函数,如sleep函数。

代码如下:```#include <stdio.h>#include <time.h>void delay(int seconds) {sleep(seconds);}int main() {printf("开始延时\n");delay(1); // 延时1秒printf("延时结束\n");return 0;}```在上述代码中,delay函数通过调用sleep函数来实现延时,参数表示延时的秒数。

这种方法的优点是延时时间较为精确,但缺点是无法实现毫秒级的延时。

以上是C语言中实现延时的两种常用方法。

开发者可以根据具体需求选择合适的延时方法。

mcs-51单片机中汇编程序延时的精确算法。

mcs-51单片机中汇编程序延时的精确算法。

MCS-51单片机中汇编程序延时的精确算法一、引言MCS-51单片机是一种常用的微控制器,其汇编程序编写对于工程师来说是极为重要的。

在MCS-51单片机中,延时是一种常见的需求,通过延时可以控制程序的执行速度和时间间隔。

而对于汇编程序中的延时算法,精确度的要求往往较高,特别是在一些实时系统中。

本文将针对MCS-51单片机中汇编程序延时的精确算法展开论述。

二、延时的需求在MCS-51单片机中,实现一定时间的延时是非常常见的需求。

在控制LED灯的闪烁过程中,需要一定的时间间隔来控制LED的亮灭频率;在读取传感器数据的过程中,需要一定的时间延时以确保传感器数据的准确性。

精确和可控的延时算法对于MCS-51单片机的应用来说是至关重要的。

三、常见的延时算法在MCS-51单片机的汇编程序中,常见的延时算法包括循环延时、定时器延时和脉冲宽度调制(PWM)延时等。

这些延时算法各有优缺点,需要根据具体的应用场景选择合适的算法。

1. 循环延时循环延时是一种简单而粗糙的延时算法,其原理是通过空转循环来消耗一定的CPU周期来实现延时。

这种延时算法的缺点是精度较差,受到CPU主频和编译器优化等因素的影响较大,不适合对延时精度有较高要求的场景。

2. 定时器延时定时器延时是一种利用MCS-51单片机内部定时器来实现延时的算法。

通过设置定时器的初值和计数方式,可以实现一定范围内的精确延时。

定时器延时的优点是精度高,不受CPU主频影响,适用于对延时精度要求较高的场景。

3. 脉冲宽度调制(PWM)延时脉冲宽度调制(PWM)延时是一种通过调节脉冲信号的宽度来实现延时的算法。

这种延时算法在一些特定的应用场景中具有较高的灵活性和精度。

例如在直流电机的速度调节过程中常常会采用PWM延时算法来实现精确的速度控制。

四、精确延时算法针对MCS-51单片机中汇编程序延时的精确算法,我们可以结合定时器延时和脉冲宽度调制(PWM)延时的优点,设计一种精确度较高的延时算法。

各种延时程序及其讲解

各种延时程序及其讲解
for(;i>0;i--)
for(j=6245;j>0;j--);
}
void main(void)
{
Delay_10us();
delay_50ms(20);
Delay_1s();
InitTime0();
while(1) {}
}
void Delay_10us()
可以在C文件中通过使用带_NOP_( )语句的函数实现,定义一系列不同的延时函数,如Delay10us( )、Delay25us( )、Delay40us( )等存放在一个自定义的C文件中,需要时在主程序中直接调用。如延时10 μs的延时函数可编写如下:
注意:不同的数据类型40的值不一样
四.总结
1.尽量使用unsigned型的数据结构。
2.尽量使用char型,实在不够用再用int,然后才是long。
3.如果有可能,不要用浮点型。
4.使用简洁的代码,因为按照经验,简洁的C代码往往可以生成简洁的目标代码(虽说不是在所有的情况下都成立)。
5.中断计时精确最高
void Delay_1s()
用Delay_10us()来实现;经过计算可得为3E01次
for(i=0x00; i<0x3E01; i++)//经过计算可得为3E01次
{
Delay_10us();
}
KEIL调试根据汇编代码可得出相应时间T = 40us + 4us + 63*循环次数
其中40us为开始为变量i(long)赋初值,函数调用4us,6us为++,与<操作,以及延时总共为63us
{
P1 = 0x00;
Delay_1s();

单片机汇编语言设计软件延时程序

单片机汇编语言设计软件延时程序

单片机汇编语言设计软件延时程序引言:在单片机编程中,经常需要使用延时函数来控制程序的执行时间,例如等待外设初始化完成、延迟发送数据等。

本文将介绍使用汇编语言设计的延时函数。

一、延时原理在单片机中,延时的实现主要通过定时器或循环计数的方式来实现。

定时器通常会使用内部时钟源来产生时钟信号,然后通过预设的计数值来控制定时时间。

循环计数方式则是通过程序在指定循环内部执行空操作的次数来实现延时。

二、定时器延时定时器延时的实现比较简单,只需要设置定时器的计数值和相关控制寄存器即可。

1.使用定时器0延时定时器0是一种常用的定时器,可通过T0计数器、定时器控制寄存器TCON和定时器模式控制寄存器TMOD来实现。

例如,以下是一个使用定时器0的延时函数的实现示例:```assemblydelay_us PROCMOV R4,16 ; 假设使用的是12MHz的晶振,所以每个机器周期为1/12MHz=83.33ns,16个机器周期为1.33usMOVR5,FFH;设置循环的次数delay_usroutine:NOP;执行空操作,延时一个机器周期DJNZ R5,delay_usroutine ;循环R5次RETdelay_us ENDPdelay_ms PROCMOV R7,4 ; 延时1ms需要延时四次1usLOOP:CALL delay_usDJNZR7,LOOPRETdelay_ms ENDP```在上述代码中,delay_us过程使用了16次空操作进行延时,该延时约为1.33us。

delay_ms过程通过循环调用delay_us过程实现了1ms的延时。

2.使用定时器1延时定时器1是使用T1计数器、定时器控制寄存器TCON和定时器模式控制寄存器TMOD来实现的。

例如,以下是一个使用定时器1的延时函数的实现示例:```assemblydelay_us PROCMOV R4,16 ; 假设使用的是12MHz的晶振,所以每个机器周期为1/12MHz=83.33ns,16个机器周期为1.33usMOVR5,FFH;设置循环的次数delay_usroutine:NOP;执行空操作,延时一个机器周期DJNZ R5,delay_usroutine ;循环R5次RETdelay_us ENDPdelay_ms PROCMOV R7,4 ; 延时1ms需要延时四次1usLOOP:CALL delay_usDJNZR7,LOOPRETdelay_ms ENDP```在上述代码中,delay_us过程使用了16次空操作进行延时,该延时约为1.33us。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

有个好帖,从精度考虑,它得研究结果是:void delay2(unsigned char i){while(--i);}为最佳方法。

分析:假设外挂12M(之后都是在这基础上讨论)我编译了下,传了些参数,并看了汇编代码,观察记录了下面的数据:delay2(0):延时518us 518-2*256=6delay2(1):延时7us(原帖写“5us”是错的,^_^)delay2(10):延时25us 25-20=5delay2(20):延时45us 45-40=5delay2(100):延时205us 205-200=5delay2(200):延时405us 405-400=5见上可得可调度为2us,而最大误差为6us。

精度是很高了!但这个程序的最大延时是为518us 显然不能满足实际需要,因为很多时候需要延迟比较长的时间。

那么,接下来讨论将t分配为两个字节,即uint型的时候,会出现什么情况。

void delay8(uint t){while(--t);}我编译了下,传了些参数,并看了汇编代码,观察记录了下面的数据:delay8(0):延时524551us 524551-8*65536=263delay8(1):延时15usdelay8(10):延时85us 85-80=5delay8(100):延时806us 806-800=6delay8(1000):延时8009us 8009-8000=9delay8(10000):延时80045us 80045-8000=45delay8(65535):延时524542us 524542-524280=262如果把这个程序的可调度看为8us,那么最大误差为263us,但这个延时程序还是不能满足要求的,因为延时最大为524.551ms。

那么用ulong t呢?一定很恐怖,不用看编译后的汇编代码了。

那么如何得到比较小的可调度,可调范围大,并占用比较少得RAM呢?请看下面的程序:/*--------------------------------------------------------------------程序名称:50us 延时注意事项:基于1MIPS,AT89系列对应12M晶振,W77、W78系列对应3M晶振例子提示:调用delay_50us(20),得到1ms延时全局变量:无返回:无--------------------------------------------------------------------*/void delay_50us(uint t){uchar j;for(;t>0;t--)for(j=19;j>0;j--);}我编译了下,传了些参数,并看了汇编代码,观察记录了下面的数据:delay_50us(1):延时63us 63-50=13delay_50us(10):延时513us 503-500=13delay_50us(100):延时5013us 5013-5000=13delay_50us(1000):延时50022us 50022-50000=22赫赫,延时50ms,误差仅仅22us,作为C语言已经是可以接受了。

再说要求再精确的话,就算是用汇编也得改用定时器了。

/*--------------------------------------------------------------------程序名称:50ms 延时注意事项:基于1MIPS,AT89系列对应12M晶振,W77、W78系列对应3M晶振例子提示:调用delay_50ms(20),得到1s延时全局变量:无返回:无--------------------------------------------------------------------*/void delay_50ms(uint t){uint j;/****可以在此加少许延时补偿,以祢补大数值传递时(如delay_50ms(1000))造成的误差,但付出的代价是造成传递小数值(delay_50ms(1))造成更大的误差。

因为实际应用更多时候是传递小数值,所以补建议加补偿!****/for(;t>0;t--)for(j=6245;j>0;j--);}我编译了下,传了些参数,并看了汇编代码,观察记录了下面的数据:delay_50ms(1):延时50 010 10usdelay_50ms(10):延时499 983 17usdelay_50ms(100):延时4 999 713 287usdelay_50ms(1000):延时4 997 022 2.978ms赫赫,延时50s,误差仅仅2.978ms,可以接受!上面程序没有才用long,也没采用3层以上的循环,而是将延时分拆为两个程序以提高精度。

应该是比较好的做法了楼上的说得很对,用C语言编写单片机程序时,一般开发界面(如科尔KEILE)都提供了C - 汇编的代码转换,参照转换后的汇编语言就可以精确延时了---------------------------------------------------------------你可以数指令,然后按着MCU的MIPS算时间,结果应该比较精确:)---------------------------------------------------------------void mDelay(unsigned int Delay) //Delay = 1000 时间为1S{unsigned int i;for(;Delay>0;Delay--){for(i=0;i<124;i++){;}}}---------------------------------------------------------------数一次循环的汇编指令,再乘以指令周期就知道一次循环的时间了啊,然后用1秒一除,不就知道循环次数了么---------------------------------------------------------------秒级的本身精度要求就不高嘛很容易控制啊多套用几个for语句或者在for语句里引用n个更低量级的(如100ms级)的延时函数即可要精确就计算汇编代码执行长度---------------------------------------------------------------to flowercity(Love Program,Love Living):你的函数没有什么参考价值延时时间和指令周期以及编译出来的代码类型有关系的不是所谓//Delay = 1000 时间为1S就是一定的.那只是针对你现在的系统.用的晶振不同,执行CPU指令周期和时钟周期比率不同结果都不同---------------------------------------------------------------秒级的,用定时器比较好吧。

---------------------------------------------------------------void waitms(int i){char m;for( ; i ;i--){for(m = 203; m ; m--){_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();}}}延时1ms的函数时钟频率12MHz---------------------------------------------------------------空操作,不过不好做到很准确---------------------------------------------------------------秒级延时,用指令的话,你要求延时的精确度是多少,高的话最好用定时器,而且你延时这么长,你的CPU不是就一直占用了,浪费呀。

---------------------------------------------------------------与定时器中断服务程序配合实现延时。

unsigned int sleepTime;unsinged char inSleep = 0;void sleepService(void){if (inSleep) sleepTime--;MOV R2,#25JMP DELAY_MSdelay_30ms: ;30msMOV R2,#12JMP DELAY_MSDELAY_5MS: ;5MSMOV R2,#2;=================================== DELAY_MS:CALL DELAY2400DJNZ R2,DELAY_MSRET;=================================== DELAY2400: ;10x244+4=2447/1.024=2390MOV R0,#244 ;1DELAY24001:MUL AB ;4MUL AB ;4DJNZ R0,DELAY24001 ;2RETDELAY: ;延时子程序(1秒)MOV R0,#0AHDELAY1: MOV R1,#00HDELAY2: MOV R2,#0B2HDJNZ R2,$DJNZ R1,DELAY2DJNZ R0,DELAY1RETMOV R2,#10 ;延时1秒LCALL DELAYMOV R2,#50 ;延时5秒LCALL DELAYDELAY: ;延时子程序PUSH R2PUSH R1汇编延时程序算法详解来源:嵌入式技术网作者:姜会敏时间:2008-01-01发布人:林逸摘要计算机反复执行一段程序以达到延时的目的称为软件延时,单片机应用程序中经常需要短时间延时,有时要求很高的精度,网上或书中虽然有现成的公式可以套用,但在部分算法讲解中发现有错误之处,而且延时的具体算法讲得并不清楚,相当一部分人对此仍很模糊,授人鱼,不如授之以渔,本文将以12MHZ 晶振为例,详细讲解MCS-51单片机中汇编程序延时的精确算法。

关键词51单片机汇编延时算法指令周期、机器周期与时钟周期指令周期:CPU执行一条指令所需要的时间称为指令周期,它是以机器周期为单位的,指令不同,所需的机器周期也不同。

时钟周期:也称为振荡周期,一个时钟周期=晶振的倒数。

MCS-51单片机的一个机器周期=6个状态周期=12个时钟周期。

MCS-51单片机的指令有单字节、双字节和三字节的,它们的指令周期不尽相同,一个单周期指令包含一个机器周期,即12个时钟周期,所以一条单周期指令被执行所占时间为12*(1/12000000)=1µs。

相关文档
最新文档