• AVR Freaks

Helpful ReplyHot!PIC18F45K22 UART String Parser Buffer Using Interrupt

Author
btommo
Senior Member
  • Total Posts : 136
  • Reward points : 0
  • Joined: 2017/07/07 02:59:33
  • Location: 0
  • Status: offline
2020/03/25 09:55:16 (permalink)
0

PIC18F45K22 UART String Parser Buffer Using Interrupt

Hi All,
 
I'm working on a parser that checks for a $GPRMC NMEA message and then sets a flag to fill a buffer in an interrupt routine, the interrupt routine does it's job and stores the message data correctly finishing filling the buffer when an '*' is seen (tried '\n' or '\r' but it only stopped when buffer was full) but I have a 'funny' issue when splitting it into seperate strings such as time and date etc please see attached real term screen shot and below code;
 
/* PIC18F45K22 GPS UART Example with RX interrupt V0.01 
 * GPRMC Message Parsing from PC
 *
 * File: main.c
 * Author: Btommo
 * PIC: PIC18F45K22
 * OSC: 8MHz internal oscillator
 * Created on 09 June 2019
 *
 * $GPRMC message used:
 * $GPRMC,225446.00,A,4916.45,N,12311.12,W,000.5,054.7,191194,020.3,E*68
 *
*/
#include <stdio.h>
#include <stdlib.h>
#include <xc.h>
#include <stdint.h>
#include "mcc_generated_files/mcc.h"

//__EEPROM_DATA(0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF);
/******************************************************************************/
/*CONFIGURATION */
/******************************************************************************/
// PIC18F45K22 Configuration Bit Settings

// 'C' source line config statements



// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.
#define _XTAL_FREQ 8000000 //oscillator frequency for delay_ms()


/******************************************************************************/
/* User Global Variable Declaration */
/******************************************************************************/

uint8_t dly_cnt1; //seconds delay counters
uint8_t dly_cnt2;

//unsigned char hours[3];
unsigned char time[9];
unsigned char valid[1];
//unsigned char minutes[3];
//unsigned char seconds[3];
unsigned char lat[7];
unsigned char lat_dir[1];
unsigned char longit[7];
unsigned char long_dir[1];
unsigned char speed_knot[5];
unsigned char course[5];
unsigned char date[6];
unsigned char Variation[5];
unsigned char EAWE[1];
/*unsigned char date_day[2];
unsigned char date_month[2];
unsigned char date_year[2];*/
unsigned char gps[]= "$GPRMC,";




/******************************************************************************/
/* Routines */
/******************************************************************************/
void DLYS(unsigned char s)
{
    dly_cnt2 = 0;
    while(dly_cnt2 < s/1) //seconds
    {
        dly_cnt1 = 0;
        while(dly_cnt1 < 1000/8)
        {
            TMR0 = 0;
            while(TMR0 < 8000/32)
            ;
            ++dly_cnt1;
        }
        ++dly_cnt2;
    }
    
}


void send_string(const char *x)
{
    while(*x)
    {
        EUSART1_Write(*x++);
    }
}

unsigned char read_string(unsigned char *Output,char Delimiter, uint8_t max_length)
{
    i = 0;
    char tmp = 1;
    for(i=0 ; i<max_length ; i++)
    {
        Output[i] = '\0';
    }
    for(i=0 ; i<(max_length); i++)
    {
        tmp = EUSART1_Read();
        if(tmp == Delimiter)
        {
            break;
        }
        Output[i] = tmp;
    }
    Output[i]= '\0';
    
    return i;
}

