【问题标题】:When programming microchip in C, how do you calculate the value needed for 1 second delay用C编程微芯片时,如何计算1秒延迟所需的值
【发布时间】:2016-05-08 23:13:04
【问题描述】:

如果在初始 Pragma 配置后给定 187.5hz,则大约为 1190,以便有 1 秒延迟。我被困在如何计算这个数字上。请帮忙!

这是初始编译指示配置

#pragma config   JTAGEN    = OFF    // JTAG Enable OFF (only use for '250)
#pragma config   FNOSC     = FRCPLL // Fast RC w PLL 8mHz internal rc Osc
#pragma config   FPLLIDIV  = DIV_10  // PLL in 8mHz/10 = 800 kHz
#pragma config   FPLLMUL   = MUL_15 // PLL mul 800 khz * 15 = 12 Mhz
#pragma config   FPLLODIV  = DIV_64  // PLL Out: 12MHz / 64 187.5 kHz
#pragma config   FPBDIV    = DIV_1  // Peripheral Bus Divisor
#pragma config   FCKSM     = CSECME // Clock Switch Enable, FSCM Enabled
#pragma config   POSCMOD   = OFF    // Primary osc disabled
#pragma config   IESO      = OFF    // Internal/external switch over
#pragma config   OSCIOFNC  = OFF    // CLKO Output Signal Active on the OSCO Pin
#pragma config   FWDTEN    = OFF    // Watchdog Timer Enable:

1190 是这样来的

// Delay routine
// With an 8MHz internal RC clock and settings to give a system clock
// of 187.5 kHz, the delay() function must be given about 1190 to get 1 sec
// delay:
// stopwatch: 100 complete ON/OFF pulses in 119 seconds.
// 500/((100/119)/2) = 1190
void delay(int d)
{
int i;  // Declare variable to be used in the loop

while(d)    // While d > 0
{
    i = 100;    // set i to 100 for inner loop
    while(i)    // while i > 0
    {
        i--;    // decrement i (e.g. i will equal 99, 98, 97,...)
    }

    d--;    // decrement d
}
}

即使看了评论,我仍然不知道数字是如何计算的......

【问题讨论】:

  • 编写delay函数,检查汇编代码,然后查看CPU的文档,知道每条指令需要多少个周期,以及循环(或循环)的总周期数.然后,如果您知道一段代码需要多少个周期,那么当您拥有时钟频率(它决定每秒的周期数)时,很容易计算出作为参数所需的值。
  • 你在为什么芯片编程?通常你会使用某种中断来实现延迟。
  • 没有可以查询的硬件时钟(亚秒级精度)吗?简单的旧忙等待延迟循环可能很难调整且耗时。你是编译到实际硬件还是模拟器?
  • @FUZxxl 我正在为 PIC32MX250F128B 编程
  • @JoachimPileborg 我的芯片是 32 位的,如何在数据表中查找周期?每个乘法和除法是否不同?

标签: c frequency microchip


【解决方案1】:

在 libpic30.h 你有这个功能:

void __delay32(unsigned long cycles);

其中cycles是要延迟的周期数。

“cycles”的最小值为 12,这在“16-Bit Language Tools Libraries Reference Manual”中指定

【讨论】:

    【解决方案2】:

    要对 PIC32 进行编程,我建议使用 microchip 的 Harmony 框架。然后,您可以使用微芯片和声配置器创建一个周期性定时器,如果定时器的计数器为零,则启动回调函数。此方法不阻塞PIC,易于创建..

    如果你需要,我可以给你一个例子。

    【讨论】:

      【解决方案3】:

      此类循环计数宏的问题在于它们高度特定于部分(核心类型),如果您曾经迁移到 32MZ 部分,这可能会让您感到悲痛。

      大多数高端(16,32 位)Microchip 部件至少有 5 个可配置的 16 位定时器,它们可以被配置为 2×2 的 32 位定时器。

      使用此类计时器可以让您直接从某个 CPU 内部频率(核心或外围设备)中获取时间,从而避免需要除每个部分的相关频率之外的“魔术”数字(-family)

      该块通常也位于某个寄存器标志上以检查中断标志,这意味着只需要一个循环即可提高分辨率。

      我没有代码给你,因为我只玩过 32 位部分,并且更熟悉 16 位 (dspic) 部分,这是所谓的“外围库”的一部分

      附:如果您设计了一个好的延迟函数,最好还添加一个 ClrWdt() 或任何将 PIC32 上的看门狗重置到外部 while 循环的方法。

      【讨论】:

        【解决方案4】:

        OP 中代码中的注释似乎与实际代码无关。代码中未使用 1190。

        假设delay() 的参数是毫秒,我认为正确的计算是 187.5(周期/毫秒)/N(周期/内循环)= 187.5/N 内循环/毫秒。如果 N 为 3(循环/内循环),那么这将是 62.5 内循环/毫秒。或 62,500 个内循环/秒。要得出 1190 内循环/秒,N 需要大约为 158。对于代码中的常数 100,N 将是 1.875。

        指令集包含一个 DECFSZ 指令,该指令递减一个寄存器,然后跳过该指令(通过执行 NOP 代替)。如果内循环展开相当多,那么每个内循环的平均指令数将接近 2。但即使在这种情况下,我认为你想使用值 187.5/2 = 94。也许有一些处理器优化可以减少周期计数 6%。或者可能 delay() 被校准为 200KHz 系统时钟。

        对延迟例程进行基准测试以了解它的准确性会很有趣。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2019-01-13
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多