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

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

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

早就知道AVR的编译器有自带的延时子函数(或者说是头文件),但一直没时间一探究竟,今天终于揭开了其内幕。

AVR编译器众多,可谓是百家齐鸣,本人独尊WinAVR.
说明:编译器版本WinAVR-20080610
先说winAVR的_Delay.h_肯定是在Include文件夹下了,进去一看果然有,可打开一看,其曰:“This file has been moved to delay.h>."
在util文件夹中找到delay头文件如下:
--------------------------------------------------------------------------------------------------------------------------------------------
void
_delay_us(double __us)
{
uint8_t __ticks;
double __tmp = ((F_CPU) / 3e6) * __us; //3e6=3000000
if (__tmp < 1.0)
__ticks = 1;
else if (__tmp > 255)
{
_delay_ms(__us / 1000.0);
return;
}
else
__ticks = (uint8_t)__tmp;
_delay_loop_1(__ticks);
}

-----------------------------------------------------------------------------------------------------------------------------------------------
_delay_ms(double __ms)
{
uint16_t __ticks;
double __tmp = ((F_CPU) / 4e3) * __ms;
if (__tmp < 1.0)
__ticks = 1;
else if (__tmp > 65535)
{
// __ticks = requested delay in 1/10 ms
__ticks = (uint16_t) (__ms * 10.0);
while(__ticks)
{
// wait 1/10 ms
_delay_loop_2(((F_CPU) / 4e3) / 10);
__ticks --;
}
return;
}
else
__ticks = (uint16_t)__tmp;
_delay_loop_2(__ticks);
}
1、分析程序发现上面两个子函数,分别using _delay_loop_1() and using_delay_loop2()
2、还有一点,用此头文件时,必须设置主频和优化项,否则会出现如下提示:
#ifndef F_CPU
/* prevent compiler error by supplying a default */
# warning "F_CPU not defined for "
# define F_CPU 1000000UL
#endif

#ifndef __OPTIMIZE__
# warning "Compiler optimizations disabled; functions from wont work as designed"
#endif
3、通过查找发现_Delay_loop1()和_Delay_loop2()在文件delay_basic.h中,如下:
/** ingroup util_delay_basic

Delay loop using an 8-bit counter c __count, so up to 256 iterations are possible. (The value 256 would have to be passedas 0.) The loop executes three CPU cycles per iteration, not including the overhead the compiler needs to setup the counter register.

Thus, at a CPU speed of 1 MHz, delays of up to 768 microseconds can be achieved.
*/
上面翻译如下:
循环变量为8位,所以可达256(其值256和0等同),每次循环好执行3个CPU时钟,不包括程序调用和退出该函数所花费的时间。
如此,当CPU为1MHZ时,最大延时为768us。( 3us*256)
void _delay_loop_1(uint8_t __count)
{
__asm__ volatile (
"1: dec %0" ""
"brne 1b" a a
: "=r" (__count)
: "0" (__count)
);
}

/** ingroup util_delay_basic

Delay loop using a 16-bit counter c __count, so up to 65536 iterations are possible. (The value 65536 would have to be passed as 0.) The loop executes four CPU cycles per iteration, not including the overhead the compiler requires to setup the counter register pair.

Thus, at a CPU speed of 1 MHz, delays of up to about 262.1 milliseconds can be achieved.
*/
上面翻译如下:
循环变量为16位,所以可达65536(其值65536和0等同),每次循环好执行4个CPU时钟,不包括程序调用和退出该函数所花费的时间。
如此,当CPU为1MHZ时,最大延时大约为262.1us。( 4us*65536)
void_delay_loop_2(uint16_t __count)
{
__asm__ volatile (
"1: sbiw %0,1" ""
"brne 1b"
: "=w" (__count)
: "0" (__count)
);
}
4、有了上面的基础就不难得出
#include // 头文件

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

#include // 头文件

_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_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
依此类推。

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

网站地图

Top