void NMEA_PARSE (void)
{
    i = 0;
    j = 0;
    while(buffer[i] != ',')
    {
        time[j] = buffer[i];
        j++;
        i++;
    }
    if(buffer[i] == ',')
    {
        i++;
    }
    j = 0;
    while(buffer[i] != ',')
    {
        valid[j] = buffer[i];
        j++;
        i++;
    }
    if(buffer[i] == ',')
    {
        i++;
    }
    j = 0;
    while(buffer[i] != ',')
    {
        lat[j] = buffer[i];
        j++;
        i++;
    }
    if(buffer[i] == ',')
    {
        i++;
    }
    j = 0;
    while(buffer[i] != ',')
    {
        lat_dir[j] = buffer[i];
        j++;
        i++;
    }
    if(buffer[i] == ',')
    {
        i++;
    }
    j = 0;
    while(buffer[i] != ',')
    {
        longit[j] = buffer[i];
        j++;
        i++;
    }
    if(buffer[i] == ',')
    {
        i++;
    }
    j = 0;
    while(buffer[i] != ',')
    {
        long_dir[j] = buffer[i];
        j++;
        i++;
    }
    if(buffer[i] == ',')
    {
        i++;
    }
    j = 0;
    while(buffer[i] != ',')
    {
        speed_knot[j] = buffer[i];
        j++;
        i++;
    }
    if(buffer[i] == ',')
    {
        i++;
    }
    j = 0;
    while(buffer[i] != ',')
    {
        course[j] = buffer[i];
        j++;
        i++;
    }
    if(buffer[i] == ',')
    {
        i++;
    }
    j = 0;
    while(buffer[i] != ',')
    {
        date[j] = buffer[i];
        j++;
        i++;
    }
    if(buffer[i] == ',')
    {
        i++;
    }
    j = 0;
    while(buffer[i] != ',')
    {
        Variation[j] = buffer[i];
        j++;
        i++;
    }
    for(i = 0; i<=79; i++)buffer[i] = '\0';
    i = 0;
}
/******************************************************************************/
/* Main Program */
/******************************************************************************/
void main()
{
    SYSTEM_Initialize();//initialize system;pins,osc,peripherals i.e adc,TMR0 etc
    
    for(i = 0; i<=79; i++)buffer[i] = '\0';
    i = 0;
    j = 0;
    flag = 0;
    //hours[2] = '\0';
    //minutes[2] = '\0';
    //seconds[2] = '\0';
    __delay_ms(500);
    send_string("SYSTEM STARTING \r\n");
   //MAIN LOOP
      
   while(1)
    {
       //wait until interrupt detects '$GPRMC,' and fills buffer
       while(flag == 0 && bufferRDY == 0)
       {
            
            
            c = EUSART1_Read();
            if(c == gps[i] && i < 7)
            {
                i++;
                if(i == 7)
                {
                    flag = 1;
                }
            }
            else
            {
                i = 0;
                //send_string("$GPRMC sentence not found \r\n");
            }
            if(flag == 1)
                i = 0;
           
       }
       if (bufferRDY == 1) // interrupt has found '$GPRMC,' and filled buffer
       {
           
            send_string("$GPRMC sentence found \r\n");
            send_string(buffer);
            send_string("\r\n");
            NMEA_PARSE();
            send_string(time);
            send_string("\r\n");
            send_string(valid);
            send_string("\r\n");
            send_string(lat);
            send_string("\r\n");
            send_string(lat_dir);
            send_string("\r\n");
            send_string(longit);
            send_string("\r\n");
            send_string(long_dir);
            send_string("\r\n");
            send_string(speed_knot);
            send_string("\r\n");
           
           
            if(valid == "A")
            {
                send_string("SENTENCE IS VALID \r\n");
               
               /*hours[0] = buffer[0];
               hours[1] = buffer[1];
               minutes[0] = buffer[2];
               minutes[1] = buffer[3];
               seconds[0] = buffer[4];
               seconds[1] = buffer[5];*/
               
           }
           if(buffer[10] != 'A')
           {
               send_string("SENTANCE IS INVALID \r\n");
           }
          
           /*send_string(buffer);
           send_string("\r\n");
           send_string(hours);
           //send_string("\r\n");
           send_string(":");
           //send_string("\r\n");
           send_string(minutes);
           //send_string("\r\n");
           send_string(":");
           send_string(seconds);*/
           send_string(time);
           send_string("\r\n");
           send_string(date);
           send_string("\r\n");
           
           flag = 0;
           bufferRDY = 0;
       }
       //__delay_ms(1000);
       
    }
    return;
}

/******************************************************************************/
/* Interrupt */
/******************************************************************************/

