Search code examples
cdelaymicrocontrollerpic18mplab

Delay on PIC18F


I'm using a PIC18F14K50 with HiTech ANSI C Compiler and MPLAB v8.43. My PIC code is finally up and running and working, with the exception of the delay function. This is crucial for my application - I need it to be in certain states for a given number of milliseconds, seconds, or minutes.

I have been trying to find a solution for this for about 2 weeks but have been unsuccessful so far. I gave up and wrote my own delay function with asm("nop"); in a loop, but this gives very unpredictable results. If I tell it to wait for half a second or 5 seconds, it works accurately enough. But as soon as I tell it to wait for longer - like for 10 minutes, the delay only lasts about 10 - 20 seconds, and 2 minutes ands up being a blink shorter than a 500ms delay.

Here are my config fuses and wait() function:

#include <htc.h>

__CONFIG(1, FOSC_IRC   & FCMEN_OFF & IESO_OFF & XINST_OFF);
__CONFIG(2, PWRTEN_OFF & BOREN_OFF & WDTEN_OFF);
__CONFIG(3, MCLRE_OFF);
__CONFIG(4, STVREN_ON  & LVP_OFF   & DEBUG_OFF);
__CONFIG(5, 0xFFFF);
__CONFIG(6, 0xFFFF);
__CONFIG(7, 0xFFFF);

void wait(int ms)
{
  for (int i = 0; i < ms; i++)
    for (int j = 0; j < 12; j++)
      asm("nop");
}

Like I said, if I call wait(500) up to wait(30000) then I will get half a second to 30 second delay to within the tolerence I'm interested in - however if I call wait(600000) then I do not get a 10 minute delay as I would expect, but rather about 10-15 seconds, and wait(120000) doesn't give a 2 minute delay, but rather a quick blink.

Ideally, I'd like to get the built-in __delay_ms() function working and being called from within my wait(), however I haven't had any success with this. If I try to #include <delay.h> then my MPLAB complains there is no such file or directory. If I look at the delay.h in my HiTech samples, there is a DelayUs(unsigned char) defined and an extern void DelayMs(unsigned char) which I haven't tried, however when I try to put the extern directly into my C code, I get an undefined symbol error upon linking.

The discrepancy between the short to medium delays and the long delays makes no sense. The only explanation I have is that the compiler has optimised out the NOPs or something.

Like I said, it's a PIC18F14K50 with the above configuration fuses. I don't have a great deal of experience with PICs, but I assume it's running at 4MHz given this set-up.

I'm happy with an external function from a library or macro, or with a hand-written function with NOPs. All I need is for it to be accurate to within a couple of seconds per minute or so.


Solution

  • Is the PIC a 16-bit microcontroller? My guess is that you're getting overflow on the value of wait, which would overflow after 2^15 (32,767 is the max value of a signed 16 bit int).