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 support@ccsinfo.com

#int_rda when is it called?
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
arrow



Joined: 17 May 2005
Posts: 213

View user's profile Send private message

#int_rda when is it called?
PostPosted: Fri Jun 02, 2006 1:46 am     Reply with quote

Hi

I am currently using the
Code:

#int_rda


for several things.
Is this function called every time there is a write and a read to the UART?

Is there a way to have this intterupt only be executed when there is a write to the UART?

Thank you
a.
rberek



Joined: 10 Jan 2005
Posts: 207
Location: Ottawa, Canada

View user's profile Send private message

PostPosted: Fri Jun 02, 2006 3:52 am     Reply with quote

This is for RS232 receive data only. Since your code writes the data for the RS232, you always know when the write happens and the there is no need for an interrupt.
Ttelmah
Guest







PostPosted: Fri Jun 02, 2006 4:15 am     Reply with quote

There are two serial interrupts.
INT_RDA, does what it says. The 'RDA', stands for 'receive data available', and the interrupt occurs, _only_ when this is true.
Similarly, INT_TBE, stands for 'transmit buffer empty', and will occur only when _this_ is true (there is no character 'waiting' to be sent).
Hence, if you want to 'send' data, INT_TBE, is the one to use, with you transferring a character, to the UART, whenever this occurs, and you have data to send. For transmission, INT_RDA, does not enter the equation at all. However remember that unless the receive input of the UART is pulled high, 'dummy' characters may be seen, and a receive interupt occur.
Now there are caveats with both these interrupts. If you do not read the UART receive buffer, in int_RDA, the interrupt will continuously repeat, and then after another character arrives, the overrun error bit will become set. Once this is set, the UART will stop receiving, but unless the cause of the interrupt is cleared, it'll carry on occurring.
Similarly, when you have finished sending, the transmit buffer _will_ be empty, and so the TBE interrupt will continue repeating, till you send more data. This is why this is one of the few interrupts, where once your 'packet' is complete, it is necessary to disable the interrupt inside the handler, and then in the 'write' code, re-enable it, once data is available to send. There is also a caveat with 'starting' transmission, where the first character loaded, will immediately transfer into the output shift register,and the interrupt will occur again. This incurs an extra overhead at the start of transmission, but in general this is minor, and it will function OK, if this is ignored.

Best Wishes
arrowGuest
Guest







PostPosted: Fri Jun 02, 2006 5:07 am     Reply with quote

Hi Ttelmah

Thank you for your through explanation.
However, I still cannot solve my problem.
I have the following code snippets:

Code:

//***RS232 interrupt
#int_rda
void RS232(){
   ch = getc();
   if(ch == 36)
      canSend = true;
   if(ch == 42)
      canSend = false;
}
//==================================================
#int_timer2
void clock(){
    doA_D(2);
    newData = true;
}
//==================================================
main() {
   int icnt, val0, val1;
   //-------------------------------
   //***SETUP A_D
   setup_port_a( ALL_ANALOG );
   setup_adc( ADC_CLOCK_INTERNAL );
   //-------------------------------
   //***Setup time interrupts
   set_timer2(0);
   setup_timer_2(T2_DIV_BY_16,249,16);     
   enable_interrupts(INT_TIMER2);
   enable_interrupts(INT_RDA);
   enable_interrupts(GLOBAL);
   //-------------------------------
   //***Initialze
   icnt = 0;
   //-------------------------------
   //***Look for Sequence "$" to start data sending
   canSend=false;
    while(TRUE){
      while(canSend){
         if(newData){
            newData=false;
            val0 = icnt << 2;
            val0 = val0 | (Ch0>>8);
            val1 = icnt << 2;
            val1 = val1 | (Ch1>>8);
            printf("+%2x%2x -%2x%2x ", val0, Ch0, val1, Ch1);
            icnt++;
            if(icnt>60) icnt=0;
         }
      }
   }
 }


Now this code works well upon the START sequence (it listens for $
and when it sees it it starts the printf commands).
However once the data starts flowing, hitting "*" does not stop the data flow. ie the canSend is not set to FALSE.

Is the timer interrupt or the printf somehow getting mixed up with the int_rda?

Can you please tell me what I am doing wrong?
Thank you
a.
ckielstra



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

View user's profile Send private message

PostPosted: Fri Jun 02, 2006 8:29 am     Reply with quote

Can you post your #use rs232 line? My guess is you don't have the ERRORS directive, without this the UART blocks on receive buffer overflow.
Douglas Kennedy



Joined: 07 Sep 2003
Posts: 755
Location: Florida

View user's profile Send private message AIM Address

PostPosted: Fri Jun 02, 2006 9:12 am     Reply with quote

The asynchronous nature of RS232 can't be over stated.
The printf in the main loop will consume alot of time increasing the probablity that more than one character will be received while the printf does its thing. There is no provision to buffer characters nor is there any provision made for the probable overrun in your receive logic.
The way to avoid frustration with RS232 is to write a circular receive buffer with a depth approximating the number of characters your printf will output. With no circular buffer and with no flow control ( Xon Xoff or hardware CTS RTS)...you should almost always expect frustrating results.
arrow



Joined: 17 May 2005
Posts: 213

View user's profile Send private message

