OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 37139|回复: 71

不占用定时器(包括SysTick)实现精确延时又一方法

  [复制链接]

5

主题

14

帖子

2

精华

中级会员

Rank: 3Rank: 3

积分
370
金钱
370
注册时间
2012-9-7
在线时间
3 小时
发表于 2013-9-26 23:37:42 | 显示全部楼层 |阅读模式

研究了一下CM3手册,其中有这么一部分:



 


 

也就是说调试组件带有一个对CPU时钟进行计数的功能,可以利用它进行延时。代码如下:

#define  DWT_CR      *(volatile u32 *)0xE0001000
#define  DWT_CYCCNT  *(volatile u32 *)0xE0001004
#define  DEM_CR      *(volatile u32 *)0xE000EDFC
#define  DBGMCU_CR   *(volatile u32 *)0xE0042004
#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功能
    DEM_CR         |=  DEM_CR_TRCENA; 

}


 

 //延时函数,参数为需要延时的微秒数

void Delayus(u32 usec)
{
     u32 ts;
    //先关闭cpu时钟计数器,并把计数器清零,最后打开计数器对cpu时钟进行向上计数

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

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


 


在应用时先调用 DelayInit初始化,然后就可以调用Delayus,Delayms进行延时了。

实际应用中效果很好,很精确并且不占用其他资源在跑OS尤其适用。

 



二.改进版,避免将DWT_CYCCNT的值清零,而可能影响调试或其他依赖于此计数器的程序


 

#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时钟数值

      }

}



 

正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

20

主题

100

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
297
金钱
297
注册时间
2012-12-22
在线时间
24 小时
发表于 2016-1-14 02:44:51 | 显示全部楼层
本帖最后由 whjambo 于 2016-1-14 02:48 编辑

函数还可以简洁一点
//延时函数,参数为需要延时的微秒数
void delay_us(u32 us)
{
        u32 temp;
        temp= DWT_CYCCNT;
        us *=  SystemCoreClock/1000000;             //SystemCoreClock官方库自带
        while((u32)( DWT_CYCCNT - temp)< us); //溢出也没关系
}

void delay_ms(u32 ms)
{
        u32 temp;
        temp= DWT_CYCCNT;
        ms *=  SystemCoreClock/1000;                  //SystemCoreClock官方库自带
        while((u32)( DWT_CYCCNT - temp)< ms); //溢出也没关系
}
是不是简洁多了,呵呵
回复 支持 4 反对 0

使用道具 举报

0

主题

416

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1002
金钱
1002
注册时间
2016-11-25
在线时间
181 小时
发表于 2017-1-10 08:21:53 | 显示全部楼层
cool,学习了
回复 支持 1 反对 0

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165371
金钱
165371
注册时间
2010-12-1
在线时间
2110 小时
发表于 2013-9-26 23:59:14 | 显示全部楼层
楼主对CM3研究很深啊,这里我是完全没有看到啊...
还有这功能,不错,呵呵。很巧妙。

顺便问下,如果JTAG TRACE跟踪的时候呢?会不会影响到这个延时?我记得jtag trace是可以看系统跑了多久的,不知道会不会也要用到这部分资源...

不过不管怎么说,楼主的研究精神值得学习,酷贴一个啊。
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

51

主题

1455

帖子

3

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
2612
金钱
2612
注册时间
2011-1-25
在线时间
176 小时
发表于 2013-9-27 08:32:06 | 显示全部楼层
很好的延时方法啊,
LZ研究精神可嘉!
一直努力就很好。
回复 支持 反对

使用道具 举报

5

主题

14

帖子

2

精华

中级会员

Rank: 3Rank: 3

积分
370
金钱
370
注册时间
2012-9-7
在线时间
3 小时
 楼主| 发表于 2013-9-27 09:12:38 | 显示全部楼层
回复【3楼】qq942266575:
---------------------------
谢谢夸奖,平时喜欢用不同的方法捣鼓东西,其中遇到过很多问题,以后会向各位请教,希望你们不吝赐教啊!
回复 支持 反对

使用道具 举报

10

主题

44

帖子

0

精华

初级会员

Rank: 2

积分
104
金钱
104
注册时间
2012-8-13
在线时间
0 小时
发表于 2013-9-27 09:31:48 | 显示全部楼层
狂赞啊,糕级攻城狮的特质啊!!!
奋斗的小鸟,不是愤怒的小鸟
回复 支持 反对

使用道具 举报

1

主题

73

帖子

0

精华

初级会员

Rank: 2

积分
102
金钱
102
注册时间
2013-9-8
在线时间
2 小时
发表于 2013-9-27 10:52:00 | 显示全部楼层
哇 ,楼主很赞啊  昨天我还在找你之前的那一贴  汇编精确延时,今天又出好方法了    GO.OD
回复 支持 反对

