|
|
View previous topic :: View next topic |
Author |
Message |
akshaymathur39
Joined: 05 Aug 2008 Posts: 11
|
#INT_RDA interrupt problem |
Posted: Sun Oct 04, 2009 1:33 am |
|
|
Hi,
I am trying to configure my PIC18F2550 for receiving GPS data.
I figured out that the external interrupts are working fine but the serial interrupt is not working at all. The clock is well configured and there seems to be some problem in serial interrupt configuration.
Here is the code for the same.
Code: |
#include <18F2550.h>
#fuses HSPLL,NOWDT,NOPROTECT,NOLVP,NODEBUG,NOMCLR,USBDIV,PLL5,CPUDIV4,VREGEN
#use delay(clock=16000000)
#use rs232(baud=4800,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)
char gps_data[5];
long data_counter = 0;
void main(void) {
LED_ON(LED2);
LED_ON(LED3);
ext_int_edge(H_TO_L);
// init interrupt triggering for button press
enable_interrupts(GLOBAL);
// Enable serial interrupt
enable_interrupts(INT_RDA);
// Enable ext0 interrupt
enable_interrupts(INT_EXT);
// Enable ext1 interrupt
enable_interrupts(INT_EXT1);
nokia_init();
while (TRUE) {
}
#int_rda
void rda_isr()
{
char c;
gps_data[data_counter] = getch();
data_counter++;
if(data_counter==5)
{
nokia_clear_screen();
nokia_gotoxy(0,1);
printf(nokia_printchar,"Interrupt");
delay_ms(500);
data_counter=0;
}
clear_interrupt(int_RDA);
}
#int_ext
void EXT0_isr()
{
nokia_clear_screen();
nokia_gotoxy(0,1);
printf(nokia_printchar,"EXT0 int");
delay_ms(1000);
}
#int_ext1
void EXT1_isr()
{
nokia_clear_screen();
nokia_gotoxy(0,1);
printf(nokia_printchar,"EXT1int");
delay_ms(1000);
} |
|
|
|
akshaymathur39
Joined: 05 Aug 2008 Posts: 11
|
|
Posted: Sun Oct 04, 2009 2:14 am |
|
|
I just tried this code:
Code: | int8 i=1;
char c;
#int_RDA
void RDA_int()
{
c=getc();
i++;
nokia_clear_screen();
nokia_gotoxy(0,1);
printf(nokia_printchar,"Interrupt %i",i);
delay_ms(500);
clear_interrupt(int_rda);
}
#int_ext
void search_isr()
{
nokia_clear_screen();
nokia_gotoxy(0,1);
printf(nokia_printchar,"Search int");
delay_ms(1000);
clear_interrupt(int_ext);
}
#int_ext1
void backlight_isr()
{
nokia_clear_screen();
nokia_gotoxy(0,1);
printf(nokia_printchar,"Backlight int");
delay_ms(1000);
clear_interrupt(int_ext1);
}
void main(void) {
LED_OFF(LED3);
LED_ON(LED2);
nokia_init();
ext_int_edge(H_TO_L);
// init interrupt triggering for button press
enable_interrupts(GLOBAL);
// Enable serial interrupt
clear_interrupt(INT_RDA); enable_interrupts(INT_RDA);
// Enable ext0 interrupt
clear_interrupt(INT_EXT); enable_interrupts(INT_EXT);
// Enable ext1 interrupt
clear_interrupt(INT_EXT1); enable_interrupts(INT_EXT1);
delay_ms(3000);
LED_ON(LED3);
while (TRUE) {
}
} |
It display following:
Interrupt 2
Interrupt 3
Interrupt 4
Can anybody please be of some help. |
|
|
Ttelmah Guest
|
|
Posted: Sun Oct 04, 2009 2:30 am |
|
|
First thing, add the keyword 'errors' to your #use RS232 declaration.
This is particularly 'vital', becaue of your INT_RDA, which breaks a whole crop of 'guidelines'....
Basically, you should get out of ISR's as quickly as possible, unless you know _exactly_ what you are doing. In your case, on the fifth character, you will stay in the ISR, for a huge time. 500mSec, plus the time to clear the display, write a message, etc. etc.. If more serial characters are received wqhile this is going on, the ISR can't be called, and these will lockup the UART _permanently_. Adding errors, will generate the code to clear this lockup, but not get rid of the basic 'cause' - set a flag in the ISR, and do all these slow operations in the main, when this is set. This then gets 'worse', since your code sits for over a second, in each of the other interrupt handlers....
Then, I'd 'guess' that the nokia routines, almost certainly use a subroutine, to actually write bytes to the display controller. This is probably used inside the nokia_init routine, and inside each of the display routines as well. If so, then interrupts _will_ be disabled in the main code, inside these routines. It won't as it stands cause a problem (except if interrupts trigger during the nokia_init), at present, since yourmain wait loop, does not try to perform any 'display', but in future _will_ cause problems. Same comment applies, don't perform display operations or delays inside the interrupts.
Recite 100 times. An ISR, should _only_ handle the actual interrupt 'event'. Keep everything else 'outside' the ISR.
Don't use 16bit counters, unless they are needed. An int8, is handled _faster_. Make your data counter 8bit, unless you are expecting more than 255 bytes of data.
Best Wishes |
|
|
akshaymathur Guest
|
|
Posted: Sun Oct 04, 2009 12:28 pm |
|
|
Hi!
Thanks for your reply. I added "errors" keyword in the #use RS232 statement.
But all I am receiving is not the actual string coming from GPS module but some random values like " ~x'A' ".
Can you please help me to refine the program.
Awaiting replies. |
|
|
Jeff7
Joined: 22 Sep 2009 Posts: 13
|
|
Posted: Sun Oct 04, 2009 12:34 pm |
|
|
Definitely do get rid of any delay_ms and printf's inside the interrupt.
Get the data first, maybe send the data to a holding array, and then afterward print out what's inside the array.
At least that's been my approach.
And of course ensure that your module is also communicating at 4800bps.
I'm working on something similar actually. I kind of came into the project after a lot of the coding had been done, but our GPS modules were problematic, and I was told to basically do a redesign, with "make it work" as the ultimate goal.
This device only needed to get data occasionally though, to keep some clock code in the PIC synced up and accurate; the PIC was usually busy doing various other things.
The code that was there acquired the data without the use of an interrupt.
Every few seconds it would do a check on the RX pin using a while-loop and kbhit to look for data.
(I'm not sure if the timed_getc() function is part of the normal CCS package, and thus falls under the "no-post copyrighted" clause of the posting rules. If it is included, I think it would be in comms.h.)
That function was called from within a while loop that was running with a timer - if it didn't get the data it was looking for within about 200mS, it exited, and would try again later.
Code: |
gps_break = 0;
while (true && gps_break < 3)
{
if (timed_getd() == '$')
{
timed_getD(); // G
timed_getD(); // P
if (timed_getd() == 'R')
{
for (i=3;i<71;i++)
{
comms[i] = timed_getd();
}
comms[0] = 'G';
comms[1] = 'P';
comms[2] = 'R';
read_counter = 0;
gps_break = 0;
break;
}
}
}
|
The data packets from this module always start with $ and then they give an identifier as to the kind of data (GPGSV, GPRMC, etc). This would look for the RMC packet, and then retrieve the full string for processing.
On occasion it would get garbled data, but there was a checksum function later on to first calculate the checksum of the data between the $ and * in the string, and compare it to the one read from the data packet. If it failed the test, the get_time function simply exited; otherwise, it would continue on and extract the time information.
On a side note, I was also able to send a command to the GPS module, speeding it up from 4800bps to 38400bps. I don't remember the exact times (they're written down in a notebook somewhere at work), but it was taking somewhere around a full half-second just to transfer this big chunk of data. Upping the speed helped reduce that considerably. |
|
|
|
|
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
|