Keil纯软件延时程序

合集下载

使用KeilC进行51单片机延时程序编写的几点心得

使用KeilC进行51单片机延时程序编写的几点心得

使用KeilC进行51单片机延时程序编写的几点心得使用Keil C进行51单片机延时程序编写的几点心得应用单片机的时候,经常会遇到需要短时间延时的情况。

需要的延时时间很短,一般都是几十到几百微妙(us)。

有时候还需要很高的精度,比如用单片机驱动DS18B20的时候,误差容许的范围在十几us以内,不然很容易出错。

这种情况下,用计时器往往有点小题大做。

而在极端的情况下,计时器甚至已经全部派上了别的用途。

这时就需要我们另想别的办法了。

以前用汇编语言写单片机程序的时候,这个问题还是相对容易解决的。

比如用的是12MHz 晶振的51,打算延时20us,只要用下面的代码,就可以满足一般的需要:mov r0,#09hloop:djnzr0,loop51 单片机的指令周期是晶振频率的1/12,也就是1us一个周期。

mov r0,#09h需要2个极其周期,djnz也需要2个极其周期。

那么存在r0里的数就是(20-2)/2。

用这种方法,可以非常方便的实现256us以下时间的延时。

如果需要更长时间,可以使用两层嵌套。

而且精度可以达到2us,一般来说,这已经足够了。

现在,应用更广泛的毫无疑问是Keil的C编译器。

相对汇编来说,C固然有很多优点,比如程序易维护,便于理解,适合大的项目。

但缺点(我觉得这是C的唯一一个缺点了)就是实时性没有保证,无法预测代码执行的指令周期。

因而在实时性要求高的场合,还需要汇编和C的联合应用。

但是是不是这样一个延时程序,也需要用汇编来实现呢?为了找到这个答案,我做了一个实验。

用C语言实现延时程序,首先想到的就是C常用的循环语句。

下面这段代码是我经常在网上看到的:void delay2(unsigned char i){for(; i != 0; i--);}。

keil中延时函数

keil中延时函数

keil中延时函数
Keil中的延时函数是指在程序运行时,通过调用Keil提供的延时函数来实现程序暂停一定时间的效果。

这种功能常常被用于等待外设响应、调试代码等方面。

Keil提供了两种主要的延时函数:__delay()和__delay_ms()。

其中,__delay()函数的参数为CPU时钟周期数量,而__delay_ms()函数的参数为毫秒数。

这两个函数的实现机制都是基于循环计数实现的。

使用Keil中的延时函数时,需要注意以下几点:
1. 在使用__delay()函数时,需要根据CPU时钟频率计算出需要延迟的CPU时钟周期数量。

2. 在使用__delay_ms()函数时,需要根据CPU时钟频率和需要延迟的毫秒数来计算出需要调用的延时函数次数。

3. 延时函数执行时会占用CPU资源,因此需要注意不要过度使用延时函数,以免影响程序的运行效率。

4. 在使用延时函数时,需要考虑系统的实时性和稳定性,以确保程序的正确性和安全性。

总之,Keil中的延时函数是一种非常常用的程序设计方法,掌握其使用方法对于编写嵌入式系统程序非常重要。

- 1 -。

Keil仿真及软件延时语句的精确计算

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调试精确实现软件延时

利用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。

KeilC51程序设计中几种精确延时方法

KeilC51程序设计中几种精确延时方法

Keil C51程序设计中几种精确延时方法2009年05月16日星期六 14:35转自:/archive/2009/03/06/1404721.html来源:嵌入式技术网作者:河南师范大学段向东毋茂盛时间:2007-12-19 发布人:林逸--------------------------------------------------------------------------------------------摘要实际的单片机应用系统开发过程中,由于程序功能的需要,经常编写各种延时程序,延时时间从数微秒到数秒不等,对于许多C51开发者特别是初学者编制非常精确的延时程序有一定难度。

本文从实际应用出发,讨论几种实用的编制精确延时程序和计算程序执行时间的方法,并给出各种方法使用的详细步骤,以便读者能够很好地掌握理解。