使用道具 举报

1

主题

73

帖子

0

精华

初级会员

Rank: 2

积分
102
金钱
102
注册时间
2013-9-8
在线时间
2 小时
发表于 2013-9-27 10:55:28 | 显示全部楼层
只是不知道 ,在使用硬件仿真时,改函数会不会对 仿真造成影响?
回复 支持 反对

使用道具 举报

5

主题

14

帖子

2

精华

中级会员

Rank: 3Rank: 3

积分
370
金钱
370
注册时间
2012-9-7
在线时间
3 小时
 楼主| 发表于 2013-9-27 11:10:37 | 显示全部楼层
回复【7楼】谷子木:
---------------------------------
要不影响调试可以在初始化函数打开CYCCNT计数器,而Delayus函数里不关CYCCNT计数器,不将CYCCNT 的值清零,而只是读取,然后判断计数值,但当计满最大值后又将返回零,这就需要在代码里做一下判断了。
回复 支持 反对

使用道具 举报

5

主题

17

帖子

0

精华

初级会员

Rank: 2

积分
90
金钱
90
注册时间
2012-11-24
在线时间
7 小时
发表于 2013-9-27 11:20:02 | 显示全部楼层
cool,学习了
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165371
金钱
165371
注册时间
2010-12-1
在线时间
2110 小时
发表于 2013-9-27 11:27:23 | 显示全部楼层
回复【8楼】cqzww:
---------------------------------
最好改成这样。
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

1

主题

22

帖子

1

精华

初级会员

Rank: 2

积分
196
金钱
196
注册时间
2012-3-29
在线时间
0 小时
发表于 2013-10-7 22:09:40 | 显示全部楼层
非常好的方法,佩服楼主啊,学习的很深入。
回复 支持 反对

使用道具 举报

38

主题

527

帖子

1

精华

金牌会员

Rank: 6Rank: 6

积分
1424
金钱
1424
注册时间
2011-11-27
在线时间
122 小时
发表于 2013-10-7 22:28:25 | 显示全部楼层
cooL
回复 支持 反对

使用道具 举报

4

主题

55

帖子

0

精华

初级会员

Rank: 2

积分
91
金钱
91
注册时间
2013-4-9
在线时间
0 小时
发表于 2013-10-8 10:10:09 | 显示全部楼层
#define  DEM_CR      *(volatile u32 *)0xE000EDFC   这个寄存器我怎么找不到  楼主能告诉下么
回复 支持 反对

使用道具 举报

68

主题

212

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
311
金钱
311
注册时间
2013-5-7
在线时间
28 小时
发表于 2013-10-8 14:38:32 | 显示全部楼层
没看懂
回复 支持 反对

使用道具 举报

4

主题

84

帖子

0

精华

初级会员

Rank: 2

积分
155
金钱
155
注册时间
2013-10-17
在线时间
9 小时
发表于 2014-4-23 11:51:02 | 显示全部楼层
又学习到了另一种延时方法
回复 支持 反对

使用道具 举报

93

主题

746

帖子

1

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
1849
金钱
1849
注册时间
2012-9-16
在线时间
286 小时
发表于 2014-6-5 16:11:48 | 显示全部楼层
很好,学习了!
纵浪大化中,不喜亦不惧;应尽便须尽,无复独多虑!
回复 支持 反对

使用道具 举报

10

主题

274

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
336
金钱
336
注册时间
2013-12-3
在线时间
0 小时
发表于 2014-6-5 16:30:21 | 显示全部楼层
牛逼。值得学习!
不用谢了……
回复 支持 反对

使用道具 举报

7

主题

333

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1838
金钱
1838
注册时间
2012-7-16
在线时间
504 小时
发表于 2014-8-5 14:48:33 | 显示全部楼层
超级赞!不然SysTick在ucos下就太麻烦了。
回复 支持 反对

使用道具 举报

0

主题

5

帖子

0

精华

新手上路

积分
25
金钱
25
注册时间
2014-9-7
在线时间
0 小时
发表于 2014-9-7 11:41:07 | 显示全部楼层
真是个好东西啊,找了好久终于找到这么个专业的论坛和一群对技术这么执着的人,谢谢楼主的分享
回复 支持 反对

使用道具 举报

6

主题

25

帖子

0

精华

初级会员

Rank: 2

积分
74
金钱
74
注册时间
2014-4-26
在线时间
1 小时
发表于 2014-10-23 17:59:02 | 显示全部楼层
楼主这个手册是怎么来的
回复 支持 反对

使用道具 举报

26

主题

194

帖子

5

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
1175
金钱
1175
注册时间
2011-8-20
在线时间
21 小时
发表于 2014-10-23 18:51:40 | 显示全部楼层
赞一个
回复 支持 反对

