|
|
View previous topic :: View next topic |
Author |
Message |
virtuosa
Joined: 19 Jan 2014 Posts: 7
|
INT_RDA not firing off. |
Posted: Tue Jan 21, 2014 12:06 pm |
|
|
Hi,
I realise this seems to be a semi-common problem as I have seen others who have had it, however I have tried applying some of the fixes to no avail.
Currently my RX_ISR seems to not do anything. I was trying to check if it was indeed firing off, but I couldn't see any data in RCREG2 in the debug mode.
I have simplified the program to reproduce the issue below:
Code: |
#include <C:\Program Files\PICC\Devices\18F25J11.h>
#use delay(clock=8M,int=2M)
#fuses HS,NOWDT,INTRC,NOPROTECT,NOIOL1WAY
#PIN_SELECT RX2=PIN_C5
#PIN_SELECT TX2=PIN_C4
#use rs232(uart1,baud=9600,bits=8,stream=PC,ERRORS)
#use rs232(uart2,baud=9600,bits=8,stream=XB,ERRORS)
#define RX_SIZE 64
char temp='\0';
short rx_flag = 0;
#INT_RDA
void RX_ISR(){
//printf(XB,"RXISR\r\n");
temp=getc();
rx_flag=1;
}
int main(){
//clear_interrupt(INT_RDA);
enable_interrupts(INT_RDA);
enable_interrupts(GLOBAL);
delay_ms(2);
delay_ms(100);
int cycle=0;
printf("start");
rx_flag=0;
while(1){
if(rx_flag)
putc(temp);
delay_ms(2000);
//fprintf(XB, "the value of flag is %d",rx_flag);
//fputc(fgetc(XB)+1,XB);
rx_flag=0;
}
return 0;
}
|
The fputc(fgetc()) line works fine, and shows me the characters incremented by 1 however when commenting this out and running the main loop with only the flag checker no output is present.
The printf which shows the value of the flag takes whatever value the flag is set to in the ISR for the first time it executes, after that it just remains at 0 for the rest of the time.
Nevertheless this problem has had me stumped for a while now! If anyone could shed some light with respect to this I would be very grateful.
Many thanks |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue Jan 21, 2014 12:37 pm |
|
|
Quote: | but I couldn't see any data in RCREG2 in the debug mode. |
You setup streams, but then you don't use streams. You are using getc()
inside the interrupt routine, instead of fgetc(), with the stream specified
as the parameter.
Also, there are two UARTs, so there are two different #int_xxxx specifiers
to identify which interrupt is assigned to the isr. You should look at the
end of the 18F25J11.h file and see which one to use for UART #1 and
which one to use for UART #2. Also, the same thing is true for the
enable_interrupts() function.
Your major problem is you don't understand that using the 2nd UART
requires setting up the code to use that 2nd UART. Currently, you are
setting almost everything up for the 1st UART. |
|
|
C Turner
Joined: 10 Nov 2003 Posts: 40 Location: Utah
|
|
Posted: Tue Jan 21, 2014 4:20 pm |
|
|
I see that you are using the flag "rx_flag" to indicate when a character is ready.
In your main() function, you haven't included the reset of that flag within the conditional statement so that it happens only once. Ignoring the point about streams/UARTs made above in this example, you need to set up a simple state machine like:
if(rx_flag) {
rx_flag = 0; // Clear the flag only ONCE and ONLY if the flag was set
putc(temp); // We do something that that received character.
}
This way, you can also get rid of that delay_ms(2000) statement and the above will spit out (echo) characters as fast as they come in rather than just one character every other second.
Whatever you do, it would probably be better if you handled string buffers in your ISR(s) rather than single characters as the former would relieve the rest of your code from having to be able to service the single-character buffer any time a character came in! In most cases, circular buffers are the most convenient - particularly if their size is 2^N characters.
(You did say that this was a "simple" test program, though...)
CT |
|
|
virtuosa
Joined: 19 Jan 2014 Posts: 7
|
|
Posted: Tue Jan 21, 2014 7:47 pm |
|
|
PCM programmer, I agree with you that it is confusing in the way I have put it. The preprocessor set up should be fine right? If I am to understand what you were saying its simply that using getc() isn't as well defined as I think it is. In this case, is it always safest to use fgetc/fputc/fprintf etc when dealing with multiple UARTs?
I took the int_rda from the CCS help manual, however looking in the header file perhaps the manual was a bit misleading? The manual said that int_rda is a general interrupt whenever any data had been received (I could well be wrong on this though). Looking in the header file, there is an INT_RDA and INT_RDA2 which I assume might be for each UART. I will experiment with using INT_RDA2 and getting all the streams correct tomorrow, hopefully the problem is something simple like that, so thank you for the insight.
C Turner, My program is a very simple one as you mentioned, but you are completely right about it being more efficient by resetting the flag in the flag_checker. My plan was just to grab the char from the UART when each interrupt was received and place them into a buffer (which I removed just to make it simpler). This should hopefully make the ISR short and not cause as many issues later. Hopefully this should be valid once the ISR starts grabbing the chars.
I will post an update tomorrow on any progress/the solution hopefully.
Thank you for your replies guys. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19539
|
|
Posted: Wed Jan 22, 2014 1:24 am |
|
|
If you have multiple #use rs232 statements, getc/putc, without a stream name access the last statement.
So in your case, INT_RDA triggers, to say that UART1 has a character, and then tries to read from UART2 (which doesn't necessarily have a character), so will hang.
Result no operation.....
If something does arrive on UART2, this is then read, and INT_RDA will try to exit, but immediately be called again, since UART1 still has a character. Hang again...
INT_RDA, is the UART1 data received interrupt.
INT_RDA2, is for UART2.
Once multiple UARTs are used, you have to get the interrupt selection, and streams 'right'.
Best Wishes |
|
|
virtuosa
Joined: 19 Jan 2014 Posts: 7
|
|
Posted: Wed Jan 22, 2014 11:52 am |
|
|
Ttelmah, PCM Programmer, you were both spot on I think. I have adjusted my code with your updates and made a simple program below which may be useful if someone else comes across this.
Ttelmah, thank you for the breakdown on how the UART streams work, I will be sure to bear this in mind in the future so hopefully I won't be duped by this again.
Code: |
#include <C:\Program Files\PICC\Devices\18F25J11.h>
#use delay(clock=8M,int=2M)
#fuses HS,NOWDT,INTRC,NOPROTECT,NOIOL1WAY
#PIN_SELECT RX2=PIN_C5
#PIN_SELECT TX2=PIN_C4
#use rs232(uart1,baud=9600,bits=8,stream=PC,ERRORS)
#use rs232(uart2,baud=9600,bits=8,stream=XB,ERRORS)
char RX1temp='\0';
char RX2temp='\0';
short rx1_flag = 0;
short rx2_flag = 0;
#INT_RDA
void RX1_ISR(){
RX1temp=fgetc(PC);
rx1_flag=1;
}
#INT_RDA2
void RX2_ISR(){
RX2temp=fgetc(XB);
rx2_flag=1;
}
int main(){
clear_interrupt(INT_RDA);
enable_interrupts(INT_RDA);
clear_interrupt(INT_RDA2);
enable_interrupts(INT_RDA2);
enable_interrupts(GLOBAL);
delay_ms(2);
delay_ms(100);
rx1_flag=0;
rx2_flag=0;
while(1){
if(rx1_flag){
//fprintf(PC, "the value of flag is %d\r\n",rx1_flag);
fputc(RX1temp,PC);
rx1_flag=0;
}
if(rx2_flag){
// fprintf(XB, "the value of flag is %d\r\n",rx2_flag);
fputc(RX2temp,XB);
rx2_flag=0;
}
}
return 0;
}
|
Thank you very much for your help and advice everyone. |
|
|
|
|
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
|