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 with #int_RDA

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



Joined: 04 Nov 2004
Posts: 33

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

Problem with #int_RDA
PostPosted: Wed Jun 07, 2006 9:51 am     Reply with quote

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;   
}   
jecottrell



Joined: 16 Jan 2005
Posts: 559
Location: Tucson, AZ

View user's profile Send private message

PostPosted: Wed Jun 07, 2006 10:20 am     Reply with quote

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
rnielsen



Joined: 23 Sep 2003
Posts: 852
Location: Utah

View user's profile Send private message

PostPosted: Wed Jun 07, 2006 10:25 am     Reply with quote

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
Ttelmah
Guest







PostPosted: Wed Jun 07, 2006 10:28 am     Reply with quote

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
Guest








PostPosted: Wed Jun 07, 2006 12:40 pm     Reply with quote

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
Mark



Joined: 07 Sep 2003
Posts: 2838
Location: Atlanta, GA

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

PostPosted: Wed Jun 07, 2006 2:28 pm     Reply with quote

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.
Ttelmah
Guest







PostPosted: Wed Jun 07, 2006 2:33 pm     Reply with quote

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