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

help with int_rda

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







help with int_rda
PostPosted: Sat Dec 16, 2006 2:46 am     Reply with quote

Hi forum

I need some help regarding the serial interrupt int_rda. I am using 18f452 and compiler version is 3.249.

I want to receive 20 characters on through serial interrupt, but i dont want the normal code to run during the receival of these 20 characters. But i still need to use interrupts because the data might come at any time. The problem is that i keep missing characters when the normal code is running and serial interrupt begin generated. I am using a 20mhz crystal and baud rate is 19200.

best Regards
kender



Joined: 09 Aug 2004
Posts: 768
Location: Silicon Valley

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

Re: help with int_rda
PostPosted: Sat Dec 16, 2006 2:56 am     Reply with quote

new guy wrote:
The problem is that i keep missing characters when the normal code is running and serial interrupt begin generated.

Generally, this shouldn't be happening, because the ISR runs independently of the main() loop. Does you main() disable interrupts? The problem could lie in the ISR itself: if the ISR is lond and it can't service the receipt of a character before the next character arrives, you will eventually start loosing characters. If you post your ISR, may be we can spot the problem.


Last edited by kender on Sat Dec 16, 2006 5:46 pm; edited 1 time in total
new guy
Guest







PostPosted: Sat Dec 16, 2006 3:12 am     Reply with quote

here is the ISR:

Code:


void rstprocess()
{
      do
      {
          write_ext_eeprom(writeadd,buffer[qindex]);  //overwrites memory with the new string

          qindex++;

          writeadd++;

      }while(buffer[qindex] != '!');

      write_ext_eeprom(writeadd,buffer[qindex]);  //overwrites memory with the new string

      fprintf(pc,"\n\rRESETTING SYSTEM !!\n\r");

      glcd_fillScreen(OFF);

      glcd_text57(8, 28, textmsg3, 2, ON);

      fputc('R',con1);  //send reset signal to UC1

      do
      {
         despo = fgetc(con1);  //wait for lrf to reach 0 degrees

         fprintf(pc,"\n\rGOT SIGNAL:%c",despo);

      }while(despo != 'R');

      windex = 0;

      despo = 0;

      reset_cpu();  //reset the cpu after writing string into EEPROM

}




#int_rda
void serial_isr()
{
    despo = fgetc(special);

    buffer[windex] = despo;

    windex++;

    if(despo == '!')  //so configuration string received completely
    {
      rstprocess();
    }

}
kender



Joined: 09 Aug 2004
Posts: 768
Location: Silicon Valley

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

PostPosted: Sat Dec 16, 2006 5:19 pm     Reply with quote

You're obviously trying to do too much in the ISR. Probably, what gets you the most is the serial writes inside ISR. ISR should store the received character in the buffer, set some flags, increment some counters and exit immediately. Processing of and reaction to the incoming data should be left to the main(), with the exception for the cases, when the fast reaction to the interrupt is of paramount importance.

Sorry, I've been looking at your code for only about 20 sec. Will write more later.
Andreas



Joined: 25 Oct 2004
Posts: 136

View user's profile Send private message

ISR
PostPosted: Sun Dec 17, 2006 3:20 am     Reply with quote

Hi,

As the last post already said, keep the ISR as short as possible !!

Usually I am doing a simple state machine in the main for reacting and having only some flags set in the isr, so you will never miss one character !

best regards
Andreas
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Sun Dec 17, 2006 9:06 am     Reply with quote

I agree that an ISR should be as short as possible, but that's the case here except for one special condition where reception of a '!' character marks the end of message. This special case takes extreme long but then resets the processor, so no need to care about the long processing. I don't think this is a very elegant implementation and it might introduce other problems but it is not related to the missing of characters.

Most likely there is something in your main loop disabling the interrupts, either some code written by you or a compiler internal library function. For example, are you using a software RS232 driver with the DISABLE_INTS function?
Ttelmah
Guest







PostPosted: Sun Dec 17, 2006 10:34 am     Reply with quote

I'd suspect the problem relates to how many functions exist in 'rstprocess'. All functions used here, will result in the interrupts being disabled in the main code if they are used outside the interrupt. Since this includes things like LCD I/O, and serial I/O, soem quite long periods with the interrupt disabled are likely. Some GLCD functions (like clearing the screen), can take a significant time, so having the interrupts enabled outside, could easily result in characters being missed.

Best Wishes
new guy
Guest







PostPosted: Mon Dec 18, 2006 6:08 am     Reply with quote

Hi all

Thank you for all your replies. but the problem still remains.after much trouble i have been able to identify exactly where the problem lies. First of all my hardware configuration:

PIC18f452
20Mhz crystal
Compiler version 3.249