使用道具 举报

72

主题

2711

帖子

2

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
3505
金钱
3505
注册时间
2014-8-4
在线时间
696 小时
发表于 2014-11-1 20:38:28 | 显示全部楼层
mark...
回复 支持 反对

使用道具 举报

32

主题

99

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
348
金钱
348
注册时间
2014-10-9
在线时间
46 小时
发表于 2014-12-12 14:23:35 | 显示全部楼层
MARK!!!
回复 支持 反对

使用道具 举报

2

主题

9

帖子

0

精华

新手上路

积分
49
金钱
49
注册时间
2013-6-1
在线时间
3 小时
发表于 2015-1-3 19:26:05 | 显示全部楼层
回复【4楼】cqzww:
---------------------------------
敢问楼主,在系统下,系统滴答定时器的中断优先级是很高的,如果在延时2us时这是遇到系统滴答定时器中断,系统滴答定时器中断处理时间2us,那么如何保证准确的延时?
回复 支持 反对

使用道具 举报

头像被屏蔽

6168

主题

7036

帖子

1

精华

论坛元老

Rank: 8Rank: 8

积分
19705
金钱
19705
注册时间
2012-12-27
在线时间
25 小时
发表于 2015-1-4 09:30:25 | 显示全部楼层
创新很难  楼主做到了
回复 支持 反对

使用道具 举报

0

主题

5

帖子

0

精华

新手上路

积分
25
金钱
25
注册时间
2015-1-4
在线时间
0 小时
发表于 2015-1-4 10:26:18 | 显示全部楼层
强大!学习了!
回复 支持 反对

使用道具 举报

头像被屏蔽

65

主题

277

帖子

0

精华

高级会员

Rank: 4

积分
674
金钱
674
注册时间
2013-8-11
在线时间
29 小时
发表于 2015-1-4 10:40:38 | 显示全部楼层
mark,谢谢楼主!!!!!
回复 支持 反对

使用道具 举报

4

主题

125

帖子

1

精华

高级会员

Rank: 4

积分
870
金钱
870
注册时间
2014-8-7
在线时间
49 小时
发表于 2015-1-4 11:45:00 | 显示全部楼层
cool,,
回复 支持 反对

使用道具 举报

7

主题

38

帖子

0

精华

初级会员

Rank: 2

积分
86
金钱
86
注册时间
2014-3-11
在线时间
0 小时
发表于 2015-1-5 19:16:27 | 显示全部楼层
大家试用了这个程序吗?
我这里编译通过后,延时程序会进入死循环。
回复 支持 反对

使用道具 举报

7

主题

38

帖子

0

精华

初级会员

Rank: 2

积分
86
金钱
86
注册时间
2014-3-11
在线时间
0 小时
发表于 2015-1-5 19:45:05 | 显示全部楼层
回复【29楼】yhnu1214:
---------------------------------
系统时钟写72000000,可以成功。
DelayInit(72000000);
回复 支持 反对

使用道具 举报

6

主题

29

帖子

0

精华

初级会员

Rank: 2

积分
163
金钱
163
注册时间
2010-12-17
在线时间
37 小时
发表于 2015-2-10 16:33:41 | 显示全部楼层
测试过楼主的延时,发现遥控解码时有时会假死,也就是有时按下遥控按键会死机,等一段时间又恢复。后来我换成原子的延时,就没有出现过这种情况,现在不知是哪里有问题。是我的程序中其它地方,还是真的这个延时有问题,不确定。又碰到过的朋友分析一下。
出现假死时,程序中的外部中断与定时器中断可以动作。
回复 支持 反对

使用道具 举报

8

主题

28

帖子

0

精华

高级会员

Rank: 4

积分
820
金钱
820
注册时间
2015-3-24
在线时间
99 小时
发表于 2015-3-29 15:28:51 | 显示全部楼层
好厉害的,老师傅级的!学习之中!
VB软件,单片机制作(揭阳地区)
回复 支持 反对

使用道具 举报

3

主题

30

帖子

0

精华

初级会员

Rank: 2

积分
182
金钱
182
注册时间
2014-11-29
在线时间
39 小时
发表于 2015-3-31 14:51:25 | 显示全部楼层
好帖!!!!!!!!!!!!!!!!!!
回复 支持 反对

使用道具 举报

10

主题

40

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
346
金钱
346
注册时间
2013-12-20
在线时间
94 小时
发表于 2015-12-22 22:59:13 | 显示全部楼层
牛逼cool
回复 支持 反对

使用道具 举报

29

主题

244

帖子

0

精华

高级会员

Rank: 4

