用定时器延时,有时候显得有点麻烦,我们不如考虑软件精确延时,软件延时无非就是利用for或while多重循环。以前用到延时函数时,都是从网上下载别人写好的延时子程序。延时5ms,400ms,1s,……,这些延时函数的函数名中都清清楚楚地标明了延时的时间,可我一直不知道这些函数是如何编写的,确切地说,是如果根据延时时间来确定循环次数的。如果是纳秒级的延时,可以通过示波器来观察波形,或者反汇编一下,计算一下指令执行时间,但如果延时时间相对较长,示波器便无能为力了。这几天好好看了一下Keil调试,发现Keil的功能实在是太强大了。利用Keil uVersion的调试就可以写出精确的软件延时程序。以下是我的简单小结,文中所有程序都是在Xtal=11.0592MHZ下测试。 ~%k{\F
M -5gQ*N^
$m.><!
比如我需要一个400ms的延时,随便写了个两重循环,外层循环5次,内层循环暂且设为5000: 5Xvp`Qq
E2|"juE
void Delay400Ms(void){ dy,Os v
P/70xn_s
uchar i=5; P(CCz 8aJ
`2H(@yNpe
unint j; Xdj,/|(noI
}=v)GdD ]
while(i--){ oAG?{HV
k_-lj\
j=5000; //通过keil调试来确定循环次数 &kdiq=U
:kAR!
while(j--); 8,*7pj
9i[:N8~
} 9(c&bSZ<
/6fjujivd,
} x=V4wh5
Y zcA>8
在main函数中调用Delay400Ms(): ^' E(g
FWf7GP#
void main() mlr:](Ge2
pXK,Sc+ sK
{ ^?Jz'650
e.*Pn31x
while(1){ ]9 X/FM>c
G4x 8-Lie
P1=0; 8K*.0[4)Lb
-(k'EPZ
Delay400ms(); *;(e
7|A!P >-
P1=1; apT csVx
; |fsk[
} ,-2p tT
R}^-/"5Y|
} WMca'i,]\
KyrG.xgn
进入uVersion的调试状态,按F10进行单步,当黄色箭头指向Delay400ms()这条语句时记下左边窗中Sys->sec的值,如图,是0.00042426。 ;iPv97>
+ &YnDcW
Ffh..d#wE
r?6VH
1WP7"\|
再按F10,执行完Delay400ms()后,sec值变为0.38858181,此时记录刚才的初值0.00042426,结果0.38815755即说明执行Delay400ms()耗时388.15755ms,由此可见还未达到400ms的延时要求。此时,增加内循环的次数,将j的值增加到6700,再重复上述过程,算得0.40009874,即Delay400ms()程序延时400.09874ms,此时已经符合延时400ms的要求。 tLC%5b`*
Ha;[~go
除了上述所说的观察sec值来确定延时时间外,还可以从Keil的性能分析窗口中观测到执行Delay400ms()函数的时间。进入调试状态后使用菜单View->Performance Analyzer Window,打开性能分析对话框,进入该对话框后,只有一项unspecified,点鼠标右键,在快捷菜单中选择Setup PA即打开性能分析设置对话框,对于C 语言程序,该对话框右侧的“Function Symbol”下的列表框给出函数符号,双击某一符号,该符号即出现在Define Performance Analyzer 下的编缉框中,每输入一个符号名字,点击Define 按钮,即将该函数加入其上的分析列表框。对于汇编语言源程序,Function Symbol 下的列表框中不会出现子程序名,可以直接在编缉框中输入子程序名,点击Close 关闭窗口,回到性能分析窗口,此时窗口共有4 个选项。全速执行程序,可以看到Delay400Ms 后出现一个蓝色指示条,配合上面的标尺可以直观地看出该函数占整个执行时间的比例,点击相应的函数名,可以在该窗口的状态栏看到更详细的数据,如下图: /L-,)u(*O
jYr&^0
FW(pBi1T=|
值得注意的是,用性能分析窗口来观察延时函数的执行时间要求被观察的延时函数中不能再调用其他任何子函数,被测函数只能由C的基本语句组成,否则观测到的时候并不是整个函数的运行时间。 OAb:Tgfy3
] @yAH/
采用上述方法,得到了以下几个延时程序: ;S- ,O!&:^
*M 2Gc6&
/* NgEsN
l3!5KG )
* 延时400毫秒 C.>O25L<3h
{jgvM(?4
*/ ]C4yX !q
~?'|S=A
void Delay400Ms(void){ >]%5lM'
:WL,h!]g
uchar i=5; J8N2E]
~Tn U#U,
unint j; t ^jbX }
clN m*[}vi
while(i--){ #l-D&((z p
+V$)j}mxc
j="6699";
Ds2?,{d_
while(j--); P BPL1V&:5
GN{ED't0W
} X= E3X8^=
\
} 6Yip `LU0
$6\ t(=
-}e#s4Yf
/* BLCZp
0 tc4v{k=
* 延时1秒 hqbA+7k o|
(| y%0
*/ )neF0A 5E
><tx.m;
void delay_1_s() <)\d!>
NF6`L(Ms
{ xpV =]K
xv
uchar loop="10"; TiM^-*b&5
ir,zOBJ,9
unint j; U5}gay
5Y |>LJ\
while(loop--){ zal0-#Ld;
`&H\6&<d
j="8375"; O~E0"p>Yv
oXbDiKtsV
while(j--); ^W:Iz[P`J
p;xE"nzdC
} I~@>&5LNV
}Y8{{U+FT
} uj^ZxNMQ
$';?T/,d
K{K2\cPt
/* 33E l"*,
tO>0?~Xt
* 延时N 秒,参数s为需要延时的秒数 LOhd]E?LiV
yJ`NQ
*/ A5Ov(ANT
PW3sRcJq
void delay_N_s(uchar s) @'9Q@CJDJ
e/duOeN
{ t}B~
u8p
while(s--){ $*fz k$
SB7i|$b#
delay_1_s(); gL$b&U]j2)
/w}Al2M
} flcDM_ R(
8Yz(av] <
}
关键字:Keil u3调试 软件延时
引用地址:
利用Keil u3调试,精确实现软件延时
推荐阅读最新更新时间:2024-03-16 15:16
解决STM32在MDK-ARM(KEIL)编译时出现 已停止工作
若是关闭对话框还可继续编译,只是到最后linking时显示一个error,提示 ..OBJXXX.axf: error: L6002U: Could not open file ..objXXX.o: No such file or directory ..OBJtest.axf - 1 Error(s), 0 Warning(s). 从网上查到很多相同问题,但是回答者都是简简单单说几句是什么原因就走了...这就是大神的通病吧,忙活自己的事去了... 解决: 1、右键我的电脑-管理-本地用户和组-用户 把里面你的中文用户名改成英文。 2、右键我的电脑-属性 右下-计算机名称、域和工作组设置-更改设置 改成
[单片机]
STM32内部RAM在线调试配置方法及详细说明 (基于Keil开发工具)
Ⅰ、写在前面 本文主要讲述的内容:基于Keil开发工具下,STM32内部RAM在线调试配置方法,以及每一项配置的详细说明。 让程序运行在RAM中调试代码有两优点:1.速度快;2.减少对芯片FLASH读写次数,增加芯片寿命。 本文牵涉的知识比较多,如果弄明白所有细节问题,对自己这方面的技能是一种很大的提升。 本文基于ST公司Cortex-M内核的STM32来讲述其配置方法,其实也适用于其他公司(如:TI、NXP等)的Cortex-M芯片,原理都是一样的。 本文PDF文章可以在我360云盘下载: https://yunpan.cn/ckvUU7t8vuWbn访问密码 42b3 关于本文的更多详情请往下看。 Ⅱ、本文要点
[单片机]
N76E003 Keil设置芯片使用FLASH的地址空间
这篇文章讲的是如何设置芯片使用FLASH的大小,比如新塘的芯片N76E003的FLASH大小只有18K,但是我需要一些空间存储一些别的信息,掉电不丢失,那么我就要把FLASH空间分成两部分,第一部分用作存储代码,第二部分用作存储信息。如果你不设置,默认工程FLASH全部空间都是存储代码的,擦除也是擦除整个芯片。如果要将FLASH分为两部分我这里提供两个思路。 第一:设置擦除使用扇区,计算程序代码大小,将所需要的数据放入代码占用空间之后(最好用最后的地址空间)。 首先设置只擦除使用扇区,如下图,设置Setttings选项时需要Nu-Link连接到目标板,勾选Erase Used Sectors。 之后是计算程序代码大小,
[单片机]
IAR FOR AVR中精确软件延时方法
注意: __delay_cycles(x),x必须是常量或则是常量表达式,如果是变量则编译报错! 在用单片机的时候常常会用到延时函数,430也不例外,常见的形式有: void delay(unsigned int ms) { unsigned int i,j; for( i=0;i ms;i++) for(j=0;j 1141;j++); //8MHz晶振时 } 复制代码//以上程序段在要求延时精度不高的场合可以用。 但在 IAR 软件430的编译器里面我们可以利用它内部的延时子程序来实现我们想要的高精度软件延时,方法如下: (1):将以下这段代码复制到你的.C源文件中。 #define CPU_F ((double)800000
[单片机]
STM32 数据类型定义
在 Keil MDK 开发环境中,经常会遇到类似于unsigned int 8、uint8_t 、u8等数据变量定义,对于初学者来讲确实是有点痛苦,后来查询发现以上三种方式均表示——无符号的8位整形数据。 由于C语言类型的长度完全由编译器决定,char 通常被定义成 8 位宽;int 通常被定义成 16 位或 32 位宽(或更高),它取决于平台(编译器将在这两者间选择最合适的字宽);short 通常被定义成 16 位宽;long 通常被定义成 32 或 64位宽。 所以 C99 中引进了一个标准C库头文件 stdint.h ,方便精确确定整数类型的宽度 定义标准的扩展整数类型_stdint.h文件(部分) /* Signe
[单片机]
MSP432P401R的keil环境搭建
1、下载MSP432的pack包并导入keil中 2、打开工程文件 3、配置魔术棒
[单片机]
Keil(MDK-ARM)系列教程(四)_工程目标选项配置(Ⅱ)
Ⅱ、C/C++选项 这后面五项中,C/C++选项最为重要,因此部分功能需要重点强调。看选项标题“C/C++”,针对的主要就是C/C++,和后一个选项“Asm”有类似之处。 第1处:预处理(Preprocessor Symbols) 这里主要就是预定义功能,相当于在程序中的#define xxxx。我上面预定义STM32F10X_HD,在stm32f10x.h文件中就不用定义了。 第2处:语言代码生成(Language / Code Generation) Language/code Generation语言代码生成,可以理解成编译、链接到最后生成代码。这部分功能对于代码优化比较重要,初学者可以不用过多理解,对代码大小、运行
[单片机]
关于在 KEIL C51 中嵌入汇编以及C51与A51间的相互调用
如何在 KEIL C51(v6.21) 中调用汇编函数的一个示例 有关c51调用汇编的方法已经有很多帖子讲到,但是一般只讲要点,很少有对整个过程作详细描述,对于初学者是不够的,这里笔者 通过一个简单例子对这个过程进行描述,希望能对初学者有所帮助。几年来,在这个论坛里笔者得到很多热心人指导,因此也希望 藉此尽一点绵薄之力。 在这个例子里,阐述了编写c51程序调用汇编函数的一种方法,这个外部函数的入口参数是一个字符型变量和一个位变量,返回值是 一个整型变量。例中,先用c51写出这个函数的主体,然后用SRC控制指令编译产生asm文件,进一步修改这个asm文件就得到我们所 要的汇编函数。该方法让编译器自动完成各种段的安排,提高了汇编程序
[单片机]