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 support@ccsinfo.com

problem with interrupt timing and delay_ms function.

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



Joined: 19 Sep 2003
Posts: 8

View user's profile Send private message Send e-mail

problem with interrupt timing and delay_ms function.
PostPosted: Thu Mar 18, 2010 3:26 am     Reply with quote

using 18F6723, CCS PCH C Compiler, Version 4.105, 50381
MPlab 8.3 and ICD3. Home build board.
I some code to generate an interrupt every 0.1Sec, part of a simple timer. This works fine but if I put a delay_ms(500) statement in the main() the interval changes to 0.25Sec. Have put some code into the interrupt routine to flash an LED and have checked the timing with a scope.

I thought the delay_ms statement would not affect the interrupt? Cant see what I am doing wrong here. If I change the delay period in the delay_ms the interrupt period changes. Obviously the final code wont have a delay_ms(500) in it this is just the bare minimum test code.
suggestions welcome!
mike

Code:

// Control program V3.00
//
#include <18f6723.h>
#device ICD=true
#DEVICE *=16  adc=10

#fuses  NOBROWNOUT, NOWDT, NOLVP , debug
#fuses  HS
#use delay (clock=8000000)
#use rs232(baud=4800, xmit=PIN_C6, rcv=PIN_C7, parity=N, BITS =8, STOP=1)
// ====
//#use i2c(master, SDA=PIN_C4, SCL=PIN_C3)
//#define SLAVE1_WRT_ADDR   0x12
//#define SLAVE1_READ_ADDR  0x13


//#include <cnt3_setup.c>    // all defines setup in here
#byte PIR2 = 0xFA1
// ====defines====
#define led0 PIN_E0
#define led1 PIN_E1
// Variable definitions
int valve_overlap;  // overlap between firing and releasing previous solenoid
int valve_inuse=0;  // holds index of last valve driven
int valve_next;      // variable used in valve control routine

float m_secs=0;       // ~0.1 sec count see interrupt code
int   secs=0;         // sec count
int   mins=0;         // minute count
int   hours=0;      // hour count
int   days=0;         // day count
float   t3_inc=0.1;

int   crap;
int16   t3, t3_set;
//#include <drive_mode.c>    // basic drive control code
//#include <int_code.c>       // interupt code

#INT_TIMER3
void time3()
{
   // occurs when Timer 3 rollover. Count rollovers to get time > rollover time
   // timer 3 rollover
   // clock is 8MHz, input to timer3 is 8/4=2MHz, div 4 divider =500000Hz or 2uS per tick
   // pre load timer3 with 15535 so that it does a count of 50000 to rollover
   // whihc is 0.1 Seconds between interupts
//timing test code
      t3=get_timer3();
   set_timer3(t3_set);
      output_high(led0);
      delay_ms(1);
      output_low(led0);
//
   m_secs=m_secs+t3_inc;
   if (m_secs > 60)
   {
      m_secs=0;
      secs=secs+1;
   }

   if (secs > 60)
   {
      secs=0;
      mins=mins+1;
   }
   if (mins >60)
   {
      mins=0;
      hours=hours+1;
   }
   if (hours > 24)
   {
      days=days+1;
      hours=0;
   }     

}


main()
{

// clock is 8MHz
// timer input is 8/4 2MHz, div by 4 = 500kHz, each count 2uS, 16 bit max count 65535, pre // pre load with 15535 so that rollover occurs every 50000 * 2uS or 0.1 Sec
   setup_timer_3 (T3_INTERNAL | T3_DIV_BY_4); //
//   setup_timer_3(T3_disabled);
   t3_set=15535;
   set_timer3(t3_set);
   enable_interrupts(INT_TIMER3); // basic clock
   enable_interrupts(GLOBAL);   
do   {

   delay_ms(5000);

   }while(true);
}
Ttelmah



Joined: 11 Mar 2010
Posts: 19348

View user's profile Send private message

PostPosted: Thu Mar 18, 2010 4:56 am     Reply with quote

Your problem, is because you have a delay in the interrupt.

The PIC, does not have a hardware register stack, so it is very hard to write code that can safeley be called from inside itself (re-entrancy). CCS, for this reason, does not support this. Because of this, you should be getting a warning when you compile, saying:
"interrupts disabled during call to prevent re-entrancy. (delay_ms)".
Hence the interrupt is only being called in the few instructions when you loop back outside the delay. The actual time that then results wil depend on the duration of the delay, and the point when the counter wraps...

Now, a number of further comments:
1) If you have a timer 'tick', use _this_ to prvide your delays. Add something like:

Code:

int16 tick;

//Then in the interrupt:

if(tick!=0) --tick;

//Then when you want a delay in the main

tick=50;

while(tick) {
   //Nice thing is that you can still do other things here while waiting

}


2) Look at using timer2, and getting rid of settng the timer 'to' a value, or using a rolling counter to get your required timing. A search here will find why this is the way to go if you want anything approaching accuracy...

3) I you want to flash the LED, simply turn it on in one interrupt, and off in the next. Gives you the flash, without a delay. As a global 'rule' interrupt handlers should always be kept as short as possible, unless you really understand every implication of letting them be slower.

4) As a 'comment', what you post, is nothing near a 'bare minimum test code'. At least half the lines could be removed....

Best Wishes
mbarrett



Joined: 19 Sep 2003
Posts: 8

View user's profile Send private message Send e-mail

problem with interupt timing and delay_ms function.
PostPosted: Thu Mar 18, 2010 6:54 am     Reply with quote

Thanks for the helpful reply.
I had been testing the code without the delay_ms() in the interupt and still got the same problem....
I added the LED flash into the interupt to try to understand what was happening in the interrupt and didnt think about the affect that would have.
I understand what the problem with re-entrant code is. BTW I did not get any warning from the compiler.
I will go back and try it without the delay_ms() in the interrupt and see if I still get the same original timing error.

Your other points
1) yes much better simpler way of doing things..
2) will look at timer 2, but wanted to understand why it did not work with my method and timer3....
3) the LED flash code was just so I test with a scope I wanted the LED on for a known period of time hence the delay. Didnt think it would cause more problems Smile.
4) yes agree, this was the part of a larger program that I was working on and stripped out most of the code. Yes it could have been smaller and simpler.......

Will go away and try some changes, and search the forum, before coming back...

cheers
mike
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