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

Enabling interrupts during a delay_ms() or while() loop
Goto page 1, 2  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
joshkeys



Joined: 16 Aug 2005
Posts: 37
Location: Fredericton,NB

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

Enabling interrupts during a delay_ms() or while() loop
PostPosted: Sun Jan 21, 2007 1:33 pm     Reply with quote

Hi all,

Compiler: 3.239
PIC: 18F4320

I am implementing code in which I have external interrupts on int0 and int1. These interrupts are a on/off button and a reset button on my project. The problem arises in a case where In my code I want to wait a random length of time before turning on an LED. So to do this I am using

Code:

set_timer0(rand());

while(get_timer0() != 0){}

output_bit(LED,1);





The problem is if i hit the on/off button while it is in the while loop, the unit does not turn off until the loop is satisfied. I read a few posts from PCM_Programmer concerning interrupts being disabled while using delay_ms() and other routines.. so how do i get around this. I need to have a random delay for the LED to turn on, but if at any time the user wishes to turn off the unit, I want the interrupt to be working.

Thx
newguy



Joined: 24 Jun 2004
Posts: 1909

View user's profile Send private message

PostPosted: Sun Jan 21, 2007 3:32 pm     Reply with quote

Instead of waiting in a loop for timer 0 to roll over, simply set timer 0 to whatever you want, then enable the timer 0 interrupt. When it rolls over, the timer 0 interrupt will fire. In the timer 0 isr, turn on your LED and disable the timer 0 interrupt. If you set up your program in this manner, it will react instantaneously (well, as close to instantaneous as you can get) to user input or other stimulii.
joshkeys



Joined: 16 Aug 2005
Posts: 37
Location: Fredericton,NB

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

PostPosted: Sun Jan 21, 2007 3:38 pm     Reply with quote

Fair enough. That should work for this case.. but for the sake of being more flexible, do you know of anyway to use the delay_ms() command and still have interrupts active? Also, what is a list of commands that will disable interrupts? If you do any sort of loop, they do not seem to work, but for some reason, when I do my while(1) loop in my main program the interrupts will work fine, but if I use a while(!variable){} it does not seem to work. any ideas there?

Thx,
Josh
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sun Jan 21, 2007 5:15 pm     Reply with quote

Quote:

but for the sake of being more flexible, do you know of anyway to use the delay_ms() command and still have interrupts active?


Add a 2nd #use delay() statement, as shown in this thread:
http://www.ccsinfo.com/forum/viewtopic.php?t=27345&highlight=instance+delayms
joshkeys



Joined: 16 Aug 2005
Posts: 37
Location: Fredericton,NB

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

PostPosted: Sun Jan 21, 2007 5:18 pm     Reply with quote

Yah, I read that thread earlier and tried that with no luck. It still waited until my delay_ms() was comlplete.. I exaggerated the time and made it 10 seconds, and it did not go to the interrupt until it was done with that.. I made sure my first #use delay was above the ISR and the second above the main.

Thx,
Josh
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sun Jan 21, 2007 5:39 pm     Reply with quote

Can you post a very short, but complete program that shows the problem ?
Maybe just use one interrupt in this program. The shorter the program,
the better.
newguy



Joined: 24 Jun 2004
Posts: 1909

View user's profile Send private message

PostPosted: Sun Jan 21, 2007 6:05 pm     Reply with quote

joshkeys wrote:
Fair enough. That should work for this case.. but for the sake of being more flexible, do you know of anyway to use the delay_ms() command and still have interrupts active? Also, what is a list of commands that will disable interrupts? If you do any sort of loop, they do not seem to work, but for some reason, when I do my while(1) loop in my main program the interrupts will work fine, but if I use a while(!variable){} it does not seem to work. any ideas there?

Thx,
Josh


Think about what the processor is doing. Your program will have a main loop, like this:

Code:
while (TRUE) {
   if (eventa) {
      eventa = FALSE;
      service_eventa();
   }
   if (eventb) {
      eventb = FALSE;
      service_eventb();
   }
}


If you have some sort of while() loop in service_eventa(), the processor will sit in that loop as long as the test condition is true. Let's say that an interrupt occurs while it is sitting in this while loop - the processor will drop what it is doing (sitting in the loop), and run the interrupt service routine. That interrupt service routine will typically set a flag (eventb) to let the main loop know that something must be now be done.

Now the ISR is done, and code jumps back to where it was before the interrupt occured - which is sitting in the while loop.

Make sense now? If you want to be able to break out of a while loop, you'll have to add extra tests that indicate whether it should sit in the loop in the first place.

My personal advice is to avoid this type of coding style (while loops) as they unnecessarily tie up the processor and make it do, essentially, nothing while waiting for some event to occur. It's far better practice to code in such a way that the processor can react to events as quickly as possible. While() loops are bad practice using this type of coding style.
joshkeys



