• AVR Freaks

Hot!PIC18F45K22 EUSART Issue reading and echo strings

Page: 12 > Showing page 1 of 2
Author
btommo
Junior Member
  • Total Posts : 94
  • Reward points : 0
  • Joined: 2017/07/07 02:59:33
  • Location: 0
  • Status: offline
2019/05/26 05:11:05 (permalink)
0

PIC18F45K22 EUSART Issue reading and echo strings

Hi,
 
I'm currently working on a program to read a string and echo it back when '\n', '\r' or '\0' is received, I have no trouble sending a string or receiving a character and performing an action based on it but I would like to be able to received a whole string and pick out the data needed such and a NMEA message but thought I would start small with receiving and echo a string received from a PC terminal;
 
Below is my code;
/* PIC18F45K22 String Echo UART Example V1.00 
 *
 *
 * File: main.c
 * Author: Btommo
 * PIC: PIC18F45K22
 * OSC: 8MHz internal oscillator
 * Created on 25 May 2019
 *
*/
#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 buffer[50];

/******************************************************************************/
/* 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(char *Output,char Delimiter, uint8_t max_length)
{
    uint8_t i = 0;
    char tmp = 1;
    for(i=0 ; i<max_length ; i++)
    {
        //while(EUSART1_is_rx_ready() == 0);// Wait for data to be received
        tmp = EUSART1_Read();
        if(tmp == Delimiter)
        {
            break;
        }
        Output[i] = tmp;
    }
    Output[i+1]= '\0';
    return i;
}

/******************************************************************************/
/* Main Program */
/******************************************************************************/
void main()
{
    SYSTEM_Initialize();//initialize system;pins,osc,peripherals i.e adc,TMR0 etc
    send_string("SYSTEM STARTING, ENTER COMMAND \r\n");
   //MAIN LOOP
      
   while(1)
    {
       
       read_string(buffer,'\n'||'\r'||'\0',49);
       send_string(buffer);
    }
    return;
}


    

 
EUSART code was generated with MCC and has been tested with switching LEDs based on characters received, first string "send_string("SYSTEM STARTING, ENTER COMMAND \r\n"); " is sent OK and viewed on terminal.
 
Thanks for your time in advance.
#1

