对MSP430单片机__delay_cycles精确延时的说明

[复制链接]
 楼主| lzmm 发表于 2023-4-10 08:00 | 显示全部楼层 |阅读模式
  1.   在这里, 我来讨论一下关于MSP430单片机使用__delay_cycles延时的问题.
  2.     IAR for MSP430编译器提供了一个编译器内联的精确延时函数(并非真正的
  3. 函数)以提供用户精确延时使用, 该函数原型是:
  4.         __intrinsic void __delay_cycles(unsigned long __cycles);
  5. 该内部函数实现__cycles个CPU周期的延时,但对于该参数的设置,我要陈述一下:
  6.     __cycles需要我们传递的是CPU运行的周期个数

  7.     网上普遍的用法是:
  8.         #define CPU_CLOCK       8000000
  9.         #define delay_us(us)    __delay_cycles(CPU_CLOCK/1000000*(us))
  10.         #define delay_ms(ms)    __delay_cycles(CPU_CLOCK/1000*(ms))

  11.     在CPU主时钟频率为8MHz时, 这确实没有问题, 但是这样的写法:
  12.         #define CPU_CLOCK       8000000
  13. 这很容易让人们想到, 可以通过修改它的值以实现对不同主频系统参数的统一,其实
  14. 这是不正确的! 比如修改为#define CPU_CLOCK 32768以实现32KHz主频的延时...

  15.     下面来计算看看:
  16.         当系统主时钟频率CPU_CLOCK为8MHz时:
  17.         频率 f = 8MHz = ,,000Hz
  18.         机器周期 Tm = /f = /8MHz = /8us
  19.     也就是说,一个机器周期(nop)的时长是1/8us,所以延时1us即8*Tm,同上面:
  20.         #define delay_us(us)    __delay_cycles(8*(us))
  21.         #define delay_ms(ms)    __delay_cycles(8000*(ms))

  22.     按照上面的宏定义方法,我们把CPU_CLOCK定义成32768,那么:
  23.         频率 f = 32KHz = ,768Hz
  24.         机器周期 Tm = /f = /32768Hz ~= .5us
  25.     可想而知,CPU最短的指令执行周期为30.5us, 这时, 想延时1us, 这可能吗?
  26. 所以, 简单地把上面的定义改成
  27.         #define CPU_CLOCK   32768
  28. 是绝对错误的.

  29.     同样, 还有些朋友实现了0.5us的延时, 这在当f = 1MHz = 1000000Hz时也
  30. 是不现实的, 此时机器周期Tm = 1us. 在f = 8Mhz时, 4个机器周期为0.5us尚可.

  31.     所以, 为避免引起错误的使用或不正确的理解,最好像下面这样定义宏:
  32.         #if CPU_CLOCK == 8000000
  33.             #define delay_us(us)    __delay_cycles(8*(us))
  34.             #define delay_ms(ms)    __delay_cycles(8000*(ms))
  35.         #else
  36.             #pragma error "CPU_CLOCK is defined implicitly!"
  37.         #endif

  38. 另外:
  39.   __delay_cycles  并不是真正的函数, 只是提供编译器内联展开,该函数并
  40. 不支持变量参数, 其参数只能是常数.


chenjun89 发表于 2023-4-10 19:30 来自手机 | 显示全部楼层
延时最好是用定时器中断
tpgf 发表于 2023-5-4 10:55 | 显示全部楼层
请问一下什么叫做编译器内联的函数呢
nawu 发表于 2023-5-4 11:24 | 显示全部楼层
tpgf 发表于 2023-5-4 10:55
请问一下什么叫做编译器内联的函数呢

应该这就是编译器的一种优化吧
aoyi 发表于 2023-5-4 12:15 | 显示全部楼层
方法内联就是把目标方法的代码复制到发起调用的方法之中,避免发生真实的方法调用。可以避免压栈和出栈的操作。提高效率
zljiu 发表于 2023-5-4 13:05 | 显示全部楼层
内联函数不需要寻址的过程,当执行到内联函数时,此函数展开(很类似宏的使用),如果在 N处调用了此内联函数,则此函数就会有N个代码段的拷贝
gwsan 发表于 2023-5-4 14:11 | 显示全部楼层
内联函数虽然节省了函数调用的时间消耗,但由于每一个函数出现的地方都要进行替换,因此增加了代码编译的时间。
tfqi 发表于 2023-5-4 14:27 | 显示全部楼层
不是所有的函数都能够变成内联函数。现在的编译器也很聪明,就算你不写 inline,它也会自动将一些函数优化成内联函数
uiint 发表于 2023-5-5 13:09 | 显示全部楼层
单片机实现精确延时可以通过定时器和外部晶振等方式来实现。
pmp 发表于 2023-5-5 18:01 | 显示全部楼层
这个应用非常复杂的吗
              
albertaabbot 发表于 2023-5-5 18:36 | 显示全部楼层
一般适用于不需要非常精确的延时情况。
sesefadou 发表于 2023-5-5 19:07 | 显示全部楼层
外部晶振也可以用来提供精确的时间基准,从而实现精确延时。
sdlls 发表于 2023-5-5 21:15 | 显示全部楼层
使用定时器实现精确延时的优点是可以提供非常精确的时间基准,缺点是需要占用单片机的定时器资源
hilahope 发表于 2023-5-5 21:29 | 显示全部楼层
这个为什么不使用定时器实现呢?              
geraldbetty 发表于 2023-5-5 21:45 | 显示全部楼层
在单片机编程中,使用 __delay_cycles() 函数可以实现精确延时。
jonas222 发表于 2023-5-5 22:29 | 显示全部楼层
使用外部晶振实现精确延时的优点是可以提供非常准确的时间基准
pmp 发表于 2023-5-6 00:09 | 显示全部楼层
通常可以使用定时器或者外部晶振来提供精确的时间基准。
jonas222 发表于 2023-5-6 00:18 | 显示全部楼层
要结合实际应用场景来选择合适的延时方法。
hudi008 发表于 2023-5-6 00:35 | 显示全部楼层
需要注意其使用方式和精度限制              
plsbackup 发表于 2023-5-7 15:12 | 显示全部楼层
定时器功能, 需要设计合理的定时器中断处理流程。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

413

主题

9133

帖子

12

粉丝
快速回复 在线客服 返回列表 返回顶部

413

主题

9133

帖子

12

粉丝
快速回复 在线客服 返回列表 返回顶部