PostPosted: Sat Jun 03, 2006 2:32 am     Reply with quote

Hi Ckielstra and Douglas

My #users232 line looks like this:

Code:

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


So I do have the ERRORS flag in there.

As for the circular buffer: I am not sure why I need it.
I am receiving the written character and reading it with getc()
So the UART should not "lock"
Also I am comparing one value at a time- hence I am not sure why I need a circular buffer (btw I had also implemented a circular buffer in the past and that did not work either).

The main question is:
If during the printf command a character arrives, will an
int_rda occur? or will this incomming character be lost for ever?

Thank you
a.
arrow



Joined: 17 May 2005
Posts: 213

View user's profile Send private message

PostPosted: Sat Jun 03, 2006 2:37 am     Reply with quote

Hi

Can someone please tell me how to clear the
bit when an error occurs upon receiving a character from the UART?

Thank you
a.
arrow



Joined: 17 May 2005
Posts: 213

View user's profile Send private message

PostPosted: Sat Jun 03, 2006 3:48 am     Reply with quote

Hi

I have put a
printf("hello\n");
just after the getc();
command in the int_rda subroutine.

When I run the PIC I see that the int_rda is being triggered continously (i.e. hello is printed to hyperterminal repeatedly). Nothing is being sent to the PIC so I am perplexed as to why the int_rda is being triggered.

Can anyone please help on this?
Thank you
a.
rberek



Joined: 10 Jan 2005
Posts: 207
Location: Ottawa, Canada

View user's profile Send private message

PostPosted: Sat Jun 03, 2006 5:34 am     Reply with quote

Well, the printf statement is sending out 6 characters at the same rate as you are receiving them. This means the interrupt goes off when you get a character, you go into the routine, read the incoming character, then print 6 characters. While you are printing them, you are missing and losing incoming characters. The receive buffer can really only hold two characters. Should you not read the receive buffer fast enough, as in this case, you will lose characters, including your $ and * characters which control how you start and stop reading your data (which look like they are NMEA sentences).

r.b.
ckielstra



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

View user's profile Send private message

PostPosted: Sat Jun 03, 2006 7:33 am     Reply with quote

Quote:
The main question is:
If during the printf command a character arrives, will an
int_rda occur? or will this incomming character be lost for ever?
You didn't mention the processor you are using, but on a PIC18F458 the interrupt flag will stay active as long as not all data received by the UART is taken from the receive buffer. The UART's receive buffer is only 2 bytes long so after reception of the 3rd byte an buffer overflow occurs and the UART stops receiving.

Quote:
Can someone please tell me how to clear the
bit when an error occurs upon receiving a character from the UART?
If you have the ERRORS directive in the #use RS232 line you can reset the UART overflow bit just by calling getc(). If you want do it manually you can reset the Overrun Error bit (OERR) by clearing bit CREN (and then re-activate the UART again by setting CREN again).
ckielstra



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

View user's profile Send private message

PostPosted: Sat Jun 03, 2006 7:45 am     Reply with quote

arrow wrote:
Hi

I have put a
printf("hello\n");
just after the getc();
command in the int_rda subroutine.

When I run the PIC I see that the int_rda is being triggered continously (i.e. hello is printed to hyperterminal repeatedly). Nothing is being sent to the PIC so I am perplexed as to why the int_rda is being triggered.

Can anyone please help on this?
This is very strange and can't be explained by a UART buffer overflow, sounds more like a hardware problem. You didn't give us a complete program, neither did you mention your processor type and compiler version so I can't try to simulate your problem.

One more test you can do is to replace the printf("hello") by a printf of the just received character, maybe it then makes sense to you as to where the received data is comming from.
Douglas Kennedy



Joined: 07 Sep 2003
Posts: 755
Location: Florida

View user's profile Send private message AIM Address

PostPosted: Sat Jun 03, 2006 12:31 pm     Reply with quote

Well you can ponder as much as you want but if it is NMEA sentences you wish to receive sucessfullly you'll eventually turn to a circular buffer.
A circular buffer will most often help you with debugging since it will show the last many chars you received not just the last one.
This is not to discourage you from trying another approach for everyone learns more from their own errors than from borrowing code from others.
PC's with RS232 use circular buffers sometimes several thousand characters deep. The PIC hardware buffer is only 2 deep..the last byte fully received and the one coming in. To catch more than 3 bytes coming in sequentially and do printfs and other things without an interrupt driven buffer will be a fun challenge for you. Good luck.
arrow



Joined: 17 May 2005
Posts: 213

View user's profile Send private message

PostPosted: Mon Jun 05, 2006 12:21 am     Reply with quote

Hi

Thank you for all your replies.

I am using the 16LF873 PIC.
I have put in a printf(ch)
where ch = getc();
And what comes out looks like garbage.

I am NOT working with NMEA- rather with a BlueTooth modem.
I dont think I need a circular buffer since I only need to detect 2 or maximum 3 key presses.

If I have a printf command (as I do in the main program),
and if I get a charcter sent over the RS232 line- will the int_rda be
triggered even if the PIC is executing the printf command?

Thank you
a.
Mark



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

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

PostPosted: Mon Jun 05, 2006 11:33 am     Reply with quote

Yes so long as you don't call printf from an interrupt.
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