/*void __interrupt() ISR (void)
{
    // interrupt handler
    if(INTCONbits.PEIE == 1)
    {
        if(PIE1bits.RC1IE == 1 && PIR1bits.RC1IF == 1)
        {
            //send_string("interrupt entered");
            //EUSART1_RxDefaultInterruptHandler();
            if(flag == 0)
            {
                //("interrupt entered");
                c = EUSART1_Read();
                send_string("interrupt entered");
                if(c == gps[i] && i < 7)
                {
                    i++;
                    if(i == 7)
                    {
                        flag=1;
                    }
                }
                else
                {
                    i = 0;
                }
                
            }
            if (flag == 1)
            {
                //send_string("$GPRMC found");
                read_string(buffer,'*',80);
            }
            
            PIR1bits.RC1IF = 0;
        }
        
    }
}*/


    

 
void __interrupt() INTERRUPT_InterruptManager (void)
{
    // interrupt handler
    if(INTCONbits.PEIE == 1)
    {
        if(PIE1bits.RC1IE == 1 && PIR1bits.RC1IF == 1)
        {
            EUSART1_RxDefaultInterruptHandler();
            if(flag == 1)
            {
                c = EUSART1_Read();
                if((c != '*') /*|| i < 79*/)
                {
                    buffer[i] = c;
                    i++;
                }
                if((c == '*') || i >= 79)
                {
                    i = 0;
                    bufferRDY = 1;
                    flag = 0;
                }
                
            }
           PIR1bits.RC1IF == 0;
        }
        
    }
}

 
Any guidance would be greatly appreciated. Thanks in advance.

Attached Image(s)

#1
pcbbc
Super Member
  • Total Posts : 1649
  • Reward points : 0
  • Joined: 2014/03/27 07:04:41
  • Location: 0
  • Status: offline
Re: PIC18F45K22 UART String Parser Buffer Using Interrupt 2020/03/25 11:03:33 (permalink) ☄ Helpfulby btommo 2020/03/26 13:37:34
+2 (2)
Tip:
Don't do ANYTHING in your ISR other than fill a circular buffer with incoming data from the UART and check for and recover UART errors.
All of the procesing to check for line delimiters, and check for specific strings of characters should be in your main code.  This should read from the circular buffer into a linear one until it reaches a delimiter, then compare the text received into that linear buffer against what you are expecting.
 
As is, at least one thing wrong with your code is that you are missing string terminators on all of your buffers:
    while(buffer[i] != ',')
    {
        time[j] = buffer[i];
        j++;
        i++;
    }
    time[j] = '\0'; // <== Missing

#2
btommo
Senior Member
  • Total Posts : 136
  • Reward points : 0
  • Joined: 2017/07/07 02:59:33
  • Location: 0
  • Status: offline
Re: PIC18F45K22 UART String Parser Buffer Using Interrupt 2020/03/26 04:36:29 (permalink)
0
Hi pcbbc,
 
Thank you for your reply and advice, adding '\0' solved the problem and was able to successfully parse using the linear buffer in the interrupt routine but realise that it wasn't correct as you mentioned.
 
I have tried doing it with a circular buffer to fill which filled the buffer correctly but seems to have effected the parsing;
 
/* PIC18F45K22 GPS UART Example with RX interrupt V0.03 with circular buffer in
 * interrupt
 * GPRMC Message Parsing from PC
 *
 * File: main.c
 * Author: Btommo
 * PIC: PIC18F45K22
 * OSC: 8MHz internal oscillator
 * Created on 26 March 2020
 *
 * $GPRMC message used:
 * $GPRMC,225446.00,A,4916.45,N,12311.12,W,000.5,054.7,191194,020.3,E*68
 *
*/
#include <stdio.h>
#include <stdlib.h>
#include <xc.h>
#include <stdint.h>
#include "mcc_generated_files/mcc.h"

//__EEPROM_DATA(0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF);
/******************************************************************************/
/*CONFIGURATION */
/******************************************************************************/
// PIC18F45K22 Configuration Bit Settings

// 'C' source line config statements



// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.
#define _XTAL_FREQ 8000000 //oscillator frequency for delay_ms()


