刚对WinAVR自带的延时函数进行一下研究,有些收获,与大家分享,不对之处请斧正,谢谢。
先看_delay_loop_1(uint8_t __count)函数,从其函数注释里面可以了解到,该函数用来延迟3个晶振时钟周 期,不包括程序调用和退出该函数所花费的时间。该函数的形参__count是一个8位的变量,由此,我们就可以根据系统采用的晶振频率算出该函数最大的延 迟时间了:
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)函数,该函数延时4个晶振周期,形参是一个16位的变量,同样 我们也可以算出该函数最大的延迟时间:
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
依此类推。
重要提示:_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
总结完毕!不正确之处还望各位不吝指正!谢谢
关键字:WinAVR 延时函数
引用地址:
如何用好WinAVR里的延时函数
推荐阅读最新更新时间:2024-03-16 14:39
51单片机精确延时函数集锦
C语言延时程序: 50us延时子程序(12MHZ) void delay_50us(uint16 t) { uint8 j; for(;t 0;t--) for(j=19;j 0;j--); } 10ms延时子程序(12MHZ) void delay10ms(void) { unsigned char i,j,k; for(i=5;i 0;i--) for(j=4;j 0;j--) for(k=248;k 0;k--); } 1s延时子程序(12MHZ) void delay1s(void) { unsigned char h,
[单片机]
STC12延时函数的探究
这种写法是C中嵌套了汇编。精确延时时间=2*t*T+5*T,T为一个机器周期。对于8051, 如果t=1,那么这个函数执行应该是7us。如果是STC12,那么这个延时函数的延时应该是:若t=1,精确延时=2*1*1/12+5*1/12=(7/12)us啊。 昨天也查了STC12手册 手册上对时钟写的很笼统,其中一句话是:与8051指令执行时间对比,一共有12个指令,一个时钟就可以执行完成,工作在相同频率下运行速度提高8~12倍 难道这里应该是(7/8)us?而不是(7/12)us? 这个是uint型函数时间是近似的 那么可以用延时时间=8*t*T 应该是8*1*(1/12)=8/12 根据程序分析猜想t=1时这个延时函数应
[单片机]
STM32F103(库函数)——点亮LED并且使用软件延时实现led闪烁
当我们学过51单片机之后就知道在51单片机中点亮一个LED很简单一句代码就可以实现。只需要将LED所连接的IO口拉低就可以点亮LED。 但是在STM32中,点亮LED确实比51要麻烦很多。 一样,在STM32中点亮LED也是属于基本的IO口的使用,所以每当我们需要点亮LED时就需要正确配置IO口。STM32的IO口相比51单片机而言要复杂很多,所以用起来也很困难。 下面就是点亮LED的代码,并且使用延时实现LED闪烁。 main.c #include stm32f10x.h #include led.h #include delay.h #include sys.h int main(void) {
[单片机]
PIC单片机的延时函数
PIC单片机C语言中的延时函数(即延时一定值),有多种等效的编写,这里介绍一种最简延时函数。 函数中的K为给定的整形。
[单片机]
STM32延时函数的三种方法——最好掌握第三种
单片机编程过程中经常用到延时函数,最常用的莫过于微秒级延时 delay_us( ) 和毫秒级 delay_ms( ) 。 1. 普通延时法 这个比较简单,让单片机做一些无关紧要的工作来打发时间,经常用循环来实现,不过要做的比较精准还是要下一番功夫。下面的代码是在网上搜到的,经测试延时比较精准。 // 粗延时函数,微秒 void delay_us(u16 time) { u16 i=0; while(time--) { i=10; // 自己定义 while(i--) ; } } // 毫秒级的延时 void delay_ms(u16 time) { u16 i=0; whil
[单片机]
STM32的Systick滴答定时器及延时函数编写
一、Systick滴答定时器是什么? Systick定时器就是系统滴答定时器,一个24 位的倒计数定时器,计到0 时,将从RELOAD 寄存器中自动重装载定时初值。只要不把它在SysTick 控制及状态寄存器中的使能位清除,就永不停息,即使在睡眠模式下也能工作。 定时器既是在规定时间之后执行某个操作。 Systick定时器常用来做延时,或者实时系统的心跳时钟。这样可以节省MCU资源,不用浪费一个定时器。比如UCOS中,分时复用,需要一个最小的时间戳,一般在STM32+UCOS系统中,都采用Systick做UCOS心跳时钟。 --------------------------------------------
[单片机]
IAR调试stm8单片机时延时函数被优化的问题
IAR优化等级选到最高,调用以下延时函数时会被编译器直接优化,无法达到延时的效果。 void delay_n_ms(u32 time) { u32 m = 0; u16 n = 0; for(;m time;m++) { for(n = 0;n 2720;n++)//16Mhz { ; } } } 在函数的变量前加volatile关键字后问题解决。 void delay_n_ms(u32 time) { volatile u32 m = 0; volatile u16 n = 0; for(;m time;m++) { for
[单片机]
STM32定时器写精准的延时函数
1.关于定时器的配置这里可以参考正点原子教程中的例子 2 .这里重装载值与预分频设置为999与7199 3.中断服务程序与精准延时函数为 4.接下来就可以使用精准延时函数
[单片机]