我应该如何为具有 48MHz 晶振和 MCC18 编译器的 PIC 18f87J50 编写延迟宏。延迟应该在我们身上。所以我例如可以写:Delay_us(201) 并真正得到 201us 延迟。
我现在拥有的是:
#define Delay_us(n) (Delay10TCYx(((n) * (uint16_t) 12 + 9) / 10))
而且它在我的示波器上似乎不正确!:/
亲切的问候!
圣诞快乐!
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
}
部分不准确可能是由于计算传递给Delay10TCYx的值的表达式的评估。由于该表达式包含一个除法,因此控制器可能需要相当长的时间来计算该值。
MCC 手册解释了创建延迟循环所涉及的非常简单的数学。您可以只实现自己的循环,而不是依赖库延迟函数。
我听说这会更准确,但我的示波器只是给了我其他值然后对了。我编译的时候会不会有事??那我不是在最高级别做吗??
#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))
我发现这使我的延迟更加准确:
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 在....另一个论坛 ;)