搜索
bottom↓
回复: 60

发个好用的精确延时函数给大家,适合STM32

[复制链接]

出0入0汤圆

发表于 2009-12-18 13:12:18 | 显示全部楼层 |阅读模式
static u8  fac_us=0;//us延时倍乘数
static u16 fac_ms=0;//ms延时倍乘数

void delay_init(u8 SYSCLK)
{
        SysTick->CTRL&=0xfffffffb;//选择内部时钟 HCLK/8
        fac_us=SYSCLK/8;                    
        fac_ms=(u16)fac_us*1000;
}                                                                    
//延时Nms
//注意Nms的范围
//Nms<=0xffffff*8/SYSCLK
//对72M条件下,Nms<=1864
void delay_ms(u16 nms)
{                                     
        u32 temp;       
                  
        SysTick->LOAD=(u32)nms*fac_ms;//时间加载
        SysTick->VAL =0x00;           //清空计数器
        SysTick->CTRL=0x01 ;          //开始倒数  
        do
        {
                temp=SysTick->CTRL;
        }
        while(temp&0x01&&!(temp&(1<<16)));//等待时间到达   
        SysTick->CTRL=0x00;       //关闭计数器
        SysTick->VAL =0X00;       //清空计数器                      
}
  
//延时us                                                                  
void delay_us(u32 Nus)
{               
        u32 temp;
                             
        SysTick->LOAD=Nus*fac_us; //时间加载                           
        SysTick->VAL=0x00;        //清空计数器
        SysTick->CTRL=0x01 ;      //开始倒数          
        do
        {
                temp=SysTick->CTRL;
        }
        while(temp&0x01&&!(temp&(1<<16)));//等待时间到达   
        SysTick->CTRL=0x00;       //关闭计数器
        SysTick->VAL =0X00;       //清空计数器            
}

阿莫论坛20周年了!感谢大家的支持与爱护!!

月入3000的是反美的。收入3万是亲美的。收入30万是移民美国的。收入300万是取得绿卡后回国,教唆那些3000来反美的!

出0入8汤圆

发表于 2009-12-18 13:58:52 | 显示全部楼层
最精确的定时是使用STM32中的输出比较模式,况且现在还有预装载寄存器,都自动了。

出0入0汤圆

发表于 2010-10-25 11:30:21 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-11-11 15:03:58 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-11-11 20:21:27 | 显示全部楼层
以后再看~

出0入0汤圆

发表于 2010-11-11 22:21:24 | 显示全部楼层
还买开始用stm32做东西呢,不过先mark了。

前几天用LPC2378,while延时太不可靠了,最后没办法只得动用定时器了。。。。

出0入0汤圆

发表于 2011-2-22 21:54:58 | 显示全部楼层
SYSCLK设定为多小呢???

出0入0汤圆

发表于 2011-4-11 02:26:46 | 显示全部楼层
回复【6楼】jclwd8263  一片机
-----------------------------------------------------------------------
应该是72.

出0入0汤圆

发表于 2011-4-11 02:38:28 | 显示全部楼层
留爪

出0入0汤圆

发表于 2011-4-11 08:49:31 | 显示全部楼层
一般的,精确延时应该使用定时器来做,while循环会被打断,不准确的。

出0入0汤圆

发表于 2011-4-16 16:31:48 | 显示全部楼层
LZ用的系统定时器

出0入0汤圆

发表于 2011-4-16 17:18:04 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-4-17 09:34:00 | 显示全部楼层
回复【楼主位】jiangjx  
-----------------------------------------------------------------------

为什么不用外设驱动库写啊?不是更直观好看吗?

出0入0汤圆

发表于 2011-4-17 09:45:18 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-4-18 16:23:22 | 显示全部楼层
mark 延时

出0入0汤圆

发表于 2011-5-24 14:05:48 | 显示全部楼层
回复【12楼】wuguoyan 吴国炎
回复【楼主位】jiangjx   
-----------------------------------------------------------------------
为什么不用外设驱动库写啊?不是更直观好看吗?
-----------------------------------------------------------------------

usb的库里有个使用库写的us级的延时在hw_config.c文件

出0入0汤圆

发表于 2011-5-24 19:09:26 | 显示全部楼层
路过,做个标记!

出0入0汤圆

发表于 2011-6-22 11:06:52 | 显示全部楼层
mark,刚开始接触m3

出0入0汤圆

发表于 2011-6-22 11:29:28 | 显示全部楼层
建议用ST 提供的延时函数。

出0入0汤圆

发表于 2011-6-22 16:00:01 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-7-7 20:24:31 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-7-10 08:41:37 | 显示全部楼层
楼主为虾米我不能用啊,延时1s 是delay_ms(1000)对吗?

出0入0汤圆

发表于 2011-7-10 08:52:47 | 显示全部楼层
想要精准还是定时器比较可靠

出0入0汤圆

