1

我应该如何为具有 48MHz 晶振和 MCC18 编译器的 PIC 18f87J50 编写延迟宏。延迟应该在我们身上。所以我例如可以写:Delay_us(201) 并真正得到 201us 延迟。

我现在拥有的是:

#define Delay_us(n) (Delay10TCYx(((n) * (uint16_t) 12 + 9) / 10))

而且它在我的示波器上似乎不正确!:/

亲切的问候!

圣诞快乐!

4

5 回答 5

2

PIC 将时钟除以 4,因此对于 48Mhz,每个操作码以 0.0833us 或 12 个周期/us 运行。我使用 MPLAB 并输入不同的 us 值并在模拟器中检查,以便循环数符合我的预期。调整功能的最佳方法是查看程序集或使用模拟器。

您可以执行以下操作,但您必须调整编译器的函数调用。

#define OVERHEAD (2)

void Delay_us(uint8_t us)
{
   if ( us <= OVERHEAD ) return; // prevent underflow
   us  -= OVERHEAD ;             // overhead of function call in us.

   Nop();       // 1  extra overhead to make function overhead an even us.
   Nop();       // 1  add or remove Nop's as necessary.
   Nop();       // 1
   //Nop();       // 1
   //Nop();       // 1
   //Nop();       // 1
   //Nop();       // 1
   //Nop();       // 1
   //Nop();       // 1
   //Nop();       // 1
   //Nop();       // 1
   //Nop();       // 1

   do   // loop needs to be 12 cycles so each cycle is 1us.
   {
      Nop();       // 1
      Nop();       // 1
      Nop();       // 1
      Nop();       // 1
      Nop();       // 1
      Nop();       // 1
      Nop();       // 1
      Nop();       // 1
      ClrWdt();    // 1
   } while(--us);  // 3
}
于 2009-12-26T16:45:18.880 回答
2

部分不准确可能是由于计算传递给Delay10TCYx的值的表达式的评估。由于该表达式包含一个除法,因此控制器可能需要相当长的时间来计算该值。

于 2009-12-28T11:17:29.210 回答
1

MCC 手册解释了创建延迟循环所涉及的非常简单的数学。您可以只实现自己的循环,而不是依赖库延迟函数。

于 2009-12-25T11:09:39.513 回答
0

我听说这会更准确,但我的示波器只是给了我其他值然后对了。我编译的时候会不会有事??那我不是在最高级别做吗??

#define CONST_RANGE(min, val, max) (sizeof(char (*)[(val) >= (min) && (val) <= (max) ? +1 : -1]), (val))
#define Delay_ms(n) Delay1KTCYx(CONST_RANGE(1, (n) * 12L, 255))
#define Delay_us(n) Delay10TCYx(CONST_RANGE(1, ((n) * 12L + 6) / 10, 255))
于 2009-12-29T14:04:11.453 回答
0

我发现这使我的延迟更加准确:

void Delay_uS(byte uSec) {

   do {
       Delay1TCY();            // 1
       Delay1TCY();            // 1
       Delay1TCY();            // 1
       Delay1TCY();            // 1
       Nop();                        // 1
       Nop();                        // 1
       Nop();                        // 1
       ClrWdt();                        // 1; Clear the WDT
       } while(--uSec);        // 3
}

关于此的任何其他想法或回复?

感谢 Dario G 在....另一个论坛 ;)

于 2009-12-25T14:46:37.577 回答