CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

problem delay us

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
spiderloic74
Guest







problem delay us
PostPosted: Wed Dec 24, 2008 3:10 am     Reply with quote

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

View user's profile Send private message Send e-mail Visit poster's website

PostPosted: Wed Dec 24, 2008 5:13 am     Reply with quote

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

View user's profile Send private message

PostPosted: Wed Dec 24, 2008 6:50 am     Reply with quote

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

View user's profile Send private message Visit poster's website

PostPosted: Sun Jul 11, 2010 7:33 pm     Reply with quote

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
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group