/******************************************************************************/
/* User Global Variable Declaration */
/******************************************************************************/

uint8_t dly_cnt1; //seconds delay counters
uint8_t dly_cnt2;
uint8_t k = 0;
uint8_t l = 0;
uint8_t is = 0;

//unsigned char hours[3];
unsigned char time[10] = '0';
unsigned char valid[3] = '\0';
//unsigned char minutes[3];
//unsigned char seconds[3];
unsigned char lat[9] = '\0';
unsigned char lat_dir[2] = '\0';
unsigned char longit[9] = '\0';
unsigned char long_dir[2] = '\0';
unsigned char speed_knot[6] = '\0';
unsigned char course[6] = '\0';
unsigned char date[7] = '\0';
unsigned char Variation[6] = '\0';
unsigned char EAWE[2] = '\0';
/*unsigned char date_day[2];
unsigned char date_month[2];
unsigned char date_year[2];*/
unsigned char gps[]= "$GPRMC,";




/******************************************************************************/
/* Routines */
/******************************************************************************/
void DLYS(unsigned char s)
{
    dly_cnt2 = 0;
    while(dly_cnt2 < s/1) //seconds
    {
        dly_cnt1 = 0;
        while(dly_cnt1 < 1000/8)
        {
            TMR0 = 0;
            while(TMR0 < 8000/32)
            ;
            ++dly_cnt1;
        }
        ++dly_cnt2;
    }
    
}


void send_string(const char *x)
{
    while(*x)
    {
        EUSART1_Write(*x++);
    }
}

unsigned char read_string(unsigned char *Output,char Delimiter, uint8_t max_length)
{
    i = 0;
    char tmp = 1;
    for(i=0 ; i<max_length ; i++)
    {
        Output[i] = '\0';
    }
    for(i=0 ; i<(max_length); i++)
    {
        tmp = EUSART1_Read();
        if(tmp == Delimiter)
        {
            break;
        }
        Output[i] = tmp;
    }
    Output[i]= '\0';
    
    return i;
}

