PIC18F: delay with Nops?

Discussion in 'Embedded Systems and Microcontrollers' started by msr, Jan 31, 2011.

  1. msr

    Thread Starter Well-Known Member

    Jul 8, 2008

    Can we get precise delays with Nops()?
    Nop() corresponds to TCY right? In case of PIC18F, TCY=4/CrystalFreq right? (4 cycles per instruction)

    Im using a PIC18F2550 with a 4MHz crystal and I just want to blink an LED on RA0 pin. I want it to be ON for 1 second and OFF for the same amount of time.

    So, once 4 cycles are needed to acomplish one instruction it gives: Nop() = (4/4Mhz) = 1us. Right? Then, I need 1.000.000 Nops.

    However the result is that the LED is ON for much more that 1 second. About 2.5 seconds...

    Here is the code Im using:
    Code ( (Unknown Language)):
    2. #include <p18f2550.h>
    4. void delay(unsigned int N){
    5.     unsigned int i;
    6.     for(i=0; i < N; i++) Nop();
    7. }
    9. void main(void)
    10. {
    11.     unsigned int i;
    13.     //WDTCONbits.SWDTEN = 0;
    14.     TRISA = 0x11111110;
    15.     LATA = 0;
    17.     while(1)
    18.     {
    19.         LATA = 1;
    20.         for(i = 0; i < 50; i++)
    21.             delay(20000);
    23.         LATA = 0;
    24.         for(i = 0; i < 50; i++)
    25.             delay(20000);
    26.     }
    27. }
    What am I missing?

    Thanks in advance.
  2. DumboFixer

    Active Member

    Feb 10, 2009
    Have you factored in the time to actually process the loop ?

    The loop variable needs to be decremented, compared against the limit and loop back if not finished - this all takes clock cycles. This applies to the delay function and the loop that calls it.

    You are getting your 1,000,000 nops as well as 1,000,000 sets of other instructions etc.

    This is, more than likely, when your extra time is coming from.

    Have a look at the assembly language produced to see the extra instructions.
  3. t06afre

    AAC Fanatic!

    May 11, 2009
    From your code I can not see which C compiler you use. But you should be able to look at your asm code output. Then you will see that your delay loop is more complex than just only NOPs. In your delay function. You will also have a counter variable. This need to be decremented and checked if the result is zero. If the result is non zero a NOP is executed. All this will take some machine code instructions to preform. Hence the long delay times
  4. spinnaker

    AAC Fanatic!

    Oct 29, 2009
    You are going to have to use assembly if you want accurate timing delays. Even if you can get "predictable" results with , the results may become unpredictable over the long term. If you change compilers or upgrade compilers you results may change because of the way the compiler chooses to interpret your C code or the way it chooses to optimize it.

    I developed several accurate assembler based delays. The problem is that I used inline assembler and the c18 compiler is not resolving branches inside the asm block. So what happens is you have two delays withing the same function, the second delay branches to the first loop of the first call to the delay routine.

    I think I will have to go to straight assembler but I need to learn how to pass values to assembler.
  5. t06afre

    AAC Fanatic!

    May 11, 2009
    If you need precise timing use internal timers and interrupts. But for more simple task a delay made in software may do. If you only want to blink a LED at one second rate. It does not has much to say if the delay is a few cycles off.
  6. spinnaker

    AAC Fanatic!

    Oct 29, 2009

    Ah yes! I got so wrapped up in programming delays I forgot to mention timers.

    And in the OP's case, this might be the better option.

    See my recent post on interrupts, near the bottom of this thread.