PIC demo board USART

cpicuart

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;
}

Best Answer

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.