void NMEA_PARSE (void)
{
    k = 0;
    l = 0;
    while(buffer[k] != ',')
    {
        time[l] = buffer[k];
        l++;
        k++;
    }
    if(buffer[k] == ',')
    {
        time[l] = '\0';
        k++;
    }
    l = 0;
    while(buffer[k] != ',')
    {
        valid[l] = buffer[k];
        l++;
        k++;
    }
    if(buffer[k] == ',')
    {
        valid[k] = '\0';
        i++;
    }
    l = 0;
    while(buffer[k] != ',')
    {
        lat[l] = buffer[k];
        l++;
        i++;
    }
    if(buffer[k] == ',')
    {
        lat[l] = '\0';
        k++;
    }
    l = 0;
    while(buffer[k] != ',')
    {
        lat_dir[l] = buffer[k];
        l++;
        k++;
    }
    if(buffer[k] == ',')
    {
        lat_dir[l] = '\0';
        k++;
    }
    l = 0;
    while(buffer[k] != ',')
    {
        longit[l] = buffer[k];
        l++;
        k++;
    }
    if(buffer[k] == ',')
    {
        longit[l+1] = '\0';
        k++;
    }
    l = 0;
    while(buffer[k] != ',')
    {
        long_dir[l] = buffer[k];
        l++;
        k++;
    }
    if(buffer[k] == ',')
    {
        long_dir[l] = '\0';
        k++;
    }
    l = 0;
    while(buffer[k] != ',')
    {
        speed_knot[l] = buffer[k];
        l++;
        k++;
    }
    if(buffer[k] == ',')
    {
        speed_knot[l] = '\0';
        k++;
    }
    l = 0;
    while(buffer[k] != ',')
    {
        course[l] = buffer[k];
        l++;
        k++;
    }
    if(buffer[k] == ',')
    {
        course[l] = '\0';
        k++;
    }
    l = 0;
    while(buffer[k] != ',')
    {
        date[l] = buffer[k];
        l++;
        k++;
    }
    if(buffer[k] == ',')
    {
        date[l] = '\0';
        k++;
    }
    l = 0;
    while(buffer[k] != ',')
    {
        Variation[l] = buffer[i];
        l++;
        k++;
    }
    if(buffer[k] == ',')
    {
        Variation[l] = '\0';
        k++;
    }
    for(k = 0; k<=79; k++)buffer[k] = '\0';
    k = 0;
}
/******************************************************************************/
/* Main Program */
/******************************************************************************/
void main()
{
    SYSTEM_Initialize();//initialize system;pins,osc,peripherals i.e adc,TMR0 etc
    
    for(k = 0; k<=79; k++)buffer[k] = '\0';
    k = 0;
    j = 0;
    flag = 0;
    //hours[2] = '\0';
    //minutes[2] = '\0';
    //seconds[2] = '\0';
    __delay_ms(500);
    send_string("SYSTEM STARTING \r\n");
   //MAIN LOOP
      
   while(1)
    {
       //wait until interrupt detects '$GPRMC,' and fills buffer
       while(flag == 0)
       {
            
            
            c = bufferCIRC[j];
            if(c == gps[k] && k < 7)
            {
                k++;
                if(k == 7)
                {
                    k = 0;
                    j++;
                    while(bufferCIRC[j] != '*')
                    {
                        if(is != i)
                        {
                            is = i;
                            buffer[k] = bufferCIRC[j];
                            k++;
                            j++;
                            if(j == BUFFER_MAX)
                                j = 0;
                        }
                    }
                    buffer[k] = '\0';
                    flag = 1;
                }
            }
            else
            {
                k = 0;
                //send_string("$GPRMC sentence not found \r\n");
            }
            j++;
            if(j >= BUFFER_MAX)
                j = 0;
           
       }
       if (flag == 1) // interrupt has found '$GPRMC,' and filled buffer
       {
           
            send_string("$GPRMC sentence found \r\n");
            send_string(buffer);
            send_string("\r\n");
            NMEA_PARSE();
            send_string(time);
            send_string("\r\n");
            send_string(valid);
            send_string("\r\n");
            send_string(lat);
            send_string("\r\n");
            send_string(lat_dir);
            send_string("\r\n");
            send_string(longit);
            send_string("\r\n");
            send_string(long_dir);
            send_string("\r\n");
            send_string(speed_knot);
            send_string("\r\n");
           
           
            if(valid[0] == 'A')
            {
                send_string("SENTENCE IS VALID \r\n");
               
               /*hours[0] = buffer[0];
               hours[1] = buffer[1];
               minutes[0] = buffer[2];
               minutes[1] = buffer[3];
               seconds[0] = buffer[4];
               seconds[1] = buffer[5];*/
               
           }
           if(valid[0] != 'A')
           {
               send_string("SENTANCE IS INVALID \r\n");
           }
          
           /*send_string(buffer);
           send_string("\r\n");
           send_string(hours);
           //send_string("\r\n");
           send_string(":");
           //send_string("\r\n");
           send_string(minutes);
           //send_string("\r\n");
           send_string(":");
           send_string(seconds);*/
           send_string(time);
           send_string("\r\n");
           send_string(date);
           send_string("\r\n");
           
           flag = 0;
       }
       //__delay_ms(1000);
       
    }
    return;
}

/******************************************************************************/
/* Interrupt */
/******************************************************************************/

/*void __interrupt() ISR (void)
{
    // interrupt handler
    if(INTCONbits.PEIE == 1)
    {
        if(PIE1bits.RC1IE == 1 && PIR1bits.RC1IF == 1)
        {
            //send_string("interrupt entered");
            //EUSART1_RxDefaultInterruptHandler();
            if(flag == 0)
            {
                //("interrupt entered");
                c = EUSART1_Read();
                send_string("interrupt entered");
                if(c == gps[i] && i < 7)
                {
                    i++;
                    if(i == 7)
                    {
                        flag=1;
                    }
                }
                else
                {
                    i = 0;
                }
                
            }
            if (flag == 1)
            {
                //send_string("$GPRMC found");
                read_string(buffer,'*',80);
            }
            
            PIR1bits.RC1IF = 0;
        }
        
    }
}*/


    

