Question

How should i write a delay macro for an PIC 18f87J50 with a 48MHz crystal and compiler of MCC18. The delay should be in us. So I for example can write: Delay_us(201) and really get 201us delay.

What I have now is:

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

And it does'nt seems right at my oscilloscope! :/

Kind Regards!

And merry Christmas!

Was it helpful?

Solution

The PIC divides the clock by 4 so for 48Mhz each opcode runs in 0.0833us or 12 cycles per us. I used MPLAB and put in different us values and checked in the simulator so that the number of cycles came out as I expected. The best way to adjust the function is to look at the assembly or use the simulator.

You can do something like the following but you will have to adjust the function call for your complier.

#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
}

OTHER TIPS

Part of the inaccuracy might be due to the evaluation of the expression that calculates the value that is passed to Delay10TCYx. Since this expression contains a division, it can take quite some time for the controller to calculate that value.

The MCC manual explains the very simple math that is involved in creating delay loops. You can just implement your own loop instead of relying on library delay functions.

I found that this made my delay us much more accurate:

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
}

Any other Ideas or replys regarding this?

Thanks to Dario G at.... another forum ;)

I heard this would be even more accurate, but my ocsilloscope just give me other values then right. Could it have something to do when I'm compiling?? That im not doing it at the highest lvl??

#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))
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top