AVR自带延时函数,_delay_ms() _delay_loop_2()

#include<avr/io.h>#include<stdint.h>#include<util/delay.h>voidDelayMs(uint16_tt){uint... #include <avr/io.h>
#include <stdint.h>
#include <util/delay.h>
void DelayMs(uint16_t t)
{
uint16_t i;
for(i=0;i<t;i++)
{
//_delay_ms(1000);
_delay_loop_2(1000);
}
}
int main(void)
{
DDRB|=_BV(PB0);
while(1)
{
PORTB&=~_BV(PB0);
DelayMs(300);
PORTB|=_BV(PB0);
DelayMs(300);
}
}
当程序使用_delay_ms(1000)作为延时主体,IO口输出一直为高,延时主体改为 _delay_loop_2(1000);可以工作,请问这是什么原因造成的呢!
展开
 我来答
ustbabcd
2012-08-15 · 超过39用户采纳过TA的回答
知道小有建树答主
回答量:90
采纳率:100%
帮助的人:67.5万
展开全部
要想使_delay_ms()正常工作需要正确定义常量F_CPU为所采用的时钟频率,以Hz为单位,若没有定义则系统默认定义为# define F_CPU 1000000UL,也就是1MHz,并在编译时出现警告 warning "F_CPU not defined for <util/delay.h>",所以如果你的时钟不是1MHz时要正确定义F_CPU,再有_delay_ms()延时以毫秒为单位,你的_delay_ms(1000)延时了整整1秒,因而用在你的函数DelayMs(300)里要延时300秒,你耐心等上5分钟它会变低的。其实_delay_ms()函数内部调用了_delay_loop_2(),这个函数内部执行空循环,每个循环要四个时钟周期,忽略开始时设置寄存器所需时间,在1MHz时钟频率时_delay_loop_2(1000)延时4ms,你的DelayMs(300)将延时大约1.2秒,所以很容易看到IO口高低变换,当然如果你的时钟频率不是1MHz,那么具体时间就要具体计算了。
追问
谢谢你,之前不知道,以为_delay_ms()延时也是4ms呢,所以就出现了上述状况,后来看了函数才知道,参数最大不能超过265,可是网上有的资料说什么旧版本的Winavr最大延时265ms,新版本的可以延时到大概6000ms,有这么一说么?我也找不到相关资料!
追答
是的,我装的是AVRstudio6.0,这个版本的_delay_ms()会判断是否超出延时极限(也就是_delay_loop_2(65535)),如果超出了就再定义一层循环,这样在1MHz时钟频率时最长可延时6.5535秒,也就是65535个0.1ms,_delay_ms(),是根据F_CPU进行过计算了的,只要正确定义F_CPU一般就能正确工作,而若要用_delay_loop_2()就要自己计算了。下面是AVR Studio 6.0 里_delay_ms()的定义:
void
_delay_ms(double __ms)
{
uint16_t __ticks;
double __tmp ;
#if __HAS_DELAY_CYCLES && defined(__OPTIMIZE__) && \
!defined(__DELAY_BACKWARD_COMPATIBLE__) && \
__STDC_HOSTED__
uint32_t __ticks_dc;
extern void __builtin_avr_delay_cycles(unsigned long);
__tmp = ((F_CPU) / 1e3) * __ms;
#if defined(__DELAY_ROUND_DOWN__)
__ticks_dc = (uint32_t)fabs(__tmp);
#elif defined(__DELAY_ROUND_CLOSEST__)
__ticks_dc = (uint32_t)(fabs(__tmp)+0.5);
#else
//round up by default
__ticks_dc = (uint32_t)(ceil(fabs(__tmp)));
#endif
__builtin_avr_delay_cycles(__ticks_dc);
#else
__tmp = ((F_CPU) / 4e3) * __ms;
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);
#endif
}
Sigma-Aldrich
2018-06-11 广告
Duolink PLA技术可通过同一个实验即可完成对蛋白质互作及其修饰的检测、定量以及确定细胞定位等。Duolink基于原位PLA技术(即邻位连接分析技术),可以帮助您在内源蛋白质表达过程中进行该分析。... 点击进入详情页
本回答由Sigma-Aldrich提供
百度网友94d2fe911
2012-08-19
知道答主
回答量:47
采纳率:0%
帮助的人:19万
展开全部
延时的时候 尽量不要在_delay_ms里面写1000 那样就不准了 一般200比较准 用for 多加几个试试吧
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
beatorwin
2012-08-15 · TA获得超过332个赞
知道小有建树答主
回答量:138
采纳率:0%
帮助的人:119万
展开全部
看看函数去- -,给函数呀原型- -
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
收起 更多回答(1)
推荐律师服务: 若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询

为你推荐:

下载百度知道APP,抢鲜体验
使用百度知道APP,立即抢鲜体验。你的手机镜头里或许有别人想知道的答案。
扫描二维码下载
×

类别

我们会通过消息、邮箱等方式尽快将举报结果通知您。

说明

0/200

提交
取消

辅 助

模 式