void __interrupt() INTERRUPT_InterruptManager (void)
{
    // interrupt handler
    if(INTCONbits.PEIE == 1)
    {
        if(PIE1bits.RC1IE == 1 && PIR1bits.RC1IF == 1)
        {
            EUSART1_RxDefaultInterruptHandler();
            bufferCIRC[i] = EUSART1_Read();
            i++;
            if(i == BUFFER_MAX)
                i = 0;
           PIR1bits.RC1IF == 0;
        }
        
    }
}

 

Attached Image(s)

#3
pcbbc
Super Member
  • Total Posts : 1649
  • Reward points : 0
  • Joined: 2014/03/27 07:04:41
  • Location: 0
  • Status: offline
Re: PIC18F45K22 UART String Parser Buffer Using Interrupt 2020/03/26 05:16:35 (permalink)
+1 (1)
Function read_string should NOT be calling EUSART1_Read.  That reads a byte from the hardware.  The ISR should be the ONLY code that touches the hardware.  It's job is to add the incoming data to the circular buffer.
 
The your mainline code calls read_string, and read_string should read from the buffer.
 
Here is a rough example of how to implement a circular buffer.  Note code is untested and supplied as an example...
// NB: Size of buffer MUST be a power of 2
#define BUFF_SIZE 0x20
#define BUFF_MASK (BUFF_SIZE - 1)

volatile unsigned char buff[BUFF_SIZE];
volatile uint8_t buff_head;
volatile uint8_t buff_tail;

// Call this from the ISR (or paste code directly) to add characters to the buffer...
void write_buffer(unsigned char c)
{
    // Add next character to circular buffer
    // Note for simplicity I do NOT check for or handle a buffer overrun
    // (I assume the main processing can consume data fast enough to prevent overrun)
    buff[buff_head] = c;
    // Advance head of circular buffer
    buff_head++;
    buff_head &= BUFF_MASK; // This works only if the buffer is a power of 2
}

// Call this from mainline to read a character from the buffer...
unsigned char read_buffer()
{
    // Wait for character available
    while (buff_head == buf_tail);
    // Get next character from buffer
    unsigned char c = buff[buff_tail];
    // Advance tail of circular buffer atomically
    GIE = 0;
    buff_tail++;
    buff_tail &= BUFF_MASK; // This works only if the buffer is a power of 2
    GIE = 1;
    return c;
}

 
This is pointless...
PIR1bits.RC1IF == 0;

RC1IF is read only.  It is reset by the hardware automatically (or not if there is another byte of data available) when you read the byte with EUSART1_Read();
#4
btommo
Senior Member
  • Total Posts : 136
  • Reward points : 0
  • Joined: 2017/07/07 02:59:33
  • Location: 0
  • Status: offline
Re: PIC18F45K22 UART String Parser Buffer Using Interrupt 2020/03/26 05:41:03 (permalink)
0
Hi pcbcc,
 
I'm not using the read string function, I'm placing the result from the circular bufferCIR[j] into buffer[k] when a new result is put into the circular buffer i.e i != is (i incremented in interrupt). the result seems to store correctly in the linear buffer in the mainline code and not a seperate function (yet);
 
225446.00,A,4916.45,N,12311.12,W,000.5,054.7,191194,020.3,E
 
For some reason when reading the linear buffer from the begining and storing time etc. when transmitting time back it shows 1.12 (which seems to be part of longitude (after fourth ',')) as opposed to 225446.00 but the next line shows 'A' which is the 'valid' string which is before, even though I increment the linear buffer counter.... doesn't make sense to me.
 
If it helps the attached was the result from using linear buffer in interrupt.
 
Nevermind, a little typo somewhere when I altered from old to new version....
 
 
post edited by btommo - 2020/03/26 06:23:30

Attached Image(s)

#5
LdB_ECM
Super Member
  • Total Posts : 312
  • Reward points : 0
  • Joined: 2019/04/16 22:01:25
  • Location: 0
  • Status: offline
