Keil仿真及软件延时语句的精确计算
Keil_C51_for循环精确延时
for循环实现C语言精确延时(晶振12MHz,一个机器周期1us.)2ms延时子程序void delay2ms(void){uchar i,j,k;for(i=5;i>0;i--)for(j=8;j>0;j--)for(k=25;k>0;k--);}10ms延时子程序程序:void delay10ms(void){uchar i,j,k;for(i=5;i>0;i--)for(j=4;j>0;j--)for(k=248;k>0;k--);}产生的汇编C:0x0800 7F05 MOV R7,#0x05C:0x0802 7E04 MOV R6,#0x04C:0x0804 7DF8 MOV R5,#0xF8C:0x0806 DDFE DJNZ R5,C:0806C:0x0808 DEFA DJNZ R6,C:0804C:0x080A DFF6 DJNZ R7,C:0802C:0x080C 22 RET20ms延时子程序程序:void delay20ms(void){uchar i,j,k;for(i=5;i>0;i--)for(j=8;j>0;j--)for(k=248;k>0;k--);}200ms延时子程序程序:void delay200ms(void){uchar i,j,k;for(i=5;i>0;i--)for(j=132;j>0;j--)for(k=150;k>0;k--);}产生的汇编C:0x0800 7F05 MOV R7,#0x05C:0x0802 7E84 MOV R6,#0x84C:0x0804 7D96 MOV R5,#0x96C:0x0806 DDFE DJNZ R5,C:0806C:0x0808 DEFA DJNZ R6,C:0804C:0x080A DFF6 DJNZ R7,C:0802C:0x080C 22 RET500ms延时子程序程序:void delay500ms(void){uchar i,j,k;for(i=15;i>0;i--)for(j=202;j>0;j--)for(k=81;k>0;k--);}产生的汇编:C:0x0800 7F0F MOV R7,#0x0FC:0x0802 7ECA MOV R6,#0xCAC:0x0804 7D51 MOV R5,#0x51C:0x0806 DDFE DJNZ R5,C:0806C:0x0808 DEFA DJNZ R6,C:0804C:0x080A DFF6 DJNZ R7,C:0802C:0x080C 22 RET计算分析:程序共有三层循环一层循环n:R5*2 = 81*2 = 162us DJNZ 2us二层循环m:R6*(n+3) = 202*165 = 33330us DJNZ 2us + R5赋值1us = 3us 三层循环: R7*(m+3) = 15*33333 = 499995us DJNZ 2us + R6赋值1us = 3us循环外: 5us 子程序调用2us + 子程序返回2us + R7赋值1us = 5us 延时总时间= 三层循环+ 循环外= 499995+5 = 500000us =500ms计算公式:延时时间=[(2*R5+3)*R6+3]*R7+5在精确延时的计算当中,最容易让人忽略的是计算循环外的那部分延时,在对时间要求不高的场合,这部分对程序不会造成影响.1s延时子程序程序:void delay1s(void){uchar h,i,j,k;for(h=5;h>0;h--)for(i=4;i>0;i--)for(j=116;j>0;j--)for(k=214;k>0;k--);}产生的汇编C:0x0800 7F05 MOV R7,#0x05 C:0x0802 7E04 MOV R6,#0x04 C:0x0804 7D74 MOV R5,#0x74 C:0x0806 7CD6 MOV R4,#0xD6 C:0x0808 DCFE DJNZ R4,C:0808 C:0x080A DDFA DJNZ R5,C:0806 C:0x080C DEF6 DJNZ R6,C:0804 C:0x080E DFF2 DJNZ R7,C:0802 C:0x0810 22 RET。
在单片机KeilC开发环境中设计精确的延时函数
第22卷第8期徐州工程学院学报2007年8月Vol.22No.8Journal of Xuzhou Institute of Technology AU G12007在单片机Keil C开发环境中设计精确的延时函数张 宏,邢文生(焦作大学, 河南 焦作 454000) 【摘 要】 Keil C语言是开发单片机系统常用的语言,但不能象汇编语言一样预测代码执行的指令周期,对外围元件实现精确的延时控制比较困难.文章从Keil C的编译原理出发,分析几种延时函数,实现了精确的延时效果.【关键词】 单片机;Keil C语言;延时【中图分类号】 TP368.1 【文献标识码】A【文章编号】167320704(2007)0820064204单片机的编程语言有汇编语言和Keil C语言等.相对汇编来说,Keil C具有代码编写方便、易于维护、便于理解的优点,适合编写大的项目,已被广泛使用.但它不能够象汇编代码那样直接计算出每条语句的执行周期,无法预测代码执行的指令时间,在实时性方面不易保证.如果某个外围元件需要比较精确的延时,用计时器会浪费宝贵的单片机资源,那么如何在Keil C语言中编写出可以实现精确延时的延时函数就具有很重要的实用意义.1 单片机工作原理及Keil C语言实现延时的机制51单片机系统由单片机、晶振、外围元件等组成.使用时需要在单片机的时钟引脚XTAL1、XTAL2接上石英晶振或有源晶振,晶振的作用是向单片机提供外部的振荡脉冲.单片机内部有指令寄存器PC,在晶振脉冲的作用下单片机一步步地执行指令寄存器所指的命令,这就是单片机语言的执行过程.单片机延时程序就是让单片机执行许多空操作.单片机Keil C语言实现延时程序的实现机制如图1所示.由图1可以看出,Keil C编译器翻译器的功能是将标准的Keil C语言生成单片机能够认识的汇编指令. Keil C环境中,如果想查看Keil C语言生成的汇编指令,需要在程序编译成功后,启动菜单下Debug命令下的start/stop debug session项,系统就会出现编译后对应的汇编语句,并可以根据汇编语句计算出延时的时间.51单片机机器周期的是晶振频率的1/12,每条汇编指令执行使用的所占的机器周期不同.延时时间的计算公式是:总机器周期数×晶振频率/12.为了计算方便,假定本系统使用的晶振是12M Hz.2 Keil C语言实现延时程序分析2.1 常见的延时代码的分析Keil C语言实现延时一般使用循环语句,下面是经常使用的延时代码:void delay(unsigned char i){for(;i!=0;i--);}Keil C将循环体for(;i!=0;i--)转换成的汇编代码及其机器周期数如表1.收稿日期:2007203221作者简介:张 宏(19662),男,河南焦作人,副教授,主要从事计算机自动控制技术研究.图1 Keil C 语言延时的实现机制Fig.1 The delay f unction with Keil C表1 循环体for (;i !=0;i --)转换成的汇编代码Table 1 The ASM code of loop “for (;I >0i --)”编译成的汇编代码功能描述机器周期数MOV A ,R7加载循环体循环个数1J Z C如果循环个数为0,结束延时2DEC R7否则循环个数减一1S J MP delay 进行下一轮循环2可以看出,完成一次主循环的需要6个机器周期,在循环次数分别是0、1、2、3……情况下,延时函数所需的机器周期分别是3、9、15、21…….如果要调用该延时函数,需要使用delay (x )语句,其中x 是延时函数主循环的次数,决定了延时时间的长短.该语句经Keil C 转换后成的汇编代码如表2.表2 调用该延时函数转换成的汇编代码Table 2 The ASM code of calling the f unction生成的汇编代码功能描述机器周期数MOV R7,#data将总循环个数送寄存器1LCALL delay 转入执行延时函数2分析该语句可知,调用延时函数需要3个时钟周期来完成.如果调用延时函数时设定循环的处始值是i ,可以得该延时函数的延长时间6i +3+3.该循环延时函数的延时精度是6个机器周期.假如系统使用的晶振是12M Hz ,则延时时间是(6i +6)/12微秒.同样道理,循环体是for (a =i ;a !=0;a --)的延时函数与此类似.2.2 使用while (--i )语句实现精度为2微秒级的延时函数如果要实现微秒级的延时精度,可以使用下面的函数代码:void delay1(unsigned char i ){while (--i );}循环体while (--i )生成的汇编源代码以及机器周期数如表3.可以看出,完成一次主循环的需要2个机器周期,在循环次数分别是0、1、2、3……情况下,延时函数所需的机器周期分别是2、4、6、8…….要调用该延时函数,由表2可知需要3个时钟周期.如果调用延时函数时设定循环个数的初始值是i ,可张宏,等:在单片机Keil C 开发环境中设计精确的延时函数徐州工程学院学报 2007年第8期以得该延时函数的延长时间2i+2+3.假定系统使用的晶振是12M Hz,则延时时间是(2i+5)/12微秒.该循环延时函数的的延时精度是2个机器周期.表3 while(--i)生成的汇编代码Table3 The ASM code of loop“while(--i)”生成的汇编代码功能描述机器周期数DJ NZ R7,delay将寄存器R7内容减1,如果不为0继续循环23 使用nop()语句设计任意延时精度的延时函数nop()语句是Keil C语言中自己带的一个函数,其功能是相当于汇编语句中的NO P指令.该语句的功能是,例如有下面C语言语句:......nop();nop();......则编译成的汇编代码为:......NO P NO P......如果在第一个延时函数中加入nop()语句,就可以增加主循环的运行周期.因此将nop()语句与延时循环程序结合起来,可以设计任意的延时时间.分析下面实例代码:void delay(unsigned char i){for(;i!=0;i--){nop();nop();}}该代码是在延时函数代码的循环体里面加入两个nop()语句,编译生成的汇编代码以及机器周期数如表4.表4 加入两个nop()语句后的延时函数汇编代码Table4 The ASM code added two nop()line生成的汇编代码功能描述机器周期数MOV A,R7加载循环个数1J Z C如果循环个数为0,结束延时2NOP执行一次空操作1NOP执行一次空操作1DEC R7循环个数减11S J MP delay进行下一轮循环2可以看出,因为C语言循环体加入两个nop()语句,因此汇编代码比原来多两个机器周期,完成一次主循环需要8个机器周期,在循环次数分别是0、1、2、3……情况下,延时函数所需的机器周期分别是3、11、19、27…….调用该延时函数,由表2可知需要3个时钟周期.假设调用延时函数时设定循环的初始值是i,可以得该延时函数的延长时间8i+3+3.该循环延时函数的的延时精度是8个机器周期.假定系统使用的晶振是12M Hz,则延时时间是(8i+6)/12微秒.通过灵活使用nop()函数,可以灵活设计出任意精度延时函数,达到满意的延时效果.在Keil C语言中,使用nop()语句需要在程序的前面加上“#include<IN TRINS.h>”语句.每一个nop()语句编译后需要一个字节的程序空间.4 结语上面程序在Keil uVision7.0版本中实现.对Keil C的编译原理的深入理解,通过恰当的语法运用,合理的语句运用,Keil C语言是可以达到满意的延时效果的.这样既可以发挥C语句的优点,又可以对外围元件进行实时的控制.张宏,等:在单片机Keil C开发环境中设计精确的延时函数参 考 文 献[1]李建忠.单片机原理及应用[M].西安:西安电子科技大学出版社,2003.[2]金炯泰等.如何使用KEIL8051C编译器[M].北京:北京航空航天大学出版社,2002.[3]范风强.单片机语言C51应用实战集锦[M].北京:电子工业出版社,2003.[4]徐爱钧.Keil Cx51V7.0单片机高级语言编程与uVision2应用实践[M].北京:电子工业出版社,2004.Precisely Programmed Delay Function B ased on MCU Language K eil CZHAN G Hong,XIN G Wen2sheng(Jiaozuo University,Jiaozuo454003,China)【Abstract】 As a commo nly used language in developing MCU system,Keil C is unable to predict t he p recise process time as t he assembly language,and is in difficulty in achieving accurate delay control over accessories.Based on some compiling principles of Keil C,t his paper analyzes some delay f unctions and a2 chieves precise delay p urpose.【K ey w ords】 MCU;Keil C;delay(责任编辑 曹 晨) (上接第18页)On Two Inequalities for g ExpectationZHU Hong2yan,SUO Xin2li,J IAO lin(China University of Mining and Technology,Xuzhou221008,China)【Abstract】 It is proven t hat J ensen’s inequality of bivariate convex f unction for g expectation holds if and only if g is a linear generator.And an equivalent condition and a sufficient condition of Markov ine2 quality for g expectation are accordingly arrived at.【K ey w ords】 backward stochastic differential equation(BSD E);g expectation;inequality(责任编辑 崔思荣)。
延时1us程序12mhz晶振c语言,51单片机KeilC延时程序的简单(晶振12MHz,一。。。
延时1us程序12mhz晶振c语⾔,51单⽚机KeilC延时程序的简单(晶振12MHz,⼀。
⼀. 500ms延时⼦程序void delay500ms(void){unsignedchari,j,k;for(i=15;i>0;i--)for(j=202;j>0;j--)for(k=81;k>0;k--);}产⽣的汇编:C:0x0800 7F0F MOV R7,#0x0FC:0x0802 7ECA MOV R6,#0xCAC:0x0804 7D51 MOV R5,#0x51C:0x0806 DDFE DJNZ R5,C:0806C:0x0808 DEFA DJNZ R6,C:0804C:0x080A DFF6 DJNZ R7,C:0802C:0x080C 22 RET计算分析:程序共有三层循环⼀层循环n:R5*2 = 81*2 = 162us DJNZ 2us⼆层循环m:R6*(n+3) = 202*165 = 33330us DJNZ 2us + R5赋值1us = 3us三层循环: R7*(m+3) = 15*33333 = 499995us DJNZ 2us + R6赋值1us = 3us循环外: 5us⼦程序调⽤2us +⼦程序返回2us + R7赋值1us = 5us延时总时间=三层循环+循环外= 499995+5 = 500000us =500ms计算公式:延时时间=[(2*R5+3)*R6+3]*R7+5⼆. 200ms延时⼦程序void delay200ms(void){unsignedchari,j,k;for(i=5;i>0;i--)for(j=132;j>0;j--)for(k=150;k>0;k--);}产⽣的汇编C:0x0800 7F05 MOV R7,#0x05C:0x0802 7E84 MOV R6,#0x84C:0x080C 22 RET三. 10ms延时⼦程序void delay10ms(void){unsignedchari,j,k;for(i=5;i>0;i--)for(j=4;j>0;j--)for(k=248;k>0;k--);}产⽣的汇编C:0x0800 7F05 MOV R7,#0x05C:0x0802 7E04 MOV R6,#0x04C:0x0804 7DF8 MOV R5,#0xF8C:0x0806 DDFE DJNZ R5,C:0806C:0x0808 DEFA DJNZ R6,C:0804C:0x080A DFF6 DJNZ R7,C:0802C:0x080C 22 RET四. 1s延时⼦程序void delay1s(void){unsignedcharh,i,j,k;for(h=5;h>0;h--)for(i=4;i>0;i--)for(j=116;j>0;j--)for(k=214;k>0;k--); }对1s延时的验证:1.设置仿真的晶振为12MHz2.在延时函数设置断点3.单步运⾏程序,到达延时函数的⼊⼝4.先记下进⼊延时函数的时间5.step out跳出函数,记下此时时间,两个时间相减即为延时函数运⾏时间函数运⾏时间=1.00041400-0.00041600≈1s产⽣的汇编C:0x0808 DCFE DJNZ R4,C:0808C:0x080A DDFA DJNZ R5,C:0806C:0x080C DEF6 DJNZ R6,C:0804C:0x080E DFF2 DJNZ R7,C:0802C:0x0810 22 RET在精确延时的计算当中,最容易让⼈忽略的是计算循环外的那部分延时,在对时间要求不⾼的场合,这部分对程序不会造成影响. void mDelay(unsigned int Delay) //Delay = 1000 时间为1S{unsignedinti;for(;Delay>0;Delay--){for(i=0;i<124;i ){;}}}void waitms(inti){charm;for( ; i ;i--){for(m = 203; m ; m--){_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();}}}延时1ms的函数时钟频率12MHzunsigned intsleepTime;unsingedchar inSleep = 0;void sleepService(void)}void isr_timer(void) //假定定时器中断1ms 中断⼀次。
keil里面时间的精确延时
51单片机 Keil C 延时程序的简单研究61.54.42.*1楼51单片机 Keil C 延时程序的简单研究作者:InfiniteSpace Studio/isjfk51单片机 Keil C 延时程序的简单研究by: InfiniteSpace Studio/isjfk, 1.21.2004任何人都可以在注明原作者和出处的前提下随意转载这篇文章,但不得用于商业目的。
应用单片机的时候,经常会遇到需要短时间延时的情况。
需要的延时时间很短,一般都是几十到几百微妙(us)。
有时候还需要很高的精度,比如用单片机驱动DS18B20的时候,误差容许的范围在十几us以内,不然很容易出错。
这种情况下,用计时器往往有点小题大做。
而在极端的情况下,计时器甚至已经全部派上了别的用途。
这时就需要我们另想别的办法了。
以前用汇编语言写单片机程序的时候,这个问题还是相对容易解决的。
比如用的是12MHz晶振的51,打算延时20us,只要用下面的代码,就可以满足一般的需要:mov r0, #09hloop: djnz r0, loop51单片机的指令周期是晶振频率的1/12,也就是1us一个周期。
mov r0, #09h需要2个极其周期,djnz也需要2个极其周期。
那么存在r0里的数就是(20-2)/2。
用这种方法,可以非常方便的实现256us以下时间的延时。
如果需要更长时间,可以使用两层嵌套。
而且精度可以达到2us,一般来说,这已经足够了。
现在,应用更广泛的毫无疑问是Keil的C编译器。
相对汇编来说,C固然有很多优点,比如程序易维护,便于理解,适合大的项目。
但缺点(我觉得这是C的唯一一个缺点了)就是实时性没有保证,无法预测代码执行的指令周期。
因而在实时性要求高的场合,还需要汇编和C的联合应用。
但是是不是这样一个延时程序,也需要用汇编来实现呢?为了找到这个答案,我做了一个实验。
用C语言实现延时程序,首先想到的就是C常用的循环语句。
利用Keil调试精确实现软件延时
图2 值得注意的是,用性能分析窗口来观察延时函数的执行时间要求被观察的延时函数中不能再调用其他任何子函数,被测函数只能由C的 基本语句组成,否则观测到的时候并不是整个函数的运行时间。 采用上述方法,得到了以下几个延时程序: /* * 延时400毫秒 */ void Delay400Ms(void){
while(s--){ delay_1_s();
} }
但是我碰到一个比较奇怪的问题:在实现N秒延时函数中,我不调用delay_1_s()这个延时1秒函数,而用delay_1_s()中的语句来替 换delay_1_s(),改后的函数如下:
void delayNs(uchar s) {
uchar loop=10; unint j; while(s--){
比如我需要一个400ms的延时,随便写了个两重循环,外层循环5次,内层循环暂且设为5000: void Delay400Ms(void){
uchar i=5;
unint j; while(i--){
j=5000; while(j--);
//通过keil调试来确定循环次数
} }
在main函数中调用Delay400Ms(): void main()
loop=10; //注意,不能忘了此句 while(loop--){
j=8375; while(j--); } }
}
{ while(1){ P1=0; Delay400ms();
P1=1; }
} 进入uVersion的调试状态,按F10进行单步,当黄色箭头指向Delay400ms()这条语句时记下左边窗中Sys->sec的值,如图, 是0.00042426。
关于51精确延时及keil仿真延时时间
关于51精确延时及keil仿真延时时间
有时候需要精确的延时,比如18B20 温度传感器对时序要求非常严格,必
须精确到微秒级别
一、用NOP 函数
在keil C51 中,直接调用库函数:
#include // 声明了void _nop_(void);
_nop_(); // 产生一条NOP 指令
作用:对于延时很短的,要求在us 级的,采用“_nop_”函数,这个函数相当
汇编NOP 指令,延时几微秒。
NOP 指令为单周期指令,可由晶振频率算出延
时时间,对于12M 晶振,延时1uS。
(若为11.0592MHz,延时为12*(1/11.0592) =1.085uS)。
对于延时比较长的,要求在大于10us,采用C51 中的循环语句来
实现。
二、用for 和while 实现
在选择C51 中循环语句时,要注意以下几个问题
第一、定义的C51 中循环变量,尽量采用无符号字符型变量。
第二、在FOR 循环语句中,尽量采用变量减减来做循环。
第三、在do…while,while 语句中,循环体内变量也采用减减方法。
这因为在C51 编译器中,对不同的循环方法,采用不同的指令来完成的。
下面举例说明:
unsigned char i;
for(i=0;iunsigned char i;
for(i=255;i>0;i--);
其中,第二个循环语句C51 编译后,就用DJNZ 指令来完成,相当于如下指。
用Keil C语言实现精确延时的技术研究
嵌 入式 汇编 , 即在 C语 言程 序 中嵌入 一段 汇编语
言程序 ; 二是 汇 编程序 部 分作 为 c语 言程 序的 一
个 子 函数 , 过 调 用 汇 编子 函数 实 现相 应 操 作 。 通 这两种 方法都 涉 及 到 C语 言与 汇 编 语 言混 合 编 程 的 问题 。混 合 编程 的关 键 主要有 两点 : 1 5 )C 1函数 名 的转换 及 其命 名规 则 ;
宏 的执行 时 间 以及 每 段 子程 序 加 调 用 语 句 所 消 耗 的 时间[ 。在 Ke 5 1 ] iC 1的 C编译 系统 中 , l C语
直接 采用 c语 言 实现 延 时的方 法 , 就是 通 过 C 1 5 编译 器预 先编译 c语 言程 序 , 后研 究它 生成 的 然
邓 全 李 磊 彭凤超
中 国电子 科技 集 团公 司第二 十七研 究所 郑 州 4 0 1 50 5
摘
要: 针对 C语言如何有效实现精确延时 的问题 , 介绍了两种基 于 Ke iC语言环境 的解决方 法 , 结合 l 并
工 程 实 践 , 证 了本 文 方 法 的 有 效 性 。 验
反汇 编语 言代码 , 而保 证延 时 准确性 的方 法 。 从
在汇 编程 序 中 实 现 1 / 0 s延 时 , 常 采用 的  ̄ 通
汇编 代码 为 :
M 0V , R7 #0 H 5 DEL Y:DI Z R7 DELAY A N ,
言程序 能够 和汇 编程 序 实 现方 便 灵 活 的接 口, C
为程序 调试 提 供 必 要 的符 号 信 息 。在 使 用 汇 编
Kel 5 iC 1编译器 S l模式 下 进 行 编译 , 时 程 mal 这
Keil C51精确延时程序(C语言)
Keil C51精确延时程序程序说明如下:振荡频率:12MHz机器周期=12/振荡频率=12/12000000=1us#include <reg52.h>void delay1(unsigned char i){ while(--i);}说明:delay1程序为:延时时间=(2*i+2)*机器周期。
i=1~255。
void delay2(unsigned char i){ while(i--);}说明:delay2程序为:延时时间=(6*i+2)*机器周期。
i=1~255。
void main (void){unsigned char m;delay1(10); //赋值并调延时程序delay1说明:本句为赋值并调用Delayus1:延时时间=(1+2)*机器周期。
全部延时时间为:延时时间=(1+2+2*i+2)*机器周期。
i=1~255。
本例:延时时间=(1+2+2*10+2)*1us=25usdelay2(10); //赋值并调延时程序delay2说明:本句为赋值并调用Delayus2:延时时间=(1+2)*机器周期。
全部延时时间为:延时时间=(1+2+6*i+2)*机器周期。
i=1~255。
本例:延时时间=(1+2+6*10+2)*1us=65usm=10; //赋值,m=1~255while(--m) ; //计算,延时时间=2*m*机器周期说明:本两句为赋值并计算。
全部延时时间为:延时时间=(1+2*m)*机器周期。
m=1~255。
本例:延时时间=(1+2*10)*1us=25uswhile(1);}。
Keil C51精确延时程序设计
Keil C51精确延时程序设计时间:2013-05-16 10:45:33 来源:电子设计工程作者:吴挺运,林成何摘要针对C语言代码的执行时间的可预见性差,结合Keil C51开发工具,分析了在Keil C51开发工具中利用C语言实现精确的延时程序的设计,指出了常用延时方法优缺点。
并通过一些实例分析了延时时间的计算方法,使C语言代码的延时时间可以被预见。
C语言中嵌套汇编语言是一种有效的方法,可以充分发挥出各语言的优势特点、提高开发效率。
关键词 Keil C51;C语言;软件延时;单片机C语言具有较强的数据处理能力、语言功能齐全、使用灵活方便、开发效率高,被广泛应用于在单片机系统开发应用中。
在单片机幕统开发的过程中,经常需要使用到延时程序,但C语言代码执行时间。
的可预见性和实时性较差,在开发一些具有严格通信时序要求的系统时,往往需要反复调试延时代码,给开发者带来了较大困难。
比如使用DS18B20进行温度测控时,必须按照其单总线通信协议,否则无法读取温度数据。
针对上述问题,结合Keil C51开发工具和Proteus仿真软件,介绍在Keil C51开发系统中,利用C语言编写的延时程序设计及其运行的时间的计算方法。
1 常用延时程序的设计方法1.1 利用定时器/计数器延时利用C51单片机内部2个16位定时器/计数器实现精确的程序,由于定时器/计数器不占用CPU的运行时间,可以提高CPU的使用效率。
但假设使用12 MHz晶振,定时器工作在方式1模式下,其最长定时时间也只能达到65.53 ms,由此,可以采用中断方式进行溢出次数累加的方法进行长时间的延时程序设计。
但在开发过程中要考虑C51自动对断点的保护和重装初值所带来的延时误差,也可以使用定时器工作在方式2模式下,减少重装初值所带来的误差。
1.2 利用空操作实现延时当所需的延时非常短,可以利用Keil C51自带intrins.h头文件中的_nop_()函数实现函数延时。
关于51精确延时及keil仿真延时时间
假设参数变量 i 的初值为 m,参数变量 j 的初值为 n,参数变量 k 的初值为 l,则总延时时间为:l 乘以(n 乘以(m 乘以 T+2T)+2T)+3T,其中 T 为 DJNZ 和 MOV 指令执行的时间。当 m=n=l 时,精确延时为 9T,最短;当 m=n=l=256 时,精确延时到 169080102029da1.html 三、下面介绍一下如何用 keil 仿真延时时间 测试函数: void TempDelay (unsigned char idata us) { while(us--); } 测试用例: TempDelay(80); //530uS TempDelay(14); //100uS
LOOP2: MOV R6,#0FFH LOOP1: DJNZ R6,LOOP1 DJNZ R7,LOOP2 这些指令的组合在汇编语言中采用 DJNZ 指令来做延时用,因此它的时间 精确计算也是很简单,假上面变量 i 的初值为 m,变量 j 的初值为 n,则总延 时时间为:m 乘以(n 乘以 T+T),其中 T 为 DJNZ 指令执行时间(DJNZ 指令为 双周期指令)。这里的+T 为 MOV 这条指令所使用的时间。同样对于更长时间 的延时,可以采用多重循环来完成。 只要在程序设计循环语句时注意以上几个问题。 下面给出有关在 C51 中延时子程序设计时要注意的问题 1、在 C51 中进行精确的延时子程序设计时,尽量不要或少在延时子程序 中定义局部变量,所有的延时子程序中变量通过有参函数传递。 2、在延时子程序设计时,采用 dowhile,结构做循环体要比 for 结构做循 环体好。 3、在延时子程序设计时,要进行循环体嵌套时,采用先内循环,再减减比 先减减,再内循环要好。
while(i); 或 unsigned char i,j i=255; while(i) {j=255; while(j) {j--}; i--; } 这三种方法都是用 DJNZ 指令嵌套实现循环的,由 C51 编译器用下面的指 令组合来完成的 MOV R7,#0FFH
仿真测量KeilC的循环延时
仿真实测KeilC的循环延时
在KeilC编程中,经常要用到延时语句,最常用的就是使用for或者是while循环。
为了较准确掌握延时时间,我用KeilC的调试功能对一些语句的运行时间进行测量,以下是测量结果(使用Atmel公司的89C52单片机,12M晶振)。
1.for循环和while循环耗时相同;
2.无符号字符型变量,递减循环,每循环需要2个机器周期;
3.无符号字符型变量,递增循环,每循环需要3个机器周期;
4.无符号整型变量,不论递增或递减循环,每循环需要8个机器周期;
5.若循环中加上对IO位的条件判断,则不论变量类型或增减类型,每循环需要20个机器周期;
以上为实测内容,未认真分析每条语句运行耗费的机器周期,若有错误之处,请各位高手指正。
———山野村夫
2016-3-15。
Keil仿真及软件延时语句的精确计算
Keil仿真及延时语句的精确计算
1、编写程序:
2、点击工程设置对话框,弹出
将晶振的默认值修改为实验板上的晶振频率,eg:11.0592,单击“确定”,完成设置3、单击窗口上的调试按钮,进入软件模拟调试模式。
:将程序复位到主函数的最开始处,准备重新运行程序;
:全速运行,运行程序时中间不停止;
:停止全速运行
:进入子函数内部
:单步执行代码,不进入子函数内部,可直接跳过函数
:跳出当前进入的函数
:程序直接运行至当前光标所在行;
:显示/隐藏编译窗口,可以查看每句C语言编译后对应的汇编代码
:显示/隐藏变量观察窗口,可以查看各个变量值的变化状态
4、查看硬件IO口电平变化:
选择IO口
查看IO状态:
5、查看变量的变化:
十进制显示:
十六进制显示:
十-----十六进制转换:
寄存器窗口:
其中sec 0.00042209=422.09us,程序启动执行到目前停止位置所花的所有时间,(这个时间是累积的)
A:单步执行所花的时间:
423.18-422.09=1.09us,恰好是51单片机在11.0592晶振频率下,一个机器周期(12个时钟周期)所花费的时间
B:延时语句的精确计算
在延时语句的两头设置端点:
点击全速运行,运行到第一个断点处,记录
再点击全速运行,运行到第二个断点处,记录968.31272ms 两个sec之差约为1s。
Keil C51程序设计中几种精确延时方法
器 延 时 从 程 序 的 执 行 效 率 和 稳 定 性 两 方 面 考 虑 都 是 最 佳
的 方 案 。但 应该 注 意 , 1编 写 的 中断 服 务 程 序 编 译 后 会 C5
自动 加 上 PUS AC P H S 、 OP P W 和 PO H C、 US P W P S P
R
JJ J c…
…
维普资讯
。
珏 譬
I
z
一
N U -( ); J
◆ #p a maam、 rg n a m 和 a m 只 能在 函 rg s #p a mae d s s 数 内使 用 。
一
NOP () 一 ;
N0 P () ;
AC C语 句 , 行 时 占用 了 4个 机 器 周 期 ; 程 序 中还 有 计 执 如 数 值加 1语 句 , 又 会 占用 1个机 器 周 期 。这 些 语 句 所 消 则 耗 的 时 间在 计 算 定 时初 值 时 要 考 虑 进 去 , 初值 中减 去 以 从
达 到最 小 误 差 的 目的 。
一
一
将 汇 编 语 言 与 C 1结 合 起 来 , 分 发 挥 各 自的 优 势 , 5 充
无 疑 是 单 片 机 开 发 人 员 的 最佳 选 择 。
}
Dea l u () ly 0 s 函数 中共 用 了 6个一 NOP () 句 , 个 一 语 每
语 句 执 行 时 间 为 1U 。主 函 数 调 用 Dea l u () , 执 S ly 0 s 时 先 行一 个 L CALL指 令 ( s , 后 执 行 6个一 2 )然 NOP () 句 一 语
维普资讯
K iC 1 序设 计中几 种精确 延 时方法 * el 5 程
Keil C中软件实现精确延时的几种方法
两种循环可以单独使用,也可以嵌套使用,即可以编写成延时函数使用,也可以在程序中直接使用,但是会有微小的差别,即增加了调用函数的时间。下面的函数可实现1ms到1s的延时,误差为16us,基本满足一般应用的要求。需要注意的是使用不同的循环变量类型,得到的延时也会不同。
[3]徐爱钧.Keil Cx51 V7.0单片机高级语言编程与uVision2应用实践[M].北京:电子工业出版社,2004.
void Delayl0us()
{
_nop_();
_nop_();
_nop_();
_nop_();
_p_();
_nop_();
}
每个语句执行时间为1us,主函数调用Delayl0us()时,先执行一个LCALL指令(2us),然后执行6个_nop_()语句(6us),最后执行了一个RET指令(2s),所以执行上述函数时共需要10us。可以把这一函数当作基本延时函数,在其他函数中调用,即嵌套调用,以实现较长时间的延时;但需要注意,如在Delay40us()中直接调用4次Delayl0us()函数,得到的延时时间将是42us,而不是40us。这是因为执行Delay40us()时,先执行了一次LCALL指令(2us),然后开始执行第一个Delayl0us(),执行完最后一个Delayl0us()时,直接返回到主程序。依此类推,如果是两层嵌套调用,如在Delay80us()中两次调用Delay40us(),则也要先执行一次LCALL指令(2us),然后执行两次Delay40us()函数(84us),所以,实际延时时间为86us。简言之,只有最内层的函数执行RET指令。该指令直接返回到上级函数或主函数。如在Delay80us()中直接调用8次Delayl0us(),此时的延时时间为82us。通过修改基本延时函数和适当的组合调用,上述方法可以实现不同时间的延时。在KeilC语言中,使用_nop_()语句需要在程序的前面加上“#include<intrins.h>”语句。每一个_nop()_语句编译后需要一个字节的程序空间。因此在短暂延时的场合使用较多。
Keil C下用软件精确延时的实现
KelC 下 用 软 件 精 确 延 时 的 实 现 i
鲁 庆 宾 , 艳 玲 邵
( 阳理 工 学 院 南
摘
河南 南 阳
4 30 7 0 4)
要 : 单 片 机 的应 用 系 统 中 , 常 需 要 用 到 不 同 精 度 的 时 间 延 时 , 不 同场 合 下 , 时 时 间 可 能 从 几 微 秒 到 几 在 经 在 延
NOP
一 一
用 汇编语 言 实现 这些延 时 , 是非 常 简单 的事 情 ,
因为延 时时 间很 容易 计算 。 但 是 汇 编 语 言 是 针 对 具 体 的 微 处 理 器 而 特 有
的 , 了 通 用 性 差 , 可 移 植 的 特 点 外 , 大 的 问 题 除 不 最
() 指 令 每 增 加 一 条 , 时 时 间 增 ; 延
0 前 言
单 片 机 因 为 体 积 小 、 能 强 、 制 灵 活 的 特 点 在 功 控 各 个 领 域 内 有 着 非 常 广 泛 的 应 用 , 制 过 程 中 经 常 控
v i ea od d ly()
{
一
NOP
一
( );
}
会 遇 到不 同精度 的时 间需 求 , 如键 盘去 抖延 时 、 据 数
精确计算 , 以满 足 不 同场 合 的需 求 。 关 键 词 : e ; 编 语 言 ; 片机 ; 确 延 时 ; 时 器 KiC 汇 l 单 精 定
中 图 分 类 号 :T 3 9 0 P 0 .5 文 献 标 识 码 :A
#i ude < i rns ncl nti .h >
间选择不 同的方法 。
fr i o ( =0; <l; + +) i i :
c51的精确延时
注:1.编译软件为"Keil uVision3"(Keil uVision2也试用)。用其他编译软件的话就不准了。
2.需要包含头文件<intrins.h>
3.所有函数的延时时间都是在12Mhz晶振下计算的,如用其他晶振需进行换算。
4.函数的执行时间为“函数的参数”乘以精确到的时间。例如delayms(unsigned char n)函数,其精确度为1ms,如果写入语句delayms(4),那就是延时4ms。
用c语言为单片机编程无疑十分节约时间,可在很短的时间内开发出较高效的代码,对于程序的维护和扩充也较汇编语言方便许多。
但c语言也有它的不足之处,那就是在时间的精确控制上。要想用c实现精确的延时,只能把c的函数编译成汇编语言,然后按照汇编语言计算其执行时间。本人就按照这种方法,编写了几个51单片机的c语言精确延时函数。
(2)精确到100us的延时(12MHz)
void delay100us(unsigned char n)
{ unsigned char i;
for(;n;n--)
{ _nop_();
for(i=46;i;i--);
}
}
(3)精确的半毫秒延时函数(12MHz)
5.计算出来的延时时间不包括函数调用与返回的时间。如果函数的精确度较高,且参数较小,那么实际延时时间就可能与计算的时间差很远。
(1)精确到2us的延时(12MHz)
void delayus(unsigned char n)
{ while(--n);
}
void delay1_2ms(unsigned char n)
{ unsigned char i;
Keil C51程序设计中几种精确延时方法
Keil C51程序设计中几种精确延时方法
段向东;毋茂盛;毋玉芝
【期刊名称】《单片机与嵌入式系统应用》
【年(卷),期】2007(000)012
【摘要】实际的单片机应用系统开发过程中,由于程序功能的需要,经常编写各种延时程序,延时时间从数微秒到数秒不等,对于许多C51开发者特别是初学者编制非常精确的延时程序有一定难度.本文从实际应用出发,讨论几种实用的编制精确延时程序和计算程序执行时间的方法,并给出各种方法使用的详细步骤,以便读者能够很好地掌握理解.
【总页数】3页(P33-35)
【作者】段向东;毋茂盛;毋玉芝
【作者单位】河南师范大学;河南师范大学;焦作大学
【正文语种】中文
【中图分类】TP3
【相关文献】
1.利用C51开发单片机应用系统中几种延时方法的研究 [J], 方玉甫;李振璧
2.KeilC51精确延时程序设计 [J], 吴挺运;林成何
3.Keil C51中C51程序与汇编程序的接口方法 [J], 张玉峰;荀建军
4.单片机软件精确延时计算和延时程序设计方法 [J], 张剑锋;陈锐;陈慕君;曾凡娇
5.Keil C51通用精确延时程序设计 [J], 余巧书
因版权原因,仅展示原文概要,查看原文内容请购买。
Keil C51程序设计中几种精确延时方法 精确延时
Keil C51程序设计中几种精确延时方法2008-04-03 08:48实现延时通常有两种方法:一种是硬件延时,要用到定时器/计数器,这种方法可以提高CPU的工作效率,也能做到精确延时;另一种是软件延时,这种方法主要采用循环体进行。
1 使用定时器/计数器实现精确延时单片机系统一般常选用11.059 2 MHz、12 MHz或6 MHz晶振。
第一种更容易产生各种标准的波特率,后两种的一个机器周期分别为1 μs和2 μs,便于精确延时。
本程序中假设使用频率为12 MHz的晶振。
最长的延时时间可达216=65 536 μs。
若定时器工作在方式2,则可实现极短时间的精确延时;如使用其他定时方式,则要考虑重装定时初值的时间(重装定时器初值占用2个机器周期)。
在实际应用中,定时常采用中断方式,如进行适当的循环可实现几秒甚至更长时间的延时。
使用定时器/计数器延时从程序的执行效率和稳定性两方面考虑都是最佳的方案。
但应该注意,C51编写的中断服务程序编译后会自动加上PUSH ACC、PUSH PSW、POP PSW和POP ACC语句,执行时占用了4个机器周期;如程序中还有计数值加1语句,则又会占用1个机器周期。
这些语句所消耗的时间在计算定时初值时要考虑进去,从初值中减去以达到最小误差的目的。
2 软件延时与时间计算在很多情况下,定时器/计数器经常被用作其他用途,这时候就只能用软件方法延时。
下面介绍几种软件延时的方法。
2.1 短暂延时可以在C文件中通过使用带_NOP_( )语句的函数实现,定义一系列不同的延时函数,如Delay10us( )、Delay25us( )、Delay40us( )等存放在一个自定义的C文件中,需要时在主程序中直接调用。
如延时10 μs 的延时函数可编写如下:void Delay10us( ) {_NOP_( );_NOP_( );_NOP_( )_NOP_( );_NOP_( );_NOP_( );}Delay10us( )函数中共用了6个_NOP_( )语句,每个语句执行时间为1 μs。
keil延时函数
keil延时函数Keil是一种常用的嵌入式开发工具,它提供了方便易用的编程环境,包括了编译器、调试器以及一系列辅助工具。
在Keil中,延时函数是我们经常使用的一个功能,它可以帮助我们在程序中实现延时的效果。
接下来,我将详细介绍Keil的延时函数。
在Keil中,延时函数实际上是通过软件实现的,主要是利用了内部的计时器和系统时钟来实现精确的延时。
Keil提供了一系列的延时函数,可以满足不同需求的延时操作。
在Keil中,最常用的延时函数是`delay`函数。
它的原型如下:```cvoid delay(unsigned int count);```这个函数的参数`count`表示要延时的时间,单位是毫秒(ms)。
例如,如果我们调用`delay(1000)`,那么程序会延时1秒钟。
在这个函数内部,程序会利用一个循环来进行延时操作,具体的实现如下:```cvoid delay(unsigned int count)unsigned int i,j;for(i=0;i<count;i++)for(j=0;j<1000;j++);```在这个函数中,我们通过两个嵌套的`for`循环来进行延时操作。
外层循环控制延时的次数,内层循环用来进行具体的延时。
每次内层循环都会执行1000次,而每次内层循环的执行时间取决于系统时钟的频率。
除了`delay`函数外,Keil还提供了其他一些延时函数,可以根据具体需求选择使用。
以下是其中一些常用的延时函数:1. `void delay_us(unsigned int us)`:这个函数用于实现微秒级别的延时,单位是微秒(us)。
2. `void delay_ms(unsigned int ms)`:这个函数用于实现毫秒级别的延时,单位是毫秒(ms)。
3. `void delay_sec(unsigned int sec)`:这个函数用于实现秒级别的延时,单位是秒(sec)。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
Keil仿真及延时语句的精确计算
1、编写程序:
2、点击工程设置对话框,弹出
将晶振的默认值修改为实验板上的晶振频率,eg:11.0592,单击“确定”,完成设置3、单击窗口上的调试按钮,进入软件模拟调试模式。
:将程序复位到主函数的最开始处,准备重新运行程序;
:全速运行,运行程序时中间不停止;
:停止全速运行
:进入子函数内部
:单步执行代码,不进入子函数内部,可直接跳过函数
:跳出当前进入的函数
:程序直接运行至当前光标所在行;
:显示/隐藏编译窗口,可以查看每句C语言编译后对应的汇编代码
:显示/隐藏变量观察窗口,可以查看各个变量值的变化状态
4、查看硬件IO口电平变化:
选择IO口
查看IO状态:
5、查看变量的变化:
十进制显示:
十六进制显示:
十-----十六进制转换:
寄存器窗口:
其中sec 0.00042209=422.09us,程序启动执行到目前停止位置所花的所有时间,(这个时间是累积的)
A:单步执行所花的时间:
423.18-422.09=1.09us,恰好是51单片机在11.0592晶振频率下,一个机器周期(12个时钟周期)所花费的时间
B:延时语句的精确计算
在延时语句的两头设置端点:
点击全速运行,运行到第一个断点处,记录
再点击全速运行,运行到第二个断点处,记录968.31272ms 两个sec之差约为1s。