Joined: 16 Aug 2005
Posts: 37
Location: Fredericton,NB

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

Problem solved
PostPosted: Sun Jan 21, 2007 10:52 pm     Reply with quote

I enabled the interrupts in the function that the main program called and it worked fine.. My program has a while(1) loop that waits for a variable to be set from the ISR, which always worked, it was my "on" button. so when I pressed "on" the device came on.. with this variable set, the main called a function, and it was while in this function the interrupts would not work. So I added the enable interruptsxxxx to the function the main called and it worked.. weird.

Thx,
Josh
horkesley



Joined: 20 Feb 2007
Posts: 48
Location: Essex UK

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

int_rda during a while loop with delay
PostPosted: Tue Feb 20, 2007 9:43 am     Reply with quote

Hi,

I have a 'while loop' including a delay_ms(100)

I have a int_rda looking at the hardware comms.

When chars are received the global interrupt flag is reset and I only receive two chars.

If I remove the delay_ms it works fine.

Why cant I use int_rda when in a while loop?

Regards
_________________
Horkesley Electronics Limited
newguy



Joined: 24 Jun 2004
Posts: 1909

View user's profile Send private message

Re: int_rda during a while loop with delay
PostPosted: Tue Feb 20, 2007 10:06 am     Reply with quote

horkesley wrote:
Hi,

I have a 'while loop' including a delay_ms(100)

I have a int_rda looking at the hardware comms.

When chars are received the global interrupt flag is reset and I only receive two chars.

If I remove the delay_ms it works fine.

Why cant I use int_rda when in a while loop?

Regards


You can receive characters anytime. If you don't 'fetch' them from the USART, then you run into trouble. The USART can fetch & store two characters - that's it.

An interrupt (any interrupt) will cause the program to break out from a delay_ms() statement or a while() loop. It's what you do in the interrupt that determines how the program/processor behaves.

Alter your RDA interrupt to store each received character in an array and set a flag to let your main program know that something was received. If the program is 'twiddling its thumbs' in a delay_ms(100) (an eternity by the way), it will still successfully receive and store every serial character that comes its way. When the delay is done and program flow returns to the main while(true) {} loop of the main program, it will branch into the 'if (character_received) {} loop and your program can then analyze the received data and do whatever it is supposed to do with no missed characters.
treitmey



Joined: 23 Jan 2004
Posts: 1094
Location: Appleton,WI USA

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

PostPosted: Tue Feb 20, 2007 10:08 am     Reply with quote

If you only get 2 chars. I would say that it is your hardware usart filling up and you not reading the char to clear them out. This causes a error on the usart.
Do a search on uart and error for more info.
Tom Jetland



Joined: 23 Jun 2011
Posts: 31
Location: UK

View user's profile Send private message

Re: int_rda during a while loop with delay
PostPosted: Thu Aug 25, 2011 11:53 am     Reply with quote

Quote:

You can receive characters anytime. If you don't 'fetch' them from the USART, then you run into trouble. The USART can fetch & store two characters - that's it.

An interrupt (any interrupt) will cause the program to break out from a delay_ms() statement or a while() loop. It's what you do in the interrupt that determines how the program/processor behaves.


I don't think you are correct in saying this newguy. When my code is in a delay (which I try to avoid doing) the RDA_INT does not fire when data comes in.

Does anyone know why this is??
newguy



Joined: 24 Jun 2004
Posts: 1909

View user's profile Send private message

PostPosted: Thu Aug 25, 2011 12:04 pm     Reply with quote

Do you see any "interrupts disabled during calls to ... to prevent re-entrancy" warnings when you compile? If you're using delay_ms() functions inside and outside of ISRs, that would explain what you're seeing.
Tom Jetland



Joined: 23 Jun 2011
Posts: 31
Location: UK

View user's profile Send private message

PostPosted: Thu Aug 25, 2011 1:17 pm     Reply with quote

So are you saying that if a delay_ms is inside an interrupt (and compiler makes ints disabled to avoid re entrancy) that interrupts will be disabled even when it's not in an interrupt when using delay_ms?? That's bizarre!
newguy



Joined: 24 Jun 2004
Posts: 1909

View user's profile Send private message

PostPosted: Thu Aug 25, 2011 1:36 pm     Reply with quote

It's not bizarre. There is a delay_ms() function. If it is called both inside an ISR and outside of it, the compiler will disable interrupts during calls to it because there is only one function called delay_ms(). Imagine your code finds its way to the delay_ms() call that is outside of an ISR and while it is executing, the ISR with a call to delay_ms() is executed. What will happen? It's called re-entrancy and it's bad.

Alter your code to eliminate the delay call in your ISR - it's bad practice and is unnecessary. Failing that, you can fool the compiler into separating the two delay calls into separate bits of code by creating a my_delay_ms() function which calls delay_ms() inside of it.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2  Next
Page 1 of 2

 
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