Question

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.

Was it helpful?

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

OTHER TIPS

If you change your int variables to unsigned, you can go up to 65535ms. To go higher than that, you need to use long as your parameter type and nest your loops even deeper.

A better long term solution would be to write a delay function that uses one of the built in hardware timers that are in your chip. Your NOP delay will not be accurate over long periods if you have things like other interrupts firing and using some CPU cycles

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top