发表于 2011-7-10 09:07:17 | 显示全部楼层
void  DelayuS(u32  delayuS)
{
    u32  i;

    while(delayuS--)
    {
        for(i=0; i<4; i++)
        {
             __no_operation();
         }
     }
}

这函数最简单5uS以上,如果没有中断打断的话,时间比较精确

出0入0汤圆

发表于 2011-7-11 10:24:36 | 显示全部楼层
__no_operation();
在哪个文件里面?
请楼上“jishanlaike 阿弱”指明路径。谢谢!

出0入0汤圆

发表于 2011-7-11 11:18:45 | 显示全部楼层
MARK。。。

出0入0汤圆

发表于 2011-7-13 11:16:31 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-7-22 11:29:41 | 显示全部楼层
回复【24楼】wanglei2005007
__no_operation();  
在哪个文件里面?
请楼上“jishanlaike 阿弱”指明路径。谢谢!
-----------------------------------------------------------------------

在intrinsics.h里面

出0入0汤圆

发表于 2011-8-9 21:18:41 | 显示全部楼层
mark!

出0入0汤圆

发表于 2011-8-10 08:40:34 | 显示全部楼层
mark,

出0入0汤圆

发表于 2011-8-10 18:19:41 | 显示全部楼层
刚学STM32,我的编写函数思想是:
delay.c
////////////////////////////////////////////////////////////////////////////
void  wait(unsigned long n)
{
   do{
   n--;
   }while(n);
}
它的延时时间为 A*n+B (单位是时钟周期)。只要仿真n=1和n=2的延时时间,就可以算出A和B的值。
这里假设A=1,B=3(由于时间关系,我还没有仿真)。



delay.h
////////////////////////////////////////////////////////////////////////////
#define  SYSCLK   72.0               //指明CPU工作频率为72MHz
#define  A             1.0           //一次循环所花的周期数
#define  B             3.0           //调用、初始化、返回总共所用的周期数
#define  delay_us(nus)   wait(((nus)*(CPUCLK)-(B))/(A))
#define  delay_ms(nms)   delay_us((nms)*1000)
#define  delay_s(ns)     delay_ms((ns)*1000)

这样,就实现了软件延时,延时精度至少达到0.02us,延时范围至少0.1us至59s,完整编绎
后,仅生成12字节的程序代码,无论从代码还是从精度上都是十分优秀的。使用方法:
delay_us(0.4);   //延时0.4us
delay_ms(1456);  //延时1.456s
delay_s(21.4345);//延时21.4345秒

出0入0汤圆

发表于 2011-8-11 09:25:19 | 显示全部楼层
路过。。。。。
但使用的时候,若在主函数中进入延时程序后,若被中断打断,而且在中断函数中有使用到了延时函数,那么中断返回后程序将被停止-----一直在检测计数值到达(但此时中断函数中的延时函数退出时已经把systick计数功能给关闭了)
使用的时候得注意了啊。。。。

出0入0汤圆

发表于 2011-9-27 19:41:18 | 显示全部楼层
MARK

出0入0汤圆

发表于 2011-9-27 20:41:54 | 显示全部楼层
回复【楼主位】jiangjx
-----------------------------------------------------------------------

额·····这不是正点大哥的模板吗??我也这发愁这个呢,我在主函数里设置 delay_init(72);进入延时就出不来了,应该就是定时没工作,经过仿真
           do
        {
                temp=SysTick->CTRL;
        }
        while(temp&0x01&&!(temp&(1<<16)));//等待时间到达


这里一直过不去,不是不我哪里做的不对,求赐教·········

出0入0汤圆

发表于 2011-9-27 21:50:48 | 显示全部楼层
回复【楼主位】jiangjx
-----------------------------------------------------------------------

学习中,谢谢,加油。

出0入0汤圆

发表于 2011-9-27 22:46:03 | 显示全部楼层
那么多定时器不用岂不是浪费,个人感觉。

出0入0汤圆

发表于 2011-9-29 16:45:15 | 显示全部楼层
回复【楼主位】jiangjx
-----------------------------------------------------------------------

LZ一定要回我哦·····
JLINK仿真的时候,是不是延时不能仿真呀····

我的进程一道延时那里就卡住了,必须手动的跳过才可以继续执行·······


我试了MIni开发板,也是这个问题·····

出0入0汤圆

发表于 2012-7-21 20:20:52 | 显示全部楼层
   mark   

出100入18汤圆

发表于 2012-9-6 12:39:53 | 显示全部楼层
qiu452555846 发表于 2011-8-10 18:19
刚学STM32,我的编写函数思想是:
delay.c
//////////////////////////////////////////////////////////// ...

下边这段延时程序写得真不错!

出0入0汤圆

发表于 2012-9-6 15:18:28 | 显示全部楼层
定时器来的精准

出0入0汤圆

发表于 2012-9-6 15:24:07 | 显示全部楼层
学习中,谢谢

