|
|
View previous topic :: View next topic |
Author |
Message |
vinims
Joined: 31 Jan 2005 Posts: 3
|
Problems with rs232 interruption |
Posted: Mon Jan 31, 2005 5:57 am |
|
|
Hi,
I wrote this code:
*************************************************************
#include "16F627.H"
#fuses XT, NOWDT, NOPROTECT, NOMCLR, NOBROWNOUT, NOLVP, NOCPD, PUT
#use delay (clock=3686400) //3.6864mHz
#use rs232(baud=115200, xmit=PIN_B2, rcv=PIN_B1, parity=N, bits=8)
//Functions definitions
void initPins(void);
void blinkLed(void);
#int_rda
void rs232_handler()
{
blinkLed();
}
void main()
{
initPins();
enable_interrupts(global);
enable_interrupts(int_rda);
while(1);
}
void initPins()
{
SET_TRIS_A(0xB0);
SET_TRIS_B(0x32);
setup_ccp1(CCP_OFF);
setup_comparator(NC_NC_NC_NC);
setup_vref(FALSE);
output_low(PIN_A0);
output_low(PIN_A1);
output_low(PIN_A2);
output_low(PIN_A3);
output_low(PIN_B0);
}
void blinkLed()
{
int cont = 5;
while (cont)
{
output_high(PIN_A0); //LED on
delay_ms(200);
output_low(PIN_A0); //LED off
delay_ms(200);
cont--;
}
}
*************************************************************
When I compile does not return error, but when I run the program and send a char through of rs232, the program not execute the function blinkLed() one time, but it seems that the function enters in loop.
Somebody would know to say me what it can be wrong?
Hmmm... forgive me for my english
Vinicius |
|
|
Douglas Kennedy
Joined: 07 Sep 2003 Posts: 755 Location: Florida
|
|
Posted: Mon Jan 31, 2005 6:36 am |
|
|
The problem is time is not on your programs side.
Each received char will cause your interrupt service routine to execute..but guess what ...you call blink led that has a delay in it ..that's because you wanted to see it blink. While it is blinking the service routine is frozen out and that's likely to be the problem.
Suggestion
Set a global flag in the interrupt service routine to indicate a char is received. In your main code blink the led if the flag is set and clear the flag after one blink.
That way the isr can be called during the blinking of the led..sure it will add a few micro secs to the blink as the isr consumes a few cycles but it won't hang your code. |
|
|
Mark
Joined: 07 Sep 2003 Posts: 2838 Location: Atlanta, GA
|
|
Posted: Mon Jan 31, 2005 7:04 am |
|
|
You should add the ERRORS parameter to the #use rs232 also. |
|
|
valemike Guest
|
|
Posted: Mon Jan 31, 2005 7:05 am |
|
|
I have an application right now where i have a 4 digit LED display, and I have to strobe thru each digit for 4ms, then go to the next digit, etc., to make it appear continuous to the human eye.
In my loop I noticed that other interrupts and i/o cause a disruption in the continuous display.
What i'm going to try to do is to use TMR0 (?), set it to interrupt me every 4ms, then update the next digit in the ISR.
In your case, instead of your calll to delay_ms(200), perhaps you should set a timer to interrupt you every 200ms (you'll need to calculate that based on your Fosc speed), and update that LED in the ISR.
-Mike |
|
|
Bill Boucher
Joined: 04 Feb 2005 Posts: 34 Location: Chatham,ON,CA
|
|
Posted: Fri Feb 04, 2005 1:43 pm |
|
|
If your program enters an endless loop, it sounds like the ISR is reentering itself. Try clearing the interupt flag within your ISR. I'm a newbie to CCS C so I'm not sure if it clears the flags automatically, but I doubt it. It will reassert GIE upon exiting the ISR, but it doesn't likely clear the int-source flags!
Also, your "blink" routine is time consuming. You wouldn't be able to "receive" again until that's done. Obviously, it blinks for you to say "Hey, I received a byte!!!". That's just fine for your first try at serial communications. Later, you'll want to keep your ISR short and sweet, say dedicated to moving data received into a user defined receive buffer variable [i.e. R_buffer(n)]. The ISR could load a var with a number. The main loop could be checking that number and if not 0, then blink that many times. No matter how slow the blink, the ISR will still run once for each byte received. Alternatively, the suggestion from valemike regarding setting the blink timing with a hardware timer is excellent. While this could be easily interupt driven (just like serial reception is), it isn't mandatory. I often use the TMR0 or TMR1 to regulate my main loop speed without triggering an interupt. All you do is wait at the bottom of the main loop for the timer flag bit to become set. When it does, you clear it, re-load the timer with a constant that sets your loop speed, then jump back to the beginning of the loop. For each pass through the main loop, you decrement a counter or something to determine when it is time to change the state of the LED. The advantage here is that the LED blinking doesn't lock the uC into delay loops so it can perform other tasks while blinking. |
|
|
|
|
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
|