Re: PIC18F45K22 UART String Parser Buffer Using Interrupt 2020/03/26 07:05:12 (permalink) ☄ Helpfulby btommo 2020/03/26 13:37:04
+2 (2)
Some of your buffers don't look long enough to take the string ... time for example is 9 characters (225446.00) and needs a 10th character for the terminator so I extended them to 12 chars
 
I just did a quick parse check with
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
 
char time[12];
char valid;
char lat[12];
char lat_dir;
char longit[12];
char long_dir;
char speed_knot[12];
char course[12];
char date[12];
char variation[12];
char var_dir;
 
const char* buffer = "$GPRMC 225446.00,A,4916.45,N,12311.12,W,000.5,054.7,191194,0020.3,E";
 
 void NMEA_PARSE(void)
{
    uint8_t len;
    char* p = strchr(buffer, ',');
    char* q = p;
    p = strchr(p + 1, ',');
    len = (unsigned)(p - q - 1);
    strncpy(time, q + 1, len);
    time[len] = '\0';
    valid = p[1];
    p = strchr(p + 1, ',');
    q = p;
    p = strchr(p + 1, ',');
    len = (unsigned)(p - q - 1);  
    strncpy(lat, q + 1, len);
    lat[len] = '\0';
    lat_dir = p[1];
    p = strchr(p + 1, ',');
    q = p;
    p = strchr(p + 1, ',');
    len = (unsigned)(p - q - 1);
    strncpy(longit, q + 1, len);
    longit[len] = '\0';
    long_dir = p[1];
    p = strchr(p + 1, ',');
    q = p;
    p = strchr(p + 1, ',');
    len = (unsigned)(p - q - 1);
    strncpy(speed_knot, q + 1, len);
    speed_knot[len] = '\0';
    q = p;
    p = strchr(p + 1, ',');
    len = (unsigned)(p - q - 1);
    strncpy(course, q + 1, len);
    course[len] = '\0';
    q = p;
    p = strchr(p + 1, ',');
    len = (unsigned)(p - q - 1);
    strncpy(date, q + 1, len);
    date[len] = '\0';
    q = p;
    p = strchr(p + 1, ',');
    len = (unsigned)(p - q - 1);
    strncpy(variation, q + 1, len);
    variation[len] = '\0';
    var_dir = p[1];
}
 
int main (void)
{
    NMEA_PARSE(); 
}

 
How slow is it on a PIC18 to convert time lat long to a float using atof?
post edited by LdB_ECM - 2020/03/26 07:11:20
#6
btommo
Senior Member
  • Total Posts : 136
  • Reward points : 0
  • Joined: 2017/07/07 02:59:33
  • Location: 0
  • Status: offline
Re: PIC18F45K22 UART String Parser Buffer Using Interrupt 2020/03/26 07:44:11 (permalink)
0
Thanks for your comment on buffer lengths, it solved issue I was having where it would run correctly sometimes and not other times and also mix up some values for some reason. but now it responds each time a message is sent and parsed correctly but encountered an issue where the data sent back is one behind the data sent, i.e if i change time from 225446.00 (sent first) to 225446.01 (sent second) it sees 225446.00 but if I send 225446.02 next it sends 225446.01 back.... strange :/.
 
Not sure on the atof function as haven't used before, but I'm about to for speed, do you mean check in simulation or is there a way to check in hardware i.e toggle a pin and scope (is there a better way in hardware?).
 
 
post edited by btommo - 2020/03/26 07:52:24
#7
btommo
Senior Member
  • Total Posts : 136
  • Reward points : 0
  • Joined: 2017/07/07 02:59:33
  • Location: 0
  • Status: offline
Re: PIC18F45K22 UART String Parser Buffer Using Interrupt 2020/03/26 08:42:20 (permalink)
0
Can someone give me a lesson on converting to float and from float to array please, I've tried to send a string back of speedMPHA and all I got was blank.....
 
speedMPH = atof(speed_knot) * 1.15;
    ftoa(speedMPH, speedMPHA);
    speedMPHA[11] = '\0';

#8
pcbbc
Super Member
  • Total Posts : 1649
  • Reward points : 0
  • Joined: 2014/03/27 07:04:41
  • Location: 0
  • Status: offline
