1
\$\begingroup\$

I am trying to create a gps application but dont get good data. I have heard that the most common fault is to use a invalid baud rate but so I have tried to look at it but without success. The PIC I am using is a pic18f45k20 with the internal oscillator. The problem is that the variable rx in the getPosition function dont get a good value. I also tried to change the ReadUSART to getcUsart but I get the same value with those two functions. i am using MPLAB X with the xc8 compiler. Also the gps module is http://www.servicepunkten.com/downloads/GlobalTop-FGPMMOPA6H-Datasheet-V0B.pdf

My code for init:

#define _XTAL_FREQ 16000000
void initUsart(){
TRISCbits.RC6 = 0; //TX pin set as output
TRISCbits.RC7 = 1; //RX pin set as input

CloseUSART();
UART1Config = USART_TX_INT_OFF & USART_RX_INT_OFF & USART_ASYNCH_MODE & USART_EIGHT_BIT & USART_BRGH_HIGH ;
baud = 103;
OpenUSART(UART1Config,baud);

//compare with the table above
RCIF = 0; //reset RX pin flag
RCIP = 1; //High priority
RCIE = 1; //Enable RX interrupt
PEIE = 1; //Enable pheripheral interrupt (serial port is a pheripheral)

ei();       //remember the master switch for interrupt?

}

void setupClock()
{
OSCCONbits.IRCF0 = 1;
OSCCONbits.IRCF1 = 1;
OSCCONbits.IRCF2 = 1;
}

#define PMTK_SET_NMEA_OUTPUT_RMCONLY "$PMTK314,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0*29"
#define PMTK_SET_NMEA_UPDATE_10HZ "$PMTK220,100*2F"
#define PMTK_SET_BAUD_9600 "$PMTK251,9600*17"

void initGps(){
for(int i = 0; i < 16; i++){
    WriteUSART(PMTK_SET_BAUD_9600[i]);
}
for(int i = 0; i < 15; i++){
    WriteUSART(PMTK_SET_NMEA_UPDATE_10HZ[i]);
}
for(int i = 0; i < 49; i++){
    WriteUSART(PMTK_SET_NMEA_OUTPUT_RMCONLY[i]);
}
}

code for reading:

void interrupt interrupts(){

if(PIR1bits.RCIF == 1)
{
    handleUsartRx();
}
if(INTCONbits.TMR0IF == 1)
{
    handleTmr0();
}
}

void handleUsartRx(){
struct Position position = getPosition();
//do stuff with position
PIR1bits.RCIF = 0; // clear rx flag
}
struct Position getPosition(){
struct Position position;
position.fixed = -1;
rx = ReadUSART(); //read the byte from rx register

if(rx == '$'){
    rxIndex = 0;
    for(int i = 0; i < 50; i++){
        receivedData[i] = '\0';
    }
}
receivedData[rxIndex] = rx;
rxIndex++;

//Dont know which is the end string
if(strstr(&receivedData,"<CR><LF>") == NULL && strstr(&receivedData,"<CR> <LF>") == NULL){

    return position;
}

//EndString is found, start parsing;
char *parsedString[9];
splitNmeaString(parsedString);
position = createPosition(parsedString);

return position;
}
\$\endgroup\$
3
  • \$\begingroup\$ What data do you get? \$\endgroup\$
    – Dave Tweed
    Commented May 18, 2014 at 10:59
  • \$\begingroup\$ I should get data like: $GPRMC,123519,A,4807.038,N,01131.000,E,022.4,084.4,230394,003.1,W*6A but I get chars like '$', 'F','´', TAB etc etc almost never a number \$\endgroup\$ Commented May 18, 2014 at 11:21
  • \$\begingroup\$ Your test for end of line doesn't look right. Usually strings like "<CR><LF>" are just used for documentation. You really want to check for "\r\n" (or individually like '\r' and '\n'). "<CR> <LF>" makes no sense, even if it was shown as "\r \n", as I've never seen a space between the CR and LF. \$\endgroup\$
    – tcrosley
    Commented May 18, 2014 at 11:45

1 Answer 1

1
\$\begingroup\$

You're doing a lot of processing inside your handleUsartRx() function before you clear the interrupt flag, and I suspect that your problem is that you're simply missing a lot of the incoming data.

In particular, you call strstr() twice, and this is a relatively expensive function in terms of CPU cycles.

Furthermore, your strstr() calls will never succeed, since <CR>, etc. is not the correct way to denote a control character in a C string. For a carriage return, for example, use either \r or \x0D. Linefeed would be either \n or \x0A.

Since you never find the end of the string, your data buffer just keeps growing, which means that the processing on each new character takes longer and longer.

\$\endgroup\$
2
  • \$\begingroup\$ Yeah, maybe I should make some changes to the design so that the interrupt only gets the char. But I doubt that the problem is caused by it as the chars I'm getting should not be possible to get (like ÿ). About the <CR> I think that I misunderstood the documentation, but it will not make any problems until the data I get is valid \$\endgroup\$ Commented May 18, 2014 at 16:12
  • \$\begingroup\$ Also when changing the baud rate I get different results. But I think I have set the clock speed correctly to 16MHz which is the maximum speed for the internal oscillator for my pic. \$\endgroup\$ Commented May 18, 2014 at 16:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.