View previous topic :: View next topic |
Author |
Message |
arrow
Joined: 17 May 2005 Posts: 213
|
#int_rda when is it called? |
Posted: Fri Jun 02, 2006 1:46 am |
|
|
Hi
I am currently using the
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
|
|
Posted: Fri Jun 02, 2006 3:52 am |
|
|
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
|
|
Posted: Fri Jun 02, 2006 4:15 am |
|
|
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
|
|
Posted: Fri Jun 02, 2006 5:07 am |
|
|
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
|
|
Posted: Fri Jun 02, 2006 8:29 am |
|
|
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
|
|
Posted: Fri Jun 02, 2006 9:12 am |
|
|
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
|
|
Posted: Sat Jun 03, 2006 2:32 am |
|
|
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
|
|
Posted: Sat Jun 03, 2006 2:37 am |
|
|
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
|
|
Posted: Sat Jun 03, 2006 3:48 am |
|
|
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
|
|
Posted: Sat Jun 03, 2006 5:34 am |
|
|
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
|
|
Posted: Sat Jun 03, 2006 7:33 am |
|
|
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
|
|
Posted: Sat Jun 03, 2006 7:45 am |
|
|
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
|
|
Posted: Sat Jun 03, 2006 12:31 pm |
|
|
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
|
|
Posted: Mon Jun 05, 2006 12:21 am |
|
|
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
|
|
Posted: Mon Jun 05, 2006 11:33 am |
|
|
Yes so long as you don't call printf from an interrupt. |
|
|
|