引言单片机因具有体积小、功能强、成本低以及便于实现分布式控制而有非常广泛的应用领域[1]。

单片机开发者在编制各种应用程序时经常会遇到实现精确延时的问题,比如按键去抖、数据传输等操作都要在程序中插入一段或几段延时,时间从几十微秒到几秒。

有时还要求有很高的精度,如使用单总线芯片DS18B20时,允许误差范围在十几微秒以内[2],否则,芯片无法工作。

用51汇编语言写程序时,这种问题很容易得到解决,而目前开发嵌入式系统软件的主流工具为C 语言,用C51写延时程序时需要一些技巧[3]。

因此,在多年单片机开发经验的基础上,介绍几种实用的编制精确延时程序和计算程序执行时间的方法。

实现延时通常有两种方法:一种是硬件延时,要用到定时器/计数器,这种方法可以提高CPU的工作效率,也能做到精确延时;另一种是软件延时,这种方法主要采用循环体进行。

1 使用定时器/计数器实现精确延时单片机系统一般常选用11.059 2 MHz、12 MHz或6 MHz晶振。

第一种更容易产生各种标准的波特率,后两种的一个机器周期分别为1 μs和2 μs,便于精确延时。

KeilC51程序设计中几种精确延时方法

KeilC51程序设计中几种精确延时方法
将汇编语言与 C51 结合起来 ,充分发挥各自的优势 , 无疑是单片机开发人员的最佳选择 。
2. 3 使用示波器确定延时时间
熟悉硬件的开发人员 ,也可以利用示波器来测定延时 程序执行时间 。方法如下 : 编写一个实现延时的函数 ,在 该函数的开始置某个 I/ O 口线如 P1. 0 为高电平 ,在函数 的最后清 P1. 0 为低电平 。在主程序中循环调用该延时函 数 ,通过示波器测量 P1. 0 引脚上的高电平时间即可确定 延时函数的执行时间 。方法如下 :
Dly T) ,经过反汇编后得到如下代码 :
C :0x0014 DFFE DJ NZ R7 ,C :0014 / / 2 T 可以看出 ,这时代码只有 1 句 ,共占用 2 个机器周期 , 精度达到 2 μs ,循环体耗时 Dly T ×2 个机器周期 ;但这时 应该注意 ,Dly T 初始值不能为 0 。 这 3 种循环结构的延时与循环次数的关系如表 1 所列 。
用; ◆ 在程序的开头应加上预处理指令 # pragma asm ,
在该指令之前只能有注释或其他预处理指令 ; ◆ 当使用 asm 语句时 ,编译系统并不输出目标模块 ,
而只输出汇编源文件 ; ◆ asm 只能用小写字母 ,如果把 asm 写成大写 ,编译
系统就把它作为普通变量 ;
◆ # pragma asm 、# pragma endasm 和 asm 只能在函 数内使用 。
Keil C51 精确延时 程序执行时间
引 言
单片机因具有体积小 、功能强 、成本低以及便于实现 分布式控制而有非常广泛的应用领域[1] 。单片机开发者 在编制各种应用程序时经常会遇到实现精确延时的问题 , 比如按键去抖 、数据传输等操作都要在程序中插入一段或 几段延时 ,时间从几十微秒到几秒 。有时还要求有很高的 精度 ,如使用单总线芯片 DS18B20 时 ,允许误差范围在十 几微秒以内[2] ,否则 ,芯片无法工作 。用 51 汇编语言写程 序时 ,这种问题很容易得到解决 ,而目前开发嵌入式系统 软件的主流工具为 C 语言 ,用 C51 写延时程序时需要一 些技巧[3] 。因此 ,在多年单片机开发经验的基础上 ,介绍 几种实用 的 编 制 精 确 延 时 程 序 和 计 算 程 序 执 行 时 间 的 方法 。

Keil C51精确延时程序(C语言)

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精确延时程序设计

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_()函数实现函数延时。

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

