微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > AVR 中 delay 函数的调用注意事项!delay_ns delay_ms

AVR 中 delay 函数的调用注意事项!delay_ns delay_ms

时间:11-23 来源:互联网 点击:

重要提示:_delay_loop_1(0)、_delay_loop_1(256)延时是一样的!!
同理, _delay_loop_2(0)、_delay_loop_2(65536)延时也是一样的!!这些函数的延时都是最长的延时。

重量级函数出场>>>>>>>>>>>>>_delay_us() and _delay_ms() !!!

先说_delay_us(double __us),不要以为该函数的形参是double形就为所欲为,随便付值都不会溢出了,其实这个函数的调用是有限制的,不然就会出现延时不对的情况。函 数的注释里说明如下:

The maximal possible delay is 768 us / F_CPU in MHz.
在1MHz时最大延时768us!!!!

也就是说double __us这个值在1M系统时钟时最大只能是768。如果大于768,比如这样调用延时函数_delay_us(780)会怎么样呢??那就会和调用_delay_loop_1(0)一样的效 果了!能延迟多少各位可以算出来。具体在各种系统时钟之下这个值是多少可以通过一个公式算出来:

MAX_VALUE = 256*3000000/F_CPU

同理,分析程序,可以知道_delay_ms(double __ms)函数,在1MHz系统时钟下其最大延时是262.14 ms!在这里也给出该函数的形参的最大值,调用此函数时的实参都不要大于 这个值,大于这个限制值的话就和调用_delay_loop_2(0)同样的延时效果!

MAX_VALUE = 65536*4000/F_CPU (1MHZ时,能输入的最大值为262)

从上面可以看出来,当用延时函数时,若不加注意会出错的(毕竟人们很难经常记住这两个最大值),那还有什么补偿的办法呢?
#include

// _delay_loop_2(XXXX); // 16-bit count, 4 cycles/loop
// _delay_loop_1(XX); // 8-bit count, 3 cycles/loop

/*------------------------------------*/
void delay_1ms(void) //1ms延时函数 主频为8MHz
{
_delay_loop_2(2000); // 16-bit count,4 cycles/loop

} // 2000*4/FREQ

//使用不同的晶振,可以自己来计算出()里的值

/*-------------------------------------*/

void delay_nms(unsigned int n) //N ms延时函数
{
unsigned int i=0;
for (i=0;idelay_1ms();
}
/*------------------------------------ -*/

原文见:http://hi.baidu.com/xtuyvzkkkllstue/item/9654ea2f29450bc7ef10f1e2

个人的一些理解,欢迎拍砖:

(1)_delay_us(double __us)调用了子函数void _delay_loop_1(uint8_t _count),uint8_t限定了_us的取值范围不能超过255,而_us又决定了_delay_us()能延时多久的问题,具体能延时多久就根据时钟频率了,如上文所说(好像原文有误_delay_loop_1(uint8_t __count)这个地方搞成了_delay_loop_2(uint16_t __count),本篇已改正):

_delay_loop_1(uint8_t __count)
1MHz时: MAX_DELAY_TIME = (1/1000000)*3*256 = 0.000768 S = 768 uS
8MHz时: MAX_DELAY_TIME = (1/8000000)*3*256 = 0.000096 S = 96 uS
............
F_CPU MAX_DELAY_TIME = (1/F_CPU)*3*256

同理,_delay_ms(double _ms)也一样,调用了子函数void _delay_loop_2(uint16_t _count),uint16_t限定了_ms的取值范围不能超过65535,而_ms又决定了_delay_ms()能延时多久

_delay_loop_2(uint16_t __count)
1MHz时: MAX_DELAY_TIME = (1/1000000)*4*65535 = 0.26214 S = 262.1 mS
8MHz时: MAX_DELAY_TIME = (1/8000000)*4*65535 = 0.03277 S = 32.8 mS
............
F_CPU MAX_DELAY_TIME = (1/F_CPU)*4*65535

(2)AVR自带delay函数延时1us、1ms跟晶振频率没有关系,晶振频率只是决定了参数取值范围,在计数延时时候F_CPU这个值抵消掉了。

(3)上文中的解决办法是自己写了个延时1ms的函数,其实跟自带的是一样,自带的如下:

void _delay_ms(double __ms)
{
uint16_t __ticks;
double __tmp = ((F_CPU) / 4e3) * __ms;
if (__tmp < 1.0)
__ticks = 1;
else if (__tmp > 65535)
__ticks = 0;/* i.e. 65536 */
else
__ticks = (uint16_t)__tmp;
_delay_loop_2(__ticks);
}

绿色部分暂且不看,红色部分即是_ticks的值,如果晶振是8M带入(F_CPU) / 4e3既得2000,跟上文是一样。就是自带的函数里面不用考虑时钟频率,因为它最终被约分。所以这个1ms延时不必自己写了,我们只需要引用_delay_ms(1);让它延时1ms,然后再设循环延时nms,这样就摆脱了_delay_ms(double _ms)中_ms的范围限制。


Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top