Kenny Barber
Kenny Barber

Reputation: 245

Constant argument problem with PIC XC8 and __delay_ms() function

There is a built in function in xc8 called __delay_ms() that allows you to achieve an accurate delay.

My problem is that you can only put in a constant value like __delay_ms(1000) for 1 second. MPLAB gives the error

"inline delay argument must be constant"

I want to be able to put a variable in that depends on the users required delay from a PC GUI and EUSART RX.

I have tried using a const int but that doesn't work.

Has anyone any ideas on how to do this? maybe a way to manipulate the function somehow?

UPDATE - I have found the built-in delay routine in XC8's pic.h header file.

The code is:

/****************************************************************/
/* Built-in delay routine                   */
/****************************************************************/
#pragma intrinsic(_delay)
extern __nonreentrant void _delay(unsigned long);
#pragma intrinsic(_delaywdt)
extern __nonreentrant void _delaywdt(unsigned long);
#if defined(_PIC14E)
   #pragma intrinsic(_delay3)
   extern __nonreentrant void _delay3(unsigned char);
#endif
// NOTE: To use the macros below, YOU must have previously defined   _XTAL_FREQ
#define __delay_us(x) _delay((unsigned long)((x)*(_XTAL_FREQ/4000000.0)))
#define __delay_ms(x) _delay((unsigned long)((x)*(_XTAL_FREQ/4000.0)))
#endif

I'm assuming that somewhere in another XC8 header file, x has been programmed to only accept a constant number i.e 1000 but can't accept a const int.

Does anyone have any ideas on this?

Upvotes: 1

Views: 5196

Answers (2)

Mike
Mike

Reputation: 4288

__delay_ms() is not a real function, it is a macro which will expand into in-line assembly instructions or a nested loop of instructions which will consume the the specified number of time. So the delay argument must be a constant and can't be changed during runtime.

If you want a real function with a parameter you had to write it on you own. The most accurate way to do this is to work with a timer module of you PIC.

Upvotes: 0

EBlake
EBlake

Reputation: 755

__delay_ms() is implemented as a macro, and cannot accept a variable argument. So, write your own routine that takes your desired delay as a parameter and then calls __delay_ms(1) in a loop for as many ms delay as you want. There will be some slight overhead for the loop, so if you need more precise timing, you will have to calibrate this out.

If you are using a watchdog timer, inside this loop is a convenient place to reset the watchdog. I don't believe that the __delay_ms() macro resets the watchdog.

Upvotes: 1

Related Questions