keil调试延时程序
2007-11-25 22:20
时间的单位换算
1秒=1000毫秒(ms) 1毫秒=1/1,000秒(s)
1秒=1,000,000 微秒(μs) 1微秒=1/1,000,000秒(s)
1秒=1,000,000,000 纳秒(ns) 1纳秒=1/1,000,000,000秒(s)
1秒=1,000,000,000,000 皮秒(ps) 1皮秒=1/1,000,000,000,000秒(s)
参考资料:资料
用定时器延时,有时候显得有点麻烦,我们不如考虑软件精确延时,软件延时无非就是利用for或while多重循环。

以前用到延时函数时,都是从网上下载别人写好的延时子程序。

延时5ms,400ms,1s,……,这些延时函数的函数名中都清清楚楚地标明了延时的时间,可我一直不知道这些函数是如何编写的,确切地说,是如果根据延时时间来确定循环次数的。

如果是纳秒级的延时,可以通过示波器来观察波形,或者反汇编一下,计算一下指令执行时间,但如果延时时间相对较长,示波器便无能为力了。

这几天好好看了一下Keil调试,发现Keil 的功能实在是太强大了。

利用Keil uVersion的调试就可以写出精确的软件延时程序。

以下是我的简单小结,文中所有程序都是在Xtal=11.0592MHZ下测试。

比如我需要一个400ms的延时,随便写了个两重循环,外层循环5次,内层循环暂且设为5000:
void Delay400Ms(void){
uchar i=5;
unint j;
while(i--){
j=5000; //通过keil调试来确定循环次数
while(j--);
}
}
在main函数中调用Delay400Ms():
void main()
{
while(1){
P1=0;
Delay400ms();
P1=1;
}
}
进入uVersion的调试状态,按F10进行单步,当黄色箭头指向Delay400ms()这条语句时记下左边窗中Sys->sec的值,如图,是0.00042426。

再按F10,执行完Delay400ms()后,sec值变为0.38858181,此时记录刚才的初值0.00042426,结果0.38815755即说明执行Delay400ms()耗时388.15755ms,由此可见还未达到400ms的延时要求。

此时,增加内循环的次数,将j的值增加到6700,再重复上述过程,算得0.40009874,即Delay400ms()程序延时400.09874ms,此时已经符合延时400ms的要求。

除了上述所说的观察sec值来确定延时时间外,还可以从Keil的性能分析窗口中观测到执行Delay400ms()函数的时间。

进入调试状态后使用菜单View->Performance Analyzer Window,打开性能分析对话框,进入该对话框后,只有一项unspecified,点鼠标右键,在快捷菜单中选择Setup PA即打开性能分析设置对话框,对于C 语言程序,该对话框右侧的“Function Symbol”下的列表框给出函数符号,双击某一符号,该符号即出现在Define Performance Analyzer 下的编缉框中,每输入一个符号名字,点击Define 按钮,即将该函数加入其上的分析列表框。

对于汇编语言源程序,Function Symbol 下的列表框中不会出现子程序名,可以直接在编缉框中输入子程序名,点击Close 关闭窗口,回到性能分析窗口,此时窗口共有4 个选项。

全速执行程序,可以看到Delay400Ms 后出现一个蓝色指示条,配合上面的标尺可以直观地看出该函数占整个执行时间的比例,点击相应的函数名,可以在该窗口的状态栏看到更详细的数据,如下图:
值得注意的是,用性能分析窗口来观察延时函数的执行时间要求被观察的延时函数中不能再调用其他任何子函数,被测函数只能由C的基本语句组成,否则观测到的时候并不是整个函数的运行时间。

采用上述方法,得到了以下几个延时程序:
/*
* 延时400毫秒
*/
void Delay400Ms(void){ uchar i=5;
unint j;
while(i--){
j="6699";
while(j--);
}
}
/*
* 延时1秒
*/
void delay_1_s()
{
uchar loop="10";
unint j;
while(loop--){
j="8375";
while(j--);
}
}
/*
* 延时N 秒,参数s为需要延时的秒数*/
void delay_N_s(uchar s)
{
while(s--){
delay_1_s();
}
}。

相关文档
最新文档