Re: PIC18F45K22 UART String Parser Buffer Using Interrupt 2020/03/26 09:13:25 (permalink) ☄ Helpfulby btommo 2020/03/26 13:36:51
+2 (2)
Look up how ftoa works in the XC8 user guide.
I think it returns a pointer to a static string.
The second parameter receives a status/return code.  It is NOT the destination string.
 
speedMPH = atof(speed_knot) * 1.15;
int status;
unsigned char* result = ftoa(speedMPH, &status);
//Do "something" with the string pointed to by 'result'.  Copy it to your own buffer with strcpy for example.

#9
btommo
Senior Member
  • Total Posts : 136
  • Reward points : 0
  • Joined: 2017/07/07 02:59:33
  • Location: 0
  • Status: offline
Re: PIC18F45K22 UART String Parser Buffer Using Interrupt 2020/03/26 09:39:00 (permalink)
0
I tried looking in xc8 2.05 guide but didn't have any hits for ftoa. Thanks for the lesson pcbbc that worked and converts, calculates, converts back and prints successfully, the only issue I have now is that the buffer has the same set of data the first time you send a new set of data (one step behind when data changes) which I'll have a think about :/ 
#10
ric
Super Member
  • Total Posts : 26159
  • Reward points : 0
  • Joined: 2003/11/07 12:41:26
  • Location: Australia, Melbourne
  • Status: online
Re: PIC18F45K22 UART String Parser Buffer Using Interrupt 2020/03/27 04:10:05 (permalink)
+1 (1)
btommo
I tried looking in xc8 2.05 guide but didn't have any hits for ftoa.



Which mode are you using XC8 in? (C90 or C99?)
Which user guide were you looking in?
 

I also post at: PicForum
Links to useful PIC information: http://picforum.ric323.co...opic.php?f=59&t=15
NEW USERS: Posting images, links and code - workaround for restrictions.
To get a useful answer, always state which PIC you are using!
#11
btommo
Senior Member
  • Total Posts : 136
  • Reward points : 0
  • Joined: 2017/07/07 02:59:33
  • Location: 0
  • Status: offline
Re: PIC18F45K22 UART String Parser Buffer Using Interrupt 2020/03/27 04:20:08 (permalink)
0
I'm in C90 and did a find search in "MPLAB_XC8_C_Compiler_User_Guide_for_PIC" in the 2.05 XC8 folder within the program files on HDD.
#12
ric
Super Member
  • Total Posts : 26159
  • Reward points : 0
  • Joined: 2003/11/07 12:41:26
  • Location: Australia, Melbourne
  • Status: online
Re: PIC18F45K22 UART String Parser Buffer Using Interrupt 2020/03/27 04:22:52 (permalink)
+2 (2)
That's the manual for C99 mode.
Look in MPLAB_XC8_C_Compiler_Legacy_User_Guide.pdf for C90 mode.
 

I also post at: PicForum
Links to useful PIC information: http://picforum.ric323.co...opic.php?f=59&t=15
NEW USERS: Posting images, links and code - workaround for restrictions.
To get a useful answer, always state which PIC you are using!
#13
btommo
Senior Member
  • Total Posts : 136
  • Reward points : 0
  • Joined: 2017/07/07 02:59:33
  • Location: 0
  • Status: offline
Re: PIC18F45K22 UART String Parser Buffer Using Interrupt 2020/03/27 04:25:25 (permalink)
0
Ah OK found it now, does C99 have equivalent instructions? Just for future reference.
#14
ric
Super Member
  • Total Posts : 26159
  • Reward points : 0
  • Joined: 2003/11/07 12:41:26
  • Location: Australia, Melbourne
  • Status: online
Re: PIC18F45K22 UART String Parser Buffer Using Interrupt 2020/03/27 04:27:18 (permalink)
+1 (1)
It's not in the C99 stdlib.
You can always use sprintf() instead.
 

I also post at: PicForum
Links to useful PIC information: http://picforum.ric323.co...opic.php?f=59&t=15
NEW USERS: Posting images, links and code - workaround for restrictions.
To get a useful answer, always state which PIC you are using!
#15
Jump to:
© 2020 APG vNext Commercial Version 4.5