积分
944
金钱
944
注册时间
2014-10-9
在线时间
93 小时
发表于 2015-12-23 09:37:19 | 显示全部楼层
确实是好东西啊
淘宝小店,没事可以点一下增加点流量http://shop69767205.taobao.com/
回复 支持 反对

使用道具 举报

16

主题

73

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
214
金钱
214
注册时间
2015-12-21
在线时间
18 小时
发表于 2015-12-23 22:05:34 | 显示全部楼层
牛,可以试试。
回复 支持 反对

使用道具 举报

6

主题

46

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
305
金钱
305
注册时间
2014-3-24
在线时间
39 小时
发表于 2015-12-25 22:31:05 | 显示全部楼层
楼主加油!
回复 支持 反对

使用道具 举报

69

主题

978

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
3765
金钱
3765
注册时间
2015-4-26
在线时间
762 小时
发表于 2016-1-14 09:02:50 | 显示全部楼层
非常不错,感谢分享
我有故事,你有酒吗
回复 支持 反对

使用道具 举报

1

主题

40

帖子

0

精华

初级会员

Rank: 2

积分
77
金钱
77
注册时间
2016-1-18
在线时间
7 小时
发表于 2016-1-24 20:55:46 | 显示全部楼层
32定时器很多啊,为什么要省出一个定时器呢?  难道能做到用光板载资源的地步?
回复 支持 反对

使用道具 举报

0

主题

17

帖子

0

精华

初级会员

Rank: 2

积分
172
金钱
172
注册时间
2013-3-8
在线时间
34 小时
发表于 2016-1-25 22:32:17 | 显示全部楼层
18楼妙啊
回复 支持 反对

使用道具 举报

5

主题

86

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1535
金钱
1535
注册时间
2015-2-4
在线时间
285 小时
发表于 2016-1-27 16:01:46 | 显示全部楼层
试了一下,在MDK5下,   ts =  usec * (cpuclkfeq /(1000*1000) );   语句报错,换成具体数值可以使用,但主要问题是无法使用软件仿真功能,一直报错!
回复 支持 反对

使用道具 举报

14

主题

82

帖子

1

精华

中级会员

Rank: 3Rank: 3

积分
374
金钱
374
注册时间
2014-12-11
在线时间
64 小时
发表于 2016-1-28 09:26:55 | 显示全部楼层
跟arduino的millis()差不多 很不错 不要清楚直接查询  之前想用systick做 在中断里++ 延时的话可以先读取数值 再查询实时数值减去之前读取值是否已经到时间  但是US做不到
回复 支持 反对

使用道具 举报

69

主题

978

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
3765
金钱
3765
注册时间
2015-4-26
在线时间
762 小时
发表于 2016-1-28 09:50:52 | 显示全部楼层
感谢分享,标记一下,慢慢学习
我有故事,你有酒吗
回复 支持 反对

使用道具 举报

5

主题

86

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1535
金钱
1535
注册时间
2015-2-4
在线时间
285 小时
发表于 2016-1-28 10:30:27 | 显示全部楼层
该功能可能是ST留给自己一些功能使用的,比如MDK的软件虚拟仿真。所以一旦使用就会导致某些功能失效,还是不用为秒。
回复 支持 反对

使用道具 举报

3

主题

177

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1603
金钱
1603
注册时间
2016-1-28
在线时间
265 小时
发表于 2016-1-28 16:09:19 | 显示全部楼层

强大!学习了!
宠辱不惊看庭前花开花落去留无意望天上云卷云舒。
回复 支持 反对

使用道具 举报

0

主题

6

帖子

0

精华

初级会员

Rank: 2

积分
68
金钱
68
注册时间
2014-10-2
在线时间
12 小时
发表于 2016-2-20 13:04:29 | 显示全部楼层
最近在ucos下折腾使用systick做延时,延时输出一直都不对,今天看到这个帖子了,实验测试看波形没问题,先用着,等空了再继续折腾ucos下使用systick延时的问题,非常感谢!!!!
回复 支持 反对

使用道具 举报

2

主题

25

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
332
金钱
332
注册时间
2016-11-3
在线时间
49 小时
发表于 2016-11-26 11:24:42 | 显示全部楼层
现在还看不懂,先收着等我等级升上来了再来
回复 支持 反对

使用道具 举报

0

主题

48

帖子

0

精华

初级会员

Rank: 2

积分
161
金钱
161
注册时间
2016-11-25
在线时间
28 小时
发表于 2016-11-26 12:13:56 | 显示全部楼层
mark、、、、
回复 支持 反对

使用道具 举报

2

主题

23

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
205
金钱
205
注册时间
2015-4-13
在线时间
30 小时
发表于 2017-1-9 21:47:02 | 显示全部楼层
牛人,学习了
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-2-26 04:12

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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