I am using serial interrupt INT_RDA. PIN C7 is pulled up. I am sending serial data through my computer and i want the serial interrupt subroutine to store that data into an array. The problem is that e.g if i enter '$ROTOS' from the hyperterminal then only $R is registered. If i sent '$' and wait for about one second and then sent 'ROTOS' then all the data is registered satisfactorily. I got to know that by getting data in serial interrupt and then printing it back on the computer immediately. Once the data appears i send the next character. After this occurance of controller getting lost somewhere after getting '$' then the int_rda works fine no matter how quickly i enter the data. So only intially the controller gets stuck somewhere. Here is my ISR

Code:


#use rs232(baud=19200,xmit=PIN_C6,rcv=PIN_C7,ERRORS,stream=special) 


#int_rda
void serial_isr()
{
   
     do
     {   
        cra = fgetc(special);
       
        fputc(cra,pc);
 
     }while(cra != 13);     


}


Just to recap: once i enter the first character, it is printed back on pc after 1 second, but all subsequent characters (after this delay) are echoed back immediated. During this delay of 1second any charactes entered are lost some where. What i want to know is that what is causing this delay.

Kind regards
Douglas Kennedy



Joined: 07 Sep 2003
Posts: 755
Location: Florida

View user's profile Send private message AIM Address

PostPosted: Mon Dec 18, 2006 7:45 am     Reply with quote

Many have a lot of grieve when it comes to #int rda. Read all that has been written on this board about int #RDA.
The interrupt is called each and every time a single char is received. You do violence to this by putting a do while in the interrupt. By doing this you completely defeat the purpose of the interrupt forcing it to wait in the interrupt until the final char is received. The first char is triggers your interrupt then no other incoming char is allowed to use the interrupt because your do loop doesn't allow the interrupt to exit after one char is received.
Read all you can about the interrupt and start over with your isr design.
Ttelmah
Guest







PostPosted: Mon Dec 18, 2006 7:50 am     Reply with quote

First, echoing back like this, is a pretty sure way of losing characters. The reason is that you are echoing on another stream, and since there is only one hardware UART, this will involve the code in being unable to respond to the serial interrupt for a character time. Second though, the main fault is almost certainly in the code outside the interrupt. If (for instance), there is any output to the same stream as is now being used in the interrupt for output, this will result in the interrupts being disabled, and further problems.
Now, let me post a larger program than is 'normal' for me, but this shows the sort of code needed to do what you want:
Code:

#include <18F452.h>
#FUSES NOWDT, WDT128, HS, NOPROTECT, NOOSCSEN, BROWNOUT, BORV42, PUT, STVREN, NODEBUG, NOLVP, NOWRT, NOWRTD, NOWRTB, NOWRTC, NOCPD, NOCPB, NOEBTR, NOEBTRB
#use delay(clock=20000000)
#use rs232(baud=19200,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8,errors)

//Buffer tests and handling
#define isempty(buff,in,out,size) (in==out)
#define hasdata(buff,in,out,size) (in!=out)
#define isfull(buff,in,out,size) (((in+1)&(size-1))==out)
#define tobuff(buff,in,out,size,chr) { buff[in]=chr;\
   in=((in+1) & (size-1));\
   if (in==out) out=((out+1) & (size-1));\
   }
#define frombuff(buff,in,out,size) (btemp=buff[out],\
   out=(out+1) & (size-1), \
   btemp)
#define ifrombuff(buff,in,out,size) (ibtemp=buff[out],\
   out=(out+1) & (size-1), \
   ibtemp)
#define clrbuff(buff,in,out,size) {in=0;\
   out=0;}

//buffer size - must be a binary size for the code as posted
#define SRBUFF (16)
int8 RSRbuff[SRBUFF],RSRin,RSRout;

#INT_RDA /* RS232 'receive' interrupt */
void RXINT(void)
{
   tobuff(RSRbuff,RSRin,RSRout,SRBUFF,getc());
}

void main(void) {
   int8 input_message[20], ctr=0, temp;
   setup_counters(RTCC_INTERNAL,WDT_OFF);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DISABLED);
   setup_ccp1(CCP_OFF);
   setup_ccp2(CCP_OFF);
   setup_adc(ADC_OFF);
   clrbuff(RSRbuff,RSRin,RSRout,SRBUFF);
   CLEAR_INTERRUPTS(INT_RDA);
   ENABLE_INTERRUPTS(INT_RDA);      /* Rx data */
   ENABLE_INTERRUPTS(GLOBAL);
   while (TRUE) {
      while (isempty(RSRbuff,RSRin,RSRout,SRBUFF)) {
         //Here do stuff while waiting for the serial

      }
      //Here a character is ready.
      temp=frombuff(RSRbuff,RSRin,RSRout,SRBUFF);
      if (temp=='$') {
          //Here have first character
          ctr=0;
      }
      input_message[ctr++]=temp;
      if (ctr==19 || temp==13) {
          //Here either a line feed, or buffer is full
          input_message[ctr]=0; //null terminate string
          printf("%s",input_message);  //send to whatever output you want
          ctr=0; //prevent buffer overrun
      }
   }


This will send back the entire received string, when it is completed (either buffer is full, or linefeed is seen). The input will be stored in the array 'input_message', starting with the $ character.

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