views:

320

answers:

5

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!

+1  A: 

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.

shoosh
Thanks for the comment! Is it bad to rely on the library?
Christian
A: 

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 ;)

Christian
What happens if there is an interrupt during this delay ?
Charles Faiga
+1  A: 

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
}
Rex Logan
And I found that this was even more accurate!! :)
Christian
+2  A: 

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.

Albi
A: 

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))
Christian