打印

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

[复制链接]
1366|22
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
lzmm|  楼主 | 2023-4-10 08:00 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
  在这里, 我来讨论一下关于MSP430单片机使用__delay_cycles延时的问题.
    IAR for MSP430编译器提供了一个编译器内联的精确延时函数(并非真正的
函数)以提供用户精确延时使用, 该函数原型是:
        __intrinsic void __delay_cycles(unsigned long __cycles);
该内部函数实现__cycles个CPU周期的延时,但对于该参数的设置,我要陈述一下:
    __cycles需要我们传递的是CPU运行的周期个数

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

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

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

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

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

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

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


使用特权

评论回复

相关帖子

沙发
chenjun89| | 2023-4-10 19:30 | 只看该作者
延时最好是用定时器中断

使用特权

评论回复
板凳
tpgf| | 2023-5-4 10:55 | 只看该作者
请问一下什么叫做编译器内联的函数呢

使用特权

评论回复
地板
nawu| | 2023-5-4 11:24 | 只看该作者
tpgf 发表于 2023-5-4 10:55
请问一下什么叫做编译器内联的函数呢

应该这就是编译器的一种优化吧

使用特权

评论回复
5
aoyi| | 2023-5-4 12:15 | 只看该作者
方法内联就是把目标方法的代码复制到发起调用的方法之中,避免发生真实的方法调用。可以避免压栈和出栈的操作。提高效率

使用特权

评论回复
6
zljiu| | 2023-5-4 13:05 | 只看该作者
内联函数不需要寻址的过程,当执行到内联函数时,此函数展开(很类似宏的使用),如果在 N处调用了此内联函数,则此函数就会有N个代码段的拷贝

使用特权

评论回复
7
gwsan| | 2023-5-4 14:11 | 只看该作者
内联函数虽然节省了函数调用的时间消耗,但由于每一个函数出现的地方都要进行替换,因此增加了代码编译的时间。

使用特权

评论回复
8
tfqi| | 2023-5-4 14:27 | 只看该作者
不是所有的函数都能够变成内联函数。现在的编译器也很聪明,就算你不写 inline,它也会自动将一些函数优化成内联函数

使用特权

评论回复
9
uiint| | 2023-5-5 13:09 | 只看该作者
单片机实现精确延时可以通过定时器和外部晶振等方式来实现。

使用特权

评论回复
10
pmp| | 2023-5-5 18:01 | 只看该作者
这个应用非常复杂的吗
              

使用特权

评论回复
11
albertaabbot| | 2023-5-5 18:36 | 只看该作者
一般适用于不需要非常精确的延时情况。

使用特权

评论回复
12
sesefadou| | 2023-5-5 19:07 | 只看该作者
外部晶振也可以用来提供精确的时间基准,从而实现精确延时。

使用特权

评论回复
13
sdlls| | 2023-5-5 21:15 | 只看该作者
使用定时器实现精确延时的优点是可以提供非常精确的时间基准,缺点是需要占用单片机的定时器资源

使用特权

评论回复
14
hilahope| | 2023-5-5 21:29 | 只看该作者
这个为什么不使用定时器实现呢?              

使用特权

评论回复
15
geraldbetty| | 2023-5-5 21:45 | 只看该作者
在单片机编程中,使用 __delay_cycles() 函数可以实现精确延时。

使用特权

评论回复
16
jonas222| | 2023-5-5 22:29 | 只看该作者
使用外部晶振实现精确延时的优点是可以提供非常准确的时间基准

使用特权

评论回复
17
pmp| | 2023-5-6 00:09 | 只看该作者
通常可以使用定时器或者外部晶振来提供精确的时间基准。

使用特权

评论回复
18
jonas222| | 2023-5-6 00:18 | 只看该作者
要结合实际应用场景来选择合适的延时方法。

使用特权

评论回复
19
hudi008| | 2023-5-6 00:35 | 只看该作者
需要注意其使用方式和精度限制              

使用特权

评论回复
20
plsbackup| | 2023-5-7 15:12 | 只看该作者
定时器功能, 需要设计合理的定时器中断处理流程。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

401

主题

8863

帖子

11

粉丝