出0入0汤圆

发表于 2012-11-5 17:31:16 | 显示全部楼层
楼主好人

出0入0汤圆

发表于 2012-11-8 23:40:10 | 显示全部楼层
谢谢楼主,Mark

出0入0汤圆

发表于 2012-11-16 02:52:27 | 显示全部楼层
mark。。。。。。。

出0入0汤圆

发表于 2012-12-28 08:45:07 | 显示全部楼层
mark  一下

出0入0汤圆

发表于 2012-12-28 16:33:55 | 显示全部楼层
这个是正点原子开发板中的例程吧

出0入0汤圆

发表于 2013-9-18 15:12:38 | 显示全部楼层
mark!!!!!!

出0入0汤圆

发表于 2013-9-18 15:52:36 | 显示全部楼层
mark      

出0入0汤圆

发表于 2013-9-18 18:41:03 来自手机 | 显示全部楼层
移植一个UCOS系统,自带的延时函数还可以

出0入0汤圆

发表于 2014-3-26 18:26:54 | 显示全部楼层
qiu452555846 发表于 2011-8-10 18:19
刚学STM32,我的编写函数思想是:
delay.c
//////////////////////////////////////////////////////////// ...

牛到不能直视!!!!!

出0入0汤圆

发表于 2017-4-21 11:16:52 | 显示全部楼层
qiu452555846 发表于 2011-8-10 18:19
刚学STM32,我的编写函数思想是:
delay.c
//////////////////////////////////////////////////////////// ...

很牛啊,认真严谨!

出0入0汤圆

发表于 2017-4-21 17:31:21 | 显示全部楼层
收藏

出0入0汤圆

发表于 2017-4-21 18:50:18 | 显示全部楼层
mark       !

出0入4汤圆

发表于 2017-4-21 21:48:45 | 显示全部楼层
本帖最后由 ilan2003 于 2017-4-21 21:49 编辑

M3中使用DWT进行精确延时    转自网络,未经过测试
#define  DWT_CR      *(volatile u32 *)0xE0001000

#define  DWT_CYCCNT  *(volatile u32 *)0xE0001004

#define  DEM_CR      *(volatile u32 *)0xE000EDFC

#define  DEM_CR_TRCENA                   (1 << 24)

#define  DWT_CR_CYCCNTENA                (1 <<  0)




#define Delayms(msec)         Delayus(msec*1000)  //对于延时毫秒级的只需要定义一个宏

static u32 cpuclkfeq;     //用于保存cpu运行频率,可运行时动态修改



//初始化延时系统,参数为CPU频率

void DelayInit(u32 clk)
{

    cpuclkfeq = clk;
//打开CYCCNT功能,并把计数器清零,最后打开计数器对cpu时钟进行向上计数

    DEM_CR         |=  DEM_CR_TRCENA;

//    DWT_CYCCNT      = 0u;    //根据需要如果调试,或其他程序要使用CYCCNT时注释掉,否则可直接清零

    DWT_CR         |= DWT_CR_CYCCNTENA;

}



//延时函数,参数为需要延时的微秒数
void Delayus(u32 usec)

{

     u32 startts,endts,ts;

  //保存进入函数时的计数器值

     startts = DWT_CYCCNT;

     ts =  usec * (cpuclkfeq /(1000*1000) );        //计算达到所需延时值的cpu时钟数,^-^如果想要更精确此处可以减去运行前面代码所需的时钟数。

     endts = startts + ts;           //计算达到所需延时时间的DWT_CYCCNT计数值,超过32bit所能表达的最大值2的32次方-1是自动绕回丢弃进位

      if(endts > startts)            //判断是否跨越最大值边界

      {

          while(DWT_CYCCNT < endts);        //等到计数到所需延时值的cpu时钟数值

       }

       else

      {

           while(DWT_CYCCNT > endts);       //等待跨域32bit的最大值,2的32次方-1

           while(DWT_CYCCNT < endts);        //等到计数到所需延时值的cpu时钟数值

      }



}

出0入0汤圆

发表于 2017-4-21 21:53:22 | 显示全部楼层
这不是原子的例程吗

出40入42汤圆

发表于 2017-4-21 22:10:10 | 显示全部楼层
ilan2003 发表于 2017-4-21 21:48
M3中使用DWT进行精确延时    转自网络,未经过测试
#define  DWT_CR      *(volatile u32 *)0xE0001000

之前我发过这种延时方法的帖子,使用SysTick和do{...}while()的,都有对应的缺陷,DWT模块比较实用。

http://www.amobbs.com/thread-5665490-1-1.html

出0入0汤圆

发表于 2017-4-22 00:42:13 | 显示全部楼层
定时器比较靠谱。

出0入0汤圆

发表于 2017-5-8 22:33:39 | 显示全部楼层
路过,做个标记!
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-26 16:10

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表