stm32stm8 精确延时时 什么比较好用

STM32精确延时(非中断,非ST库函数)_计数器_中国百科网
STM32精确延时(非中断,非ST库函数)
    前天学了下stm的systick,发现还满好用的,可以用来精确定时.以前在用CVAVR的时候发现里面的delay.h非常好用.于是,利用stm32的SysTick做了个精确的延时头函数.SysTick的配置在void delay_init(u8 SYSCLK);里面输入的参数SYSCLK是你配置的系统时钟,比如72M,我就调用delay_init(72);然后就完成了对SysTick的初始化设置.在后面调用delay_ms(u32 Nms);delay_us(u32 Nus);就可以得到很准确的延时.注意:1,delay_us(u32 Nus);在Nus值很小的时候,误差比较大,我仿真的时候delay_us(1);实际上得到的是延时了1.5us左右.理论上Nus的值越大,越准确.2,delay_ms(u32 Nms);的参数不能太大!更具你系统时钟来确定.72M的时候Nms的最大值是1864.在其他晶振(CTRL&=0//选择内部时钟 HCLK/8fac_us=SYSCLK/8;fac_ms=(u16)fac_us*1000;}//延时Nms//注意Nms的范围//NmsLOAD=(u32)nms*fac_ //时间加载SysTick->CTRL|=0x01;//开始倒数while(!(SysTick->CTRL&(1CTRL&=0XFFFFFFFE;//关闭计数器SysTick->VAL=0X;//清空计数器}//延时usvoid delay_us(u32 Nus){SysTick->LOAD=Nus*fac_//时间加载SysTick->CTRL|=0x01;//开始倒数while(!(SysTick->CTRL&(1CTRL=0X;//关闭计数器SysTick->VAL=0X;//清空计数器}#endif
Copyright by ;All rights reserved.8838人阅读
嵌入式学习(80)
STM32/STM8(14)
STM32 使用通用计时器实现微秒延时
为了驱动ARF2496K这款芯片,做STM32上的移植,所以第一步需要解决的就是时序问题,很显然在STM32下类似于51的延时方法并不适用,自然想到了采用定时器进行定时来延时。目前使用的是查询方式进行延时。
环境: STM32F107主控,采用STLINK仿真
代码如下:
static void TIM5_Init_Query(CALC_TYPE type,uint32_t val)
TIM_TimeBaseInitTypeDef Tim5;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5,ENABLE);
Tim5.TIM_Period=1; //???
if(type==CALC_TYPE_S) //延时以S为单位时,时钟频率57600Hz,外部需要1250次计时
Tim5.TIM_Prescaler=57600-1; //预分频 72MHz / 5Hz
}else if(type==CALC_TYPE_MS)
Tim5.TIM_Prescaler=2880-1; //25000Hz ,定时器计数25次为ms
}else if(type==CALC_TYPE_US)
Tim5.TIM_Prescaler=72-1; //1MHz ,计数1次为us
Tim5.TIM_Prescaler=7200-1;
Tim5.TIM_ClockDivision=0;
Tim5.TIM_CounterMode=TIM_CounterMode_D //向下计数
TIM_TimeBaseInit(TIM5,&Tim5);
static void TIM5_S_CALC(uint32_t s)
&& &u16 counter=(s*1250)&0xFFFF; //前提定时器时钟为1250Hz
&& &TIM_Cmd(TIM5,ENABLE);
&& &TIM_SetCounter(TIM5,counter); //设置计数值
&& &while(counter&1)
&& &&& &counter=TIM_GetCounter(TIM5);
&& &TIM_Cmd(TIM5,DISABLE);
static void TIM5_MS_CALC(uint32_t ms)
&& &u16 counter=(ms*25)&0xFFFF;
&& &TIM_Cmd(TIM5,ENABLE);
&& &TIM_SetCounter(TIM5,counter); //设置计数值
&& &while(counter&1)
&& &&& &counter=TIM_GetCounter(TIM5);
&& &TIM_Cmd(TIM5,DISABLE);
static void TIM5_US_CALC(uint32_t us)
&& &u16 counter=us&0
&& &TIM_Cmd(TIM5,ENABLE);
&& &TIM_SetCounter(TIM5,counter); //设置计数值
&& &while(counter&1)
&& &&& &counter=TIM_GetCounter(TIM5);
&& &TIM_Cmd(TIM5,DISABLE);
int main()
SystemInit(); //库函数 初始化系统时钟源选择,PLL等
#ifdef _DEBUG
&& &Init_PD11();
TIM5_Init_Query(CALC_TYPE_US);
&&& while(1)
&& &&& &PD11_U; //产生方波
&& &&& &TIM5_US_CALC(1);&& //TIM5_MS_CALC(1); 毫秒延时, TIM5_S_CALC(1); 秒级别延时
&& &&& &PD11_D;
&& &&& &TIM5_US_CALC(1);
实验数据:
延时1微秒时,略有出入,下图:
(延时1us,并不精准,这与while循环中的语句有关)
延时20微秒时,比较准确,下图:
延时1毫秒时,下图:
(差了0.2ms,也就是才延时0.9ms,可以将分频系数降低,然后延时值加大些进行改善)
延时20毫秒时,下图:
延时1秒时,下图:
毫秒延时那里修改成下面代码,基本上能精准。
Tim5.TIM_Prescaler=720-1; //100KHz ,定时器计数100次为1ms
static void TIM5_MS_CALC(uint32_t ms)
&& &u16 counter=(ms*100)&0xFFFF; //前提定时器时钟为100KHz
&& &TIM_Cmd(TIM5,ENABLE);
&& &TIM_SetCounter(TIM5,counter); //设置计数值
&& &while(counter&1)
&& &&& &counter=TIM_GetCounter(TIM5);
&& &TIM_Cmd(TIM5,DISABLE);
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:331811次
积分:4052
积分:4052
排名:第5581名
原创:53篇
转载:138篇
评论:105条
(2)(1)(2)(3)(1)(1)(1)(1)(7)(3)(8)(3)(7)(1)(3)(1)(2)(8)(9)(32)(23)(15)(2)(3)(6)(11)(8)(1)(5)(12)(7)(2)Keil C51程序设计中几种精确延时方法
> Keil C51程序设计中几种精确延时方法
Keil C51程序设计中几种精确延时方法
实际的单片机应用系统开发过程中,由于程序功能的需要,经常编写各种程序,时间从数微秒到数秒不等,对于许多开发者特别是初学者编制非常的程序有一定难度。本文从实际应用出发,讨论几种实用的编制延时程序和计算程序执行时间的,并给出各种使用的详细步骤,以便读者能够很好地掌握理解。本文引用地址:关键词
延时 程序执行时间引言  单片机因具有体积小、功能强、成本低以及便于实现分布式控制而有非常广泛的应用领域[1]。单片机开发者在编制各种应用程序时经常会遇到实现精确延时的问题,比如按键去抖、数据传输等操作都要在程序中插入一段或几段延时,时间从几十微秒到几秒。有时还要求有很高的精度,如使用单总线芯片DS18B20时,允许误差范围在十几微秒以内[2],否则,芯片无法工作。用51汇编语言写程序时,这种问题很容易得到解决,而目前开发嵌入式系统软件的主流工具为C语言,用写延时程序时需要一些技巧[3]。因此,在多年单片机开发经验的基础上,介绍几种实用的编制精确延时程序和计算程序执行时间的。  实现延时通常有两种方法:一种是硬件延时,要用到定时器/计数器,这种方法可以提高CPU的工作效率,也能做到精确延时;另一种是软件延时,这种方法主要采用循环体进行。1 使用定时器/计数器实现精确延时  单片机系统一般常选用11.059 2 MHz、12 MHz或6 MHz晶振。第一种更容易产生各种标准的波特率,后两种的一个机器周期分别为1 &s和2 &s,便于精确延时。本程序中假设使用频率为12 MHz的晶振。最长的延时时间可达216=65 536 &s。若定时器工作在方式2,则可实现极短时间的精确延时;如使用其他定时方式,则要考虑重装定时初值的时间(重装定时器初值占用2个机器周期)。  在实际应用中,定时常采用中断方式,如进行适当的循环可实现几秒甚至更长时间的延时。使用定时器/计数器延时从程序的执行效率和稳定性两方面考虑都是最佳的方案。但应该注意,C51编写的中断服务程序编译后会自动加上PUSH ACC、PUSH PSW、POP PSW和POP ACC语句,执行时占用了4个机器周期;如程序中还有计数值加1语句,则又会占用1个机器周期。这些语句所消耗的时间在计算定时初值时要考虑进去,从初值中减去以达到最小误差的目的。2 软件延时与时间计算  在很多情况下,定时器/计数器经常被用作其他用途,这时候就只能用软件方法延时。下面介绍几种软件延时的方法。2.1 短暂延时  可以在C文件中通过使用带_NOP_( )语句的函数实现,定义一系列不同的延时函数,如Delay10us( )、Delay25us( )、Delay40us( )等存放在一个自定义的C文件中,需要时在主程序中直接调用。如延时10 &s的延时函数可编写如下:  void Delay10us( ) {    _NOP_( );    _NOP_( );    _NOP_( );    _NOP_( );    _NOP_( );    _NOP_( );  }  Delay10us( )函数中共用了6个_NOP_( )语句,每个语句执行时间为1 &s。主函数调用Delay10us( )时,先执行一个LCALL指令(2 &s),然后执行6个_NOP_( )语句(6 &s),最后执行了一个RET指令(2 &s),所以执行上述函数时共需要10 &s。  可以把这一函数当作基本延时函数,在其他函数中调用,即嵌套调用[4],以实现较长时间的延时;但需要注意,如在Delay40us( )中直接调用4次Delay10us( )函数,得到的延时时间将是42 &s,而不是40 &s。这是因为执行Delay40us( )时,先执行了一次LCALL指令(2 &s),然后开始执行第一个Delay10us( ),执行完最后一个Delay10us( )时,直接返回到主程序。依此类推,如果是两层嵌套调用,如在Delay80us( )中两次调用Delay40us( ),则也要先执行一次LCALL指令(2 &s),然后执行两次Delay40us( )函数(84 &s),所以,实际延时时间为86 &s。简言之,只有最内层的函数执行RET指令。该指令直接返回到上级函数或主函数。如在Delay80&s( )中直接调用8次Delay10us( ),此时的延时时间为82 &s。通过修改基本延时函数和适当的组合调用,上述方法可以实现不同时间的延时。2.2 在C51中嵌套汇编程序段实现延时  在C51中通过预处理指令#pragma asm和#pragma endasm可以嵌套汇编语言语句。用户编写的汇编语言紧跟在#pragma asm之后,在#pragma endasm之前结束。  如:#pragma asm    &    汇编语言程序段    &    #pragma endasm  延时函数可设置入口参数,可将参数定义为unsigned char、int或long型。根据参数与返回值的传递规则,这时参数和函数返回值位于R7、R7R6、R7R6R5中。在应用时应注意以下几点:  ◆ #pragma asm、#pragma endasm不允许嵌套使用;  ◆ 在程序的开头应加上预处理指令#pragma asm,在该指令之前只能有注释或其他预处理指令;  ◆ 当使用asm语句时,编译系统并不输出目标模块,而只输出汇编源文件;  ◆ asm只能用小写字母,如果把asm写成大写,编译系统就把它作为普通变量;  ◆ #pragma asm、#pragma endasm和 asm只能在函数内使用。  将汇编语言与C51结合起来,充分发挥各自的优势,无疑是单片机开发人员的最佳选择。2.3 使用示波器确定延时时间  熟悉硬件的开发人员,也可以利用示波器来测定延时程序执行时间。方法如下:编写一个实现延时的函数,在该函数的开始置某个I/O口线如P1.0为高电平,在函数的最后清P1.0为低电平。在主程序中循环调用该延时函数,通过示波器测量P1.0引脚上的高电平时间即可确定延时函数的执行时间。方法如下:  sbit T_point = P1^0;  void Dly1ms(void) {    unsigned int i,j;    while (1) {      T_point = 1;      for(i=0;i2;i++){        for(j=0;j124;j++){;}      }      T_point = 0;      for(i=0;i1;i++){        for(j=0;j124;j++){;}      }    }  }  void main (void) {    Dly1ms();  }
尘埃粒子计数器相关文章:
分享给小伙伴们:
我来说两句……
最新技术贴
微信公众号二
微信公众号一查看: 2208|回复: 8
如何用STM32延时到1微妙以下?
主题帖子精华
初级会员, 积分 52, 距离下一级还需 148 积分
在线时间0 小时
我现在一个工程需要我用STM32做一个只有0.39微妙和一个0.78微妙的延时,误差浮动不超过300纳秒。求教大神啊!
delay.c里面的变量 fac_us 改小
外部8MHz晶振,72MHz主时钟情况下 &fac_us =9;也就是计9个数为1us &把fac_us 改为1,最小延时就是1/9us了
void delay_us(u32 nus)
SysTick-&LOAD=nus*fac_ //时间加载
& & &--&SysTick-&LOAD=&//fac_us =1
SysTick-&VAL=0x00; & & & &//清空计数器
SysTick-&CTRL=0x01 ; & & ...
主题帖子精华
在线时间253 小时
delay.c里面的变量 fac_us 改小
外部8MHz晶振,72MHz主时钟情况下 &fac_us =9;也就是计9个数为1us &把fac_us 改为1,最小延时就是1/9us了
void delay_us(u32 nus)
SysTick-&LOAD=nus*fac_ //时间加载
& & &--&SysTick-&LOAD=&//fac_us =1
SysTick-&VAL=0x00; & & & &//清空计数器
SysTick-&CTRL=0x01 ; & & &//开始倒数
temp=SysTick-&CTRL;
while((temp&0x01)&&!(temp&(1&&16)));//等待时间到达 &&
SysTick-&CTRL=0x00; & & & //关闭计数器
SysTick-&VAL =0X00; & & & //清空计数器 &
需要注意一点,这个是理论值,实际是有误差的!至于 能否通过,你可以试用一下
主题帖子精华
初级会员, 积分 109, 距离下一级还需 91 积分
在线时间23 小时
回复【2楼】lycreturn:
---------------------------------
学习了,厉害!!
主题帖子精华
初级会员, 积分 52, 距离下一级还需 148 积分
在线时间0 小时
回复【2楼】lycreturn:
---------------------------------还有个问题,我这边没有示波器,我如何测试这个时间,手上有一个JTAG和一个最小系统。
主题帖子精华
在线时间253 小时
回复【4楼】sunmowen:
---------------------------------
&jtag可以仿真
主题帖子精华
新手上路, 积分 42, 距离下一级还需 8 积分
在线时间4 小时
在调用这个延时函数的时候,写寄存器会耗用一定的时间,这样1/9us延时就感觉很不准了
主题帖子精华
初级会员, 积分 52, 距离下一级还需 148 积分
在线时间0 小时
回复【5楼】lycreturn:
---------------------------------
这个JTAG怎么弄,有没有教程什么的。
主题帖子精华
初级会员, 积分 52, 距离下一级还需 148 积分
在线时间0 小时
回复【6楼】nkk:
---------------------------------
比如说用FOR这样的软件延时怎么样呢?
主题帖子精华
在线时间253 小时
回复【6楼】nkk:
---------------------------------
确实&&&us级延时,延时时间越小,准确性越低
回复【8楼】sunmowen:
---------------------------------
战舰&&mini开发板&资料里面都有介绍JTAG使用的,去置顶帖找
for延时也不怎么准的
Powered by

我要回帖

更多关于 stm32 精确延时 的文章

 

随机推荐