24 Replies Related Threads

    qhb
    Superb Member
    • Total Posts : 9998
    • Reward points : 0
    • Joined: 2016/06/05 14:55:32
    • Location: One step ahead...
    • Status: offline
    Re: PIC18F45K22 EUSART Issue reading and echo strings 2019/05/26 05:59:01 (permalink)
    +1 (1)
    You never mention what happened when you tried your code, but I can see one glaring problem.
    You are passing a "delimiter" character to your read_string() function, but what you are passing is:
    '\n'||'\r'||'\0'
    which is just calculating the logical OR function of 0x0A, 0x0D and 0x00.
    The result of that calculation will be 0x01 (i.e. TRUE), which I am sure is not what you wanted.
    The function as written can only test against a SINGLE delimiter. You will have to rewrite it if you want to cater for multiple variations.
     

    Nearly there...
    #2
    btommo
    Junior Member
    • Total Posts : 94
    • Reward points : 0
    • Joined: 2017/07/07 02:59:33
    • Location: 0
    • Status: offline
    Re: PIC18F45K22 EUSART Issue reading and echo strings 2019/05/26 06:20:48 (permalink)
    0
    Hi qhb,
     
    Thank you for your reply, as mentioned I only get the first string sent by the micro, I'll try it with '\n' only as the delimiter.
     
    Below is new code;
     
     
    /* PIC18F45K22 String Echo UART Example V1.00 
     *
     *
     * File: main.c
     * Author: Btommo
     * PIC: PIC18F45K22
     * OSC: 8MHz internal oscillator
     * Created on 25 May 2019
     *
    */
    #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 buffer[50];

    /******************************************************************************/
    /* 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(char *Output,char Delimiter, uint8_t max_length)
    {
        uint8_t i = 0;
        char tmp = 1;
        for(i=0 ; i<max_length ; i++)
        {
            //while(EUSART1_is_rx_ready() == 0);// Wait for data to be received
            tmp = EUSART1_Read();
            if(tmp == Delimiter)
            {
                break;
            }
            Output[i] = tmp;
        }
        Output[i+1]= '\0';
        return i;
    }

    /******************************************************************************/
    /* Main Program */
    /******************************************************************************/
    void main()
    {
        SYSTEM_Initialize();//initialize system;pins,osc,peripherals i.e adc,TMR0 etc
        send_string("SYSTEM STARTING, ENTER COMMAND \r\n");
       //MAIN LOOP
          
       while(1)
        {
           //buffer = 0;
           read_string(buffer,'\n',49);
           send_string(buffer);
           EUSART1_Write('\r');
        }
        return;
    }


        

     
    It now works and sends the buffer mostly correct but I am getting a slight issue where if the last digit is deleted and the message is resent the echo'ed result sends back the last digit that was deleted. This only occurs to the next digit and if two digits are deleted only the next number that was in the buffer will show up.
     
    Edit: also another issue, I changed max_length to 255 and checked what is sent if I go past the buffer size and I get the attached result with two extra characters sent back '07'.
    post edited by btommo - 2019/05/26 06:45:29

    Attached Image(s)

    #3
    qhb
    Superb Member
    • Total Posts : 9998
    • Reward points : 0
    • Joined: 2016/06/05 14:55:32
    • Location: One step ahead...
    • Status: offline
    Re: PIC18F45K22 EUSART Issue reading and echo strings 2019/05/26 13:40:01 (permalink)
    0
    Your logic for adding the null at the end of the buffer fails if you hit the max_length
    i.e. your for() loop will exit with i = 49, then you write the NULL to Output[i+1], which is offset 50, which is past the end of your buffer, and you have left Output[49] with whatever it previously contained.
     

    Nearly there...
    #4
    btommo
    Junior Member
    • Total Posts : 94
    • Reward points : 0
    • Joined: 2017/07/07 02:59:33
    • Location: 0
    • Status: offline
    Re: PIC18F45K22 EUSART Issue reading and echo strings 2019/05/27 03:36:08 (permalink)
    0
    Thanks qhb, I've added a for loop to null the entries in the buffer which got rid of the extra character at the end but I have an issue where if the number of entries is greater than the buffer they show up on the next set of data. I know this wouldn't be an issue if the maximum length of the message is known and the buffer register was a suitable length but would like to iron it out, is there any way to clear RCREG1, I tried making it '0' as that is it's initial value, also tried disabling and enabling the SPEN in RCSTA1 but didn't make any difference.
     
    /* PIC18F45K22 String Echo UART Example V1.00 
     *
     *
     * File: main.c
     * Author: Btommo
     * PIC: PIC18F45K22
     * OSC: 8MHz internal oscillator
     * Created on 25 May 2019
     *
    */
    #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 buffer[50];

    /******************************************************************************/
    /* 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(char *Output,char Delimiter, uint8_t max_length)
    {
        uint8_t i = 0;
        char tmp = 1;
        for(i=0 ; i<max_length ; i++)
        {
            Output[i] = '\0';
        }
        for(i=0 ; i<(max_length); i++)
        {
            //while(EUSART1_is_rx_ready() == 0);// Wait for data to be received
            tmp = EUSART1_Read();
            if(tmp == Delimiter)
            {
                break;
            }
            Output[i] = tmp;
        }
        Output[i]= '\0';
        
        return i;
    }

    /******************************************************************************/
    /* Main Program */
    /******************************************************************************/
    void main()
    {
        SYSTEM_Initialize();//initialize system;pins,osc,peripherals i.e adc,TMR0 etc
        send_string("SYSTEM STARTING, ENTER COMMAND \r\n");
       //MAIN LOOP
          
       while(1)
        {
           //buffer = 0;
           read_string(buffer,'\n',50);
           send_string("Data Received: ");
           send_string(buffer);
           EUSART1_Write('\r');
           EUSART1_Write('\n');
        }
        return;
    }


        

     
    Attached is an image of the terminal result when too many entries are received.

    Attached Image(s)

    #5
    btommo
    Junior Member
    • Total Posts : 94
    • Reward points : 0
    • Joined: 2017/07/07 02:59:33
    • Location: 0
    • Status: offline
    Re: PIC18F45K22 EUSART Issue reading and echo strings 2019/05/27 06:39:28 (permalink)
    0
    Sorry for the double post but thought it worth me noting I'm started work on my GPS parser and hit a bit of a wall where some of the information comes back wrong using the same method as the string echo program.
     
    Below is my code;
    /* PIC18F45K22 GPS UART Example V1.00 
     * GPRMC Message Parsing from PC
     *
     * File: main.c
     * Author: Btommo
     * PIC: PIC18F45K22
     * OSC: 8MHz internal oscillator
     * Created on 25 May 2019
     *
    */
    #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 buffer[68];
    unsigned char hours[2];
    unsigned char minutes[2];
    unsigned char seconds[2];
    unsigned char lat_deg[2];
    unsigned char lat_min[5];
    unsigned char lat_dir[1];
    unsigned char long_deg[2];
    unsigned char long_min[5];
    unsigned char long_dir[1];
    unsigned char speed_knot[5];
    unsigned char date_day[2];
    unsigned char date_month[2];
    unsigned char date_year[2];
    unsigned char gps[]= "$GPRMC,";
    unsigned char flag,c,i;

    /******************************************************************************/
    /* 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(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++)
        {
            //while(EUSART1_is_rx_ready() == 0);// Wait for data to be received
            tmp = EUSART1_Read();
            if(tmp == Delimiter)
            {
                break;
            }
            Output[i] = tmp;
        }
        Output[i]= '\0';
        
        return i;
    }

    /******************************************************************************/
    /* Main Program */
    /******************************************************************************/
    void main()
    {
        SYSTEM_Initialize();//initialize system;pins,osc,peripherals i.e adc,TMR0 etc
        send_string("SYSTEM STARTING \r\n");
       //MAIN LOOP
          
       while(1)
        {
           //read until $GPRMC, is detected
           for(i = 0; i<=65; i++)buffer[i] = '\0';
           i = 0;
           flag = 0;
           while(flag == 0)
           {
                while(EUSART1_is_rx_ready() == 0);// Wait for data to be received
                
                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)
           {
               send_string("$GPRMC sentence found \r\n");
               read_string(buffer,'*',68);
               if(buffer[7] == 'A')
               {
                   send_string("SENTANCE 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[7] != '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("\r\n");
           }
           
        }
        return;
    }


        

     
    attached is also the result from the serial terminal which shows some of the returned data different from what is sent.
    It can also be seen that the first string sent by the micro is also shown wrong, I did change from 115200 to 9600 Baud on both terminal and micro
     
    This is what is sent;
    $GPRMC,225446,A,4916.45,N,12311.12,W,000.5,054.7,191194,020.3,E*68

    I'm loosing a lot of the information from the message.
     
    Edit: the fault with the first message was rectified with a delay at the beginning, attached is image of terminal result
    post edited by btommo - 2019/05/27 06:48:20

    Attached Image(s)

    #6
    btommo
    Junior Member
    • Total Posts : 94
    • Reward points : 0
    • Joined: 2017/07/07 02:59:33
    • Location: 0
    • Status: offline
    Re: PIC18F45K22 EUSART Issue reading and echo strings 2019/05/29 10:25:04 (permalink)
    0
    After playing with it further I am still at a loss  with the GPRMS program:/, I tried putting a delay before the read_string routine which caused the first message I sent to be missed and only 'replied' when sent again with invalid result.
     
    I also tried waiting until transmit is done after the "GPRMC sentence found" message was sent back which had no effect as well as waiting until the buffer is full, what could change;
     
    This: 225446,A,4916.45,N,12311.12,W,000.5,054.7,191194,020.3,E
     
    Into this: 22ŠrŠ’bº±000.5,054.7,191194,020.3,E
     
    Any thoughts or suggestions are welcome, as I said I am at a loss.
     
    Edit: I have been changing the oscillator frequency of the PIC and obtained a different result, the best being at 1MHz, the second to last set of messages in the attached .jpg, as you can see the random characters aren't present but still missing a lot of information, has anyone any experience of EUSART 9600 baud rate communication?
    post edited by btommo - 2019/05/29 13:25:49

    Attached Image(s)

    #7
    btommo
    Junior Member
    • Total Posts : 94
    • Reward points : 0
    • Joined: 2017/07/07 02:59:33
    • Location: 0
    • Status: offline
    Re: PIC18F45K22 EUSART Issue reading and echo strings 2019/06/05 06:06:56 (permalink)
    0
    I've started to make some more progress on this now, I've found that it's a bad idea to transmit while you are receiving, i.e. not saying $GPRMC sentance found just after '$GPRMC,' this got rid of the random characters and now the buffer received the correct information, it can see whether the sentence is valid or not.
     
    The issue I'm having now is sending back parsed information and seeing that it is parsed correctly, which I'm doing with time (the first 6 characters of buffer) so it should show as 22:54:46 but I am getting something interesting in the attached image which shows "$GPRMC," at the end of each string for some reason and also on minutes it shows hours then "$GPRMC," and a similar situation when sending back the seconds.
     
    below is my code;
     
    /* PIC18F45K22 GPS UART Example V1.00 
     * GPRMC Message Parsing from PC
     * 
     * File: main.c
     * Author: Btommo
     * PIC: PIC18F45K22
     * OSC: 8MHz internal oscillator
     * Created on 25 May 2019
     * 
     * $GPRMC message used:
     * $GPRMC,225446,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 buffer[80];
    unsigned char hours[2];
    unsigned char minutes[2];
    unsigned char seconds[2];
    unsigned char lat_deg[2];
    unsigned char lat_min[5];
    unsigned char lat_dir[1];
    unsigned char long_deg[2];
    unsigned char long_min[5];
    unsigned char long_dir[1];
    unsigned char speed_knot[5];
    unsigned char date_day[2];
    unsigned char date_month[2];
    unsigned char date_year[2];
    unsigned char gps[]= "$GPRMC,";
    unsigned char flag,c,i;

    /******************************************************************************/
    /* 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(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;
    }

    /******************************************************************************/
    /* Main Program */
    /******************************************************************************/
    void main()
    {
        SYSTEM_Initialize();//initialize system;pins,osc,peripherals i.e adc,TMR0 etc 
        __delay_ms(500);
        send_string("SYSTEM STARTING \r\n"); 
       //MAIN LOOP
          
       while(1)
        {
           //read until $GPRMC, is detected
           for(i = 0; i<=65; i++)buffer[i] = '\0';
           i = 0;
           flag = 0;
           while(flag == 0)
           {
                
                
                c = EUSART1_Read();
                if(c == gps[i] && i < 7)
                {
                    i++;
                    if(i == 7)flag=1;
                }
                else
                {
                    i = 0;
                }
               
           }
           if (flag == 1)
           {
               
                read_string(buffer,'*',80);
                if(buffer[7] == '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[7] != 'A')
               {
                   send_string("SENTANCE IS INVALID \r\n");
               }
              
               send_string(buffer);
               send_string("\r\n");
               send_string(hours);
               send_string(":");
               send_string(minutes);
               send_string(":");
               send_string(seconds);
               send_string("\r\n");
           }
           //__delay_ms(1000);
           
        }
        return;
    }


     

    Attached Image(s)

    #8
    pcbbc
    Super Member
    • Total Posts : 1189
    • Reward points : 0
    • Joined: 2014/03/27 07:04:41
    • Location: 0
    • Status: offline
    Re: PIC18F45K22 EUSART Issue reading and echo strings 2019/06/05 08:23:09 (permalink)
    +1 (1)
    You buffers for hours, minutes and seconds...
    unsigned char hours[2];
    unsigned char minutes[2];
    unsigned char seconds[2];

    ...are only 2 characters, and so do not have space for a null ('\0') terminator character at the end.
     
    Therefore this code...
                   hours[0] = buffer[0];
                    hours[1] = buffer[1];
                    minutes[0] = buffer[2];
                    minutes[1] = buffer[3];
                    seconds[0] = buffer[4];
                    seconds[1] = buffer[5];

    ...completely fills the buffer, and then when this code executes...
               send_string(hours);
               send_string(":");
               send_string(minutes);
               send_string(":");
               send_string(seconds);
               send_string("\r\n");

    ...send_string doesn't know where the end of the string is.  Therefore it just runs on through memory in a buffer overrun error until it reaches whatever byte in memory just happens to contain a null character.
     
    Fix:
    unsigned char hours[3];
    unsigned char minutes[3];
    unsigned char seconds[3];
    ...
                    hours[0] = buffer[0];
                    hours[1] = buffer[1];
                    hours[2] = '\0';
                    minutes[0] = buffer[2];
                    minutes[1] = buffer[3];
                    minutes[2] = '\0';
                    seconds[0] = buffer[4];
                    seconds[1] = buffer[5];
                    seconds[2] = '\0';

    #9
    davea
    Senior Member
    • Total Posts : 129
    • Reward points : 0
    • Joined: 2016/01/28 13:12:13
    • Location: 0
    • Status: offline
    Re: PIC18F45K22 EUSART Issue reading and echo strings 2019/06/05 09:05:42 (permalink)
    0
    are u doing this as a learning experience
    or trying to get the job DONE
    the detection of "$GPRMC," should be done in the UART RX ISR then start filling the buffer
    you should also look for the "," if there's no data there will be ",,"
     
     
    #10
    btommo
    Junior Member
    • Total Posts : 94
    • Reward points : 0
    • Joined: 2017/07/07 02:59:33
    • Location: 0
    • Status: offline
    Re: PIC18F45K22 EUSART Issue reading and echo strings 2019/06/05 09:41:04 (permalink)
    0
    Thanks pcbbc I'll give it a try.
    It's a learning experience at the moment as it would be useful to know for future projects.
    Would there be 'no data' in a valid NMEA message? Would it be better to also fill and parse the buffer in the RX ISR? I'm sort of taking it step by step first through the PC Terminal and then the next step would be GPS and show the data on LCD and monitoring what's send to the PIC on PC terminal. I'm planning on trying the NEO 6m
    post edited by btommo - 2019/06/05 09:43:12
    #11
    pcbbc
    Super Member
    • Total Posts : 1189
    • Reward points : 0
    • Joined: 2014/03/27 07:04:41
    • Location: 0
    • Status: offline
    Re: PIC18F45K22 EUSART Issue reading and echo strings 2019/06/05 10:31:45 (permalink)
    0
    btommoWould there be 'no data' in a valid NMEA message?

    Sorry, no experience with GPS receivers.  Davea is your man.
     
    Would it be better to also fill and parse the buffer in the RX ISR?

    Eventually, yes.  It is next to impossible to code all but the most basic of serial functions without using an ISR.
     
    It's probably the reason why you ran into issues "sending and receiving at the same time".  If your mainline code is locked up in a loop sending, then it is no longer listening for incoming data and will miss incoming bytes as the EUSART hardware receive buffer is only 2 bytes.
     
    So if you want reliable asynchronous sending and receiving it almost mandates an ISR.
    #12
    davea
    Senior Member
    • Total Posts : 129
    • Reward points : 0
    • Joined: 2016/01/28 13:12:13
    • Location: 0
    • Status: offline
    Re: PIC18F45K22 EUSART Issue reading and echo strings 2019/06/05 12:32:07 (permalink)
    0
    if use the ISR
    to detect and fill the buffer, set a flag when 0x0D or 0x0A is received
    and reset the scanning state of $GPSRMC 
    you have 1 second in the main to parse it (forever basically)  
    post edited by davea - 2019/06/05 12:49:13
    #13
    davea
    Senior Member
    • Total Posts : 129
    • Reward points : 0
    • Joined: 2016/01/28 13:12:13
    • Location: 0
    • Status: offline
    Re: PIC18F45K22 EUSART Issue reading and echo strings 2019/06/05 13:20:39 (permalink)
    0
    here is some 15 year old code
    written in ASM for freescale/NPX/Motorola
    it uses a get and put pointer
    that the ISR would not need 
     
     
    ;********************************
    GPS_STR FCB '$GPRMC,'
    STR_SIZ EQU $-GPS_STR ;(7)
    ;********************************
    GET_SCI LDA RX2_GET
            CMP RX2_PUT
            BEQ SCI_OUT
    ;-------------------------------
            LDHX #RX2_BUFF ; GET BASE
            TAX ; GET PNT
            LDA 0,X ; GET DATA
            INCX ; INC PNT
            PSHA ; SAVE DATA
            TXA
            AND #$3F ; WRAP AT 64
            STA RX2_GET ; SAVE PNT
            PULA ; GET DATA
            LDX GPS_BIT_CNT
            CPX #STR_SIZ
            BHS GET_DT
    ;-------
            CLRH
            CMPA GPS_STR,X
            BNE RES_GPS
            INCX
            STX GPS_BIT_CNT
            CPX #STR_SIZ
            BLO SCI_OUT
            BSET GPS_RXED,GPS_FLG ; DATA FROM GPS
            BRA SCI_OUT
    ;-------
    GET_DT BRCLR GPS_AQU,GPS_FLG,RES_GPS
    ;-------
            LDHX #RX_BUF ; GET PAGE #
            LDX RX_PNT ; GET BASE POINTER
            STA 0,X
            CMP #$0A
            BEQ CHK_F
            INCX
            STX RX_PNT
            DBNZ CHR_CNT,SCI_OUT
            BRA RES_GPS
    ;-------
    CHK_F CPX #58 ; IS $0A IN CORECT PLACE
            BLO RES_GPS ; NOPE (MISSED A CHR)
            MOV #12,CHR_CNT
            LDA #',' ; SET TO LOOK FOR ","
            LDHX #RX_BUF ; START OF GPS DATA
    FND_C CBEQ X+,CHK_A ; FIND FIRST ","
            DBNZ CHR_CNT,FND_C ; ONLY SO FAR
            BRA RES_GPS
    ;-------
    CHK_A LDA 0,X ; "A" OR "V"
            CMP #'A'
            BNE RES_GPS
            BCLR GPS_AQU,GPS_FLG ; MARK FIX'ED
            AIX #2
            STHX GPS_PNT ; START OF FIX DATA
    ;-------
    RES_GPS MOV #70,CHR_CNT
            CLRA
            STA GPS_BIT_CNT
            STA RX_PNT
    SCI_OUT RTS

    #14
    AMPS
    Super Member
    • Total Posts : 410
    • Reward points : 0
    • Status: offline
    Re: PIC18F45K22 EUSART Issue reading and echo strings 2019/06/05 21:28:19 (permalink)
    0
    why cant you use sample code if its learning
     
    https://www.electronicwings.com/pic/gps-module-interfacing-with-pic18f4550
     
     

    Amps
    *.*.*.*.*.*.*.*.*.*.*.*.*
    #15
    btommo
    Junior Member
    • Total Posts : 94
    • Reward points : 0
    • Joined: 2017/07/07 02:59:33
    • Location: 0
    • Status: offline
    Re: PIC18F45K22 EUSART Issue reading and echo strings 2019/06/07 08:47:19 (permalink)
    0
    Thanks davea and pcbbc, I'll look into creating code using an interrupt for RX over the weekend and after trying it with null at the end of the strings, see how it goes then start using a GPS, and davea tank you for the example but my assembler is a bit rusty '^^. AMPS I am creating my code from parts here and there that I researched but want to create my own code to fully understand hence starting with PC communication then moving onto GPS.
     
     
     
    post edited by btommo - 2019/06/08 01:35:02
    #16
    btommo
    Junior Member
    • Total Posts : 94
    • Reward points : 0
    • Joined: 2017/07/07 02:59:33
    • Location: 0
    • Status: offline
    Re: PIC18F45K22 EUSART Issue reading and echo strings 2019/06/08 01:40:31 (permalink)
    0
    pcbbc adding a null at the end of the strings removed the extra characters thanks (note to self always add null at end of strings) I tried to hook up my GPS module to a USB to TTL module today... I got a bunch of random characters and spaces in it although may be because its raining and I'm in a concrete house next to a window. I think I'll work on the interrupt code today...
     
    I was able to get something from placing the antenna against the window. davea you were right there are two sets of data that are missing, the 'course made good' and the magnetic variation, are these only present when there is a change in location? 
    post edited by btommo - 2019/06/08 02:58:47
    #17
    btommo
    Junior Member
    • Total Posts : 94
    • Reward points : 0
    • Joined: 2017/07/07 02:59:33
    • Location: 0
    • Status: offline
    Re: PIC18F45K22 EUSART Issue reading and echo strings 2019/06/09 06:25:34 (permalink)
    0
    I've written some code to check for '$GPRMC' and fill the buffer when it is found on the attached, I've programmed a PIC with the 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 buffer[80];
    unsigned char hours[3];
    unsigned char minutes[3];
    unsigned char seconds[3];
    unsigned char lat_deg[2];
    unsigned char lat_min[5];
    unsigned char lat_dir[1];
    unsigned char long_deg[2];
    unsigned char long_min[5];
    unsigned char long_dir[1];
    unsigned char speed_knot[5];
    unsigned char date_day[2];
    unsigned char date_month[2];
    unsigned char date_year[2];
    unsigned char gps[]= "$GPRMC,";
    unsigned char flag,c,i;



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

    /******************************************************************************/
    /* Main Program */
    /******************************************************************************/
    void main()
    {
        SYSTEM_Initialize();//initialize system;pins,osc,peripherals i.e adc,TMR0 etc 
        
        for(i = 0; i<=65; i++)buffer[i] = '\0';
        i = 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
           
           if (flag == 1) // interrupt has found '$GPRMC,' and filled buffer
           {
               
               send_string("$GPRMC sentence found \r\n");
               
               if(buffer[10] == '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("\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)
            {
                //EUSART1_RxDefaultInterruptHandler();
                if(flag == 0)
                {
                    c = EUSART1_Read();
                    if(c == gps[i] && i < 7)
                    {
                        i++;
                        if(i == 7)
                        {
                            flag=1;
                        }
                    }
                    else
                    {
                        i = 0;
                    }
                }
                if (flag == 1)
                {
                    read_string(buffer,'*',80);
                }
                
                PIR1bits.RC1IF = 0;
            } 
            
        }
    }


        

     
    In hardware the issue I am having is that the first string from the micro is sent back stating that the system is starting but don't get anything when I sent the below ASCII message as before;
     
    $GPRMC,225446.00,A,4916.45,N,12311.12,W,000.5,054.7,191194,020.3,E*68
     
    I've done some software debugging in the simulator but am unable to find the fault, I know that the interrupt is enabled properly as when I set the RC1IF flag in simulator it goes to the interrupt ISR but doesn't seem to clear on it's own and gets stuck in the EUSART1_Read routine at 'while(0 == eusart1RxCount)' generated from MCC shown below;
     
    uint8_t EUSART1_Read(void)
    {
        uint8_t readValue = 0;
        
        while(0 == eusart1RxCount)
        {
        }

        eusart1RxLastError = eusart1RxStatusBuffer[eusart1RxTail];

        readValue = eusart1RxBuffer[eusart1RxTail++];
        if(sizeof(eusart1RxBuffer) <= eusart1RxTail)
        {
            eusart1RxTail = 0;
        }
        PIE1bits.RC1IE = 0;
        eusart1RxCount--;
        PIE1bits.RC1IE = 1;

        return readValue;
    }

     
    When I make eusart1RxCount = 1, it finishes the read and goes back to the interrupt after executing the final line in the interrupt it goes back to the interrupt rather than back to the main function, I know the RC1IF is reset after reading the RCREG but have tried it both with and without resetting in the interrupt. Not sure if this is an issue I'm just getting in simulation that hardware wouldn't see but hardware doesn't seem to function.
     
    edit: I've just added a 'send string function' that's sent when the interrupt is entered and the RC!IF is set, it does it once when a sentence is sent and then doesn't respond so it seems to be stuck in the interrupt routine.
    #18
    btommo
    Junior Member
    • Total Posts : 94
    • Reward points : 0
    • Joined: 2017/07/07 02:59:33
    • Location: 0
    • Status: offline
    Re: PIC18F45K22 EUSART Issue reading and echo strings 2019/06/09 06:34:18 (permalink)
    0
    I've also just sent a string after the c = EUSART1_read(); function in the interrupt, it doesn't show up in the terminal so may be where it locks up, one sent before that line does get sent.
    #19
    davea
    Senior Member
    • Total Posts : 129
    • Reward points : 0
    • Joined: 2016/01/28 13:12:13
    • Location: 0
    • Status: offline
    Re: PIC18F45K22 EUSART Issue reading and echo strings 2019/06/09 09:04:16 (permalink)
    0
    1 your setting flag after $GPRMC
    you should fill the buffer until /r/n then set flag (and for safety a max count for data) 
    2 how are you filling buffer, I see no ++ for pointer 
    post edited by davea - 2019/06/09 09:07:42
    #20
    Page: 12 > Showing page 1 of 2
    Jump to:
    © 2019 APG vNext Commercial Version 4.5