![](templates/subSilver/images/CCSLogo.jpg) |
![CCS C Software and Maintenance Offers](templates/subSilver/images/forumAd6.jpg) |
View previous topic :: View next topic |
Author |
Message |
Sensor
Joined: 04 Nov 2004 Posts: 33
|
Problem with #int_RDA |
Posted: Wed Jun 07, 2006 9:51 am |
|
|
PIC = 16F627A
Compiler = PCWH version 3.236
Target Voltage = 5V
Oscillator = 4MHz
I am trying to get two 16F627A's to talk back and forth using their UARTS. Everything works fine until I remove the two statements from my interrupt:
Code: | lcd_clear();
printf(lcd_putch, "Got %S", received_string); |
If I keep those two statements in, everything works fine. I am using the LCD for debug purposes only, so in the end, I will not want those statements. Why does removing the LCD code mess things up? Is there a way to get around this?
Here is the rest of my code. I rewrote the get_string() function from INPUT.C and named the function get_str():
Code: |
#include <16F627A.h>
#use delay(clock=4000000)
#use rs232(baud=9600,parity=N,xmit=PIN_B2,rcv=PIN_B1,bits=8,errors)
#FUSES NOWDT,INTRC_IO,PUT,NOPROTECT,BROWNOUT,NOMCLR,NOLVP,NOCPD
#include "get_string.c"
#include "project_defs_new.h"
#include "string.h"
#include "lcd_driver.c"
#define STRING_SIZE 32
char received_string[STRING_SIZE];
char sat_119[32];
char sat_110[32];
char sat_101[32];
#int_RDA
void RDA_isr(void)
{
get_str(received_string, STRING_SIZE); // transmitted string must have a '\r' or get_str will fail
//want to remove these two lines
lcd_clear();
printf(lcd_putch, "Got %S", received_string);
}
void main()
{
disable_interrupts(GLOBAL);
lcd_init();
enable_interrupts(INT_RDA);
enable_interrupts(GLOBAL);
strcpy(sat_119,"119");
strcpy(sat_110,"110");
strcpy(sat_101,"101");
while(TRUE)
{
if(strcmp(received_string,sat_119)==0){
LED2_On;
LED1_Off;
disable_interrupts(INT_RDA);
printf("Got\r");
enable_interrupts(INT_RDA);
strcpy(received_string, "OK"); //change received string so only get in if statement once
}
if(strcmp(received_string,sat_110)==0){
LED1_On;
LED2_Off;
disable_interrupts(INT_RDA);
printf("Got\r");
enable_interrupts(INT_RDA);
strcpy(received_string, "OK");
}
if(strcmp(received_string,sat_101)==0){
LED1_On;
LED2_On;
disable_interrupts(INT_RDA);
printf("Received\r");
enable_interrupts(INT_RDA);
strcpy(received_string, "OK");
}
}
}
//Get string function
void get_str(char* s, int max)
{
int len;
char c;
--max;
len = 0;
while(c != 13) // 13 equals ASCII Caraige Return \r
{
c = getc();
if(c != 13){ //terminates on carriage return
if(len<max)
s[len++] = c;
}
}
s[len] = 0;
}
|
|
|
![](templates/subSilver/images/spacer.gif) |
jecottrell
Joined: 16 Jan 2005 Posts: 559 Location: Tucson, AZ
|
|
Posted: Wed Jun 07, 2006 10:20 am |
|
|
Try replacing the LCD lines with a delay. I have a feeling the LCD lines are acting as a delay and allowing the full string to arrive. Once you remove them the interrupt fires on the first character and you lose the rest?
The delay is a suggestion for debugging and not the recommended solution. The experts will probably be able to give the elegant solution.
Just a WAG.
John |
|
![](templates/subSilver/images/spacer.gif) |
rnielsen
Joined: 23 Sep 2003 Posts: 852 Location: Utah
|
|
Posted: Wed Jun 07, 2006 10:25 am |
|
|
First, puting function calls, inside an ISR, is an extremely bad idea. ISR's should be as short as possible since nothing else can happen while it has control. Never, ever put a while() inside one either. You want the ISR to be entered, shatch the character and then get out. Don't have the program setting in there waiting for a condition to be met. If you need to, read the character, evaluate it and if it meets what you're looking for then stuff it someplace to be manipulated later in the main(), or a different routine. If it doesn't meet what you're looking for then bail out.
Inside your ISR you are evaluating 'c', inside your while(), before it's even assigned a value. Re-think what you want to do and try again. Make is as simple as possible first, then add more stuff until you have what you want to end up with.
Ronald |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah Guest
|
|
Posted: Wed Jun 07, 2006 10:28 am |
|
|
If you are bothering to use interrupts, then don't waste the effort, and have the code sit inside the interrupt handler waiting for a string. When an interrupt occurs, there is _one_ character waiting to read. Read this, and let the processor get on with other things, or you might as well simply 'poll' for received data in the main loop.
I'd suspect the problem is 'c'.
You declare this in the subroutine inside the interrupt handler, _but do not initialise it_. Hence unless it is overwritten, the next time this routine is called, it'll contain the last value used. After one pass through the get_str function, it'll contain the eol character, so the while loop will never execute. Now 'local' values, can be overwritten by other routines called from the same 'master' routine. So what is happening, is that the lcd code, results in this being overwritten, and the code once more executing OK.
So, either initialise 'c' (as you do with len), or reverse the logic of the loop, and use a 'do...while', so the test is executed at the end of the loop.
Best Wishes |
|
![](templates/subSilver/images/spacer.gif) |
Guest
|
|
Posted: Wed Jun 07, 2006 12:40 pm |
|
|
Initializing 'c' fixed the problem.
So, instead of using an interrupt, should I just constantly check kbhit(), and if kbhit() = 1 then jump into my get_str() routine?
Thanks for the help |
|
![](templates/subSilver/images/spacer.gif) |
Mark
Joined: 07 Sep 2003 Posts: 2838 Location: Atlanta, GA
|
|
Posted: Wed Jun 07, 2006 2:28 pm |
|
|
Anonymous wrote: | Initializing 'c' fixed the problem.
So, instead of using an interrupt, should I just constantly check kbhit(), and if kbhit() = 1 then jump into my get_str() routine?
Thanks for the help |
I would receive the data into a buffer. When you receive the EOL character then set a flag and process the data. |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah Guest
|
|
Posted: Wed Jun 07, 2006 2:33 pm |
|
|
It is important to understand what an interrupt is 'for'. It allows asynchronous events, to call a routine, _but_ brings with it a significant overhead. There are about 70+ instructions of overhead associated with having an interrupt handler. Now if (for instance), you wanted the processor to be getting on with other jobs (polling a keyboard, updating I/O, and sending messages etc.), while you wait for a message, the interrupts are the way to go, but you then use the full ability of the interrupt, just transfer _one_ charater when the interrupt is called, and set a 'flag' when the terminator character is seen. The main code can then get on doing the other jobs, and just stop these when the flag is set. However as currently coded, you do nothing else while waiting for the message, hence you might as well get rid of the interrupts, and just dothe work in a polled loop. At the start of your 'while', look for a kbhit, and then when this is seen, call your get_str function. The result will be the same as your current code...
In general, interrupts using the 'per character' solution, are more likely to be the 'right' solution, since you can then have the code doing other things. As it currently stands, you are using interrupts, but ghaining nothing from them.
Best Wishes |
|
![](templates/subSilver/images/spacer.gif) |
|
|
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
|