View previous topic :: View next topic |
Author |
Message |
spiderloic74 Guest
|
problem delay us |
Posted: Wed Dec 24, 2008 3:10 am |
|
|
Hi,
I work on PIC18F4550 with MPLAB and a compiler CCS PCW.
I have a problem with the function delay_us(), i can't exceed 255. (i think i should take a more recent CCS compiler?)
Then i do a function for, with for end my delay that i want and inside delay-us(1). The problem is that she produce a real time incoherent (not linear compared at the number) and higher.
I count the time's instructions, but it's not that. or it's problem with the function for... i don't know.
Someone will have an idea for this error or so a way for do a delay more high (with a timer i can't, i use already lot of interruption)
Thank |
|
|
asmallri
Joined: 12 Aug 2004 Posts: 1635 Location: Perth, Australia
|
|
Posted: Wed Dec 24, 2008 5:13 am |
|
|
older versions of the compiler delay_us() accepts a variable in the range of 0 to 255 or a constant in the range of 0 to 65535. New versions of the compiler accept a variable in the range of 0 to 65535.
The delay function is based sw based instruction cycle based delay loops. If your code uses interrupts then the delay will be incorrect as it will include all the time the PIC spent processing the interrupts. If you need accurate times then you need to use a timer. Setup a timer will the desired delay, and monitor the timer interrupt flag until it is set. Note that you do not need to enable interrupts for the timer you are using as you just need to poll the flag. _________________ Regards, Andrew
http://www.brushelectronics.com/software
Home of Ethernet, SD card and Encrypted Serial Bootloaders for PICs!! |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Wed Dec 24, 2008 6:50 am |
|
|
The for-loop with a delay_us(1) call inside has the problem that the overhead of the loop and calling the function is too large. On a 4MHz processor the overhead could take as much as 4us for every loop...
Here is a link to a delay_us function taking an int16 as parameter: http://www.ccsinfo.com/forum/viewtopic.php?t=16656
As mentioned by Asmallri interrupts will cause extra delays. For many applications this is no problem but if the timer needs to be accurate you'll have to use one of the hardware timers. An efficient method for creating more timers is to have one hardware timer drive many software timers, see the example code below.
Code: | #include <16F876.h>
#device *=16
#fuses HS, NOWDT, NOLVP, NOPROTECT
#use delay(clock=16000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)
#define MY_TIMER_1_RATE 10 // Every 10 ms
#define MY_TIMER_2_RATE 50 // Every 50 ms
int8 sw_timer1;
int8 sw_timer2;
// This timer interrupt is configured to fire every 1 ms
// Inside are two software based timers that fire every x ms.
#int_timer0
void my_timer_isr(void)
{
set_timer0( get_timer0() + (256 - 250)); // Adjust timer0 value to assure it overflows
// every 1000us instead of 1024us
if (--sw_timer1 == 0)
{
sw_timer1 = MY_TIMER_1_RATE;
// Do your timer 1 thing here
}
if (--sw_timer2 == 0)
{
sw_timer2 = MY_TIMER_2_RATE;
// Do your timer 2 thing here
}
}
void main(void)
{
sw_timer1 = MY_TIMER_1_RATE;
sw_timer2 = MY_TIMER_2_RATE;
setup_timer_0(RTCC_INTERNAL | RTCC_DIV_16); // 1 tick every 4 us (at 16MHz)
enable_interrupts(INT_TIMER0);
enable_interrupts(GLOBAL);
while(TRUE);
} |
|
|
|
vsmguy
Joined: 13 Jan 2007 Posts: 91
|
|
Posted: Sun Jul 11, 2010 7:33 pm |
|
|
ckielstra wrote: | The for-loop with a delay_us(1) call inside has the problem that the overhead of the loop and calling the function is too large. On a 4MHz processor the overhead could take as much as 4us for every loop... |
Incorrect.
The function will be inlined as and when required.
delay_us() is 100% accurate till 153uS after which CCS *really* uses a sloppy function call. Its is after this that > 0.3% error in timing is introduced.
Sorry to reply to such an old thread but I am looking into this matter now and wanted to keep this as a reference.
Here is CCS generated ASM for 20MHz:
Code: |
.................... delay_us( 1 );
0182: GOTO 183
0183: GOTO 184
0184: NOP
|
|
|
|
|