CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

Quick and Simple RS232 string values parser 'El Parser'

 
Post new topic   Reply to topic    CCS Forum Index -> Code Library
View previous topic :: View next topic  
Author Message
vasiliok



Joined: 17 May 2011
Posts: 19
Location: Kaunas, Lithuania

View user's profile Send private message

Quick and Simple RS232 string values parser 'El Parser'
PostPosted: Fri Nov 10, 2017 2:06 am     Reply with quote

Hi All!

There is a great need to transfer values from the PC application to the microcontroller using the RS232 interface in a clear and understandable text format. Something remotely similar to JSON, but much simpler and less versatile.

This firmware called "El Parser" :-) receives string from PC, parses it and extracts values of the tokens transmitted.

Now it works with: boolean, unsigned int8 and int16, signed int8 and int16, string (array of values).

If you have time and desire join and help improve the program code!
Let's create a convenient and versatile parser together!

Please test this firmware and report your results!

String with tokens and values must be in such format:
Code:

{STRING1=1234567890; BOOL1=true; BOOL2=false;  WORD1=12345; CRC=253; WORD2=256; BYTE1=100;TEMPERATURE1=-100; LEVEL1=-32767;}


It can contain only one token:
Code:

{CRC=0;}


The main structure of string is {TOKEN=<value>;}

Pay attention for tokens and their descripted types, for signed and unsigned values!

Tested with PIC18F46K22 microcontroller.

el_parser.h
Code:

//////////////////////////////////////////////////////////////////
////                           el_parser.h                    ////
////                                                          ////
////   Author: Igor Shaev                                     ////
////   Date: November 10, 2011                                ////
////   (C) Kaunas, Lithuania                                  ////
//////////////////////////////////////////////////////////////////

// built in libraries
#include <string.h>
#include <stdlib.h>


//-----------------------------------------------------------------------------
// TOKEN TYPES
#DEFINE _boolean        1
#DEFINE _int8           2  // UNsigned int8
#DEFINE _int16          3  // UNsigned int16
#DEFINE _strng          4  // string or array of values
#DEFINE _sgnint8        5  // signed int8
#DEFINE _sgnint16       6  // signed int16

// some kind of float type wanted :-)
// please help! :-)


#DEFINE SIZE_TOKEN      15    // Sets the max token length including '\0'
#DEFINE TOTAL_TOKENS    11     // Total number of searchable tokens

#DEFINE SIZE_STRING     10    // Size for STRING type array


// Fill in 'tokens' array with your own used tokens
const char tokens[TOTAL_TOKENS][SIZE_TOKEN]={
                                       "BOOL1=\0",              // index 0
                                       "BOOL2=\0",              // index 1
                                       "BYTE1=\0",              // index 2
                                       "BYTE2=\0",              // index 3
                                       "WORD1=\0",              // index 4
                                       "WORD2=\0",              // index 5
                                       "STRING1=\0",            // index 6
                                       "STRING2=\0",            // index 7
                                       "CRC=\0",                // index 8
                                       "TEMPERATURE1=\0",       // index 9
                                       "LEVEL1=\0"              // index 10
                                                   };

// Specify type of your own tokens here, according to 'tokens' array above
const char token_type[TOTAL_TOKENS]={
                                       _boolean,               // index 0
                                       _boolean,               // index 1
                                       _int8,                  // index 2
                                       _int8,                  // index 3
                                       _int16,                 // index 4
                                       _int16,                 // index 5
                                       _strng,                 // index 6
                                       _strng,                 // index 7
                                       _int8,                  // index 8
                                       _sgnint8,               // index 9
                                       _sgnint16               // index 10
                                                   };

unsigned int8 Token[SIZE_TOKEN]; // Temporary command buffer
                                     
//-----------------------------------------------------------------------------

// ------- Real variables to assigned to TOKEN received values ----------------
// The same type of variables as assigned in 'token_type' array
int1 BOOL1;
int1 BOOL2;
unsigned int8 BYTE1;
unsigned int8 BYTE2;
unsigned int16 WORD1;
unsigned int16 WORD2;
char STRING1[SIZE_STRING];
char STRING2[SIZE_STRING];
unsigned int8 CRC;
signed int8 TEMPERATURE1;
signed int16 LEVEL1;

//-----------------------------------------------------------------------------

// Position of item find in 'search_string' function
int loc;
// String to save parsed text value
char value_string[SIZE_STRING];
//dummy variable
unsigned int16 dumm;
// flag to detect negative signed variables
int1 flag_negative;


//-----------------------------------------------------------------------------


el_parser.c
Code:

//////////////////////////////////////////////////////////////////
////                           el_parser.c                    ////
////                                                          ////
////   Author: Igor Shaev                                     ////
////   Date: November 10, 2011                                ////
////   (C) Kaunas, Lithuania                                  ////
////                                                          ////
////   Description: Set of functions to parse STRING          ////
////   received by RS232 and to assign received values to     ////
////   desired variables.                                     ////
////                                                          ////
////   Compiler version: 5.074                                ////
////                                                          ////
////   Firmware ver 1.0                                       ////
////   updated: ----                                          ////
////                                                          ////
//////////////////////////////////////////////////////////////////

#include <el_parser.h>


//=============================================================================
// Search for '{' and '}' in the Rx buffer array
//
// Function returns:
//    1 - if ready to parse the buffer
//    0 - if not ready
//=============================================================================
unsigned int8 ready_to_parse(){

   unsigned int16 i;
   unsigned int8 counter=0;
   
   for(i=0;i<buf_max;i++){
      if(buffer[i]=='{' || buffer[i]=='}')counter++;
   }
   
   if(counter==2)return 1;
      else return 0;

}
//=============================================================================
//=============================================================================





//=============================================================================
// Clears Rx buffer (fills with zeroes)
//=============================================================================
void clear_rx_buffer(){
   
   unsigned int16 i;

   for(i=0;i<buf_max;i++){
      buffer[i] = 0;
   }

   // rx buffer index
   buf_index=0;

}
//=============================================================================
//=============================================================================




//=============================================================================
//Loads token to temporary array
//=============================================================================
void load_token(unsigned int8 index){

   unsigned int8 var=0;                                        // temp index for array
   
   memset(Token,NULL,SIZE_TOKEN);                              // Reset data array index
     
      while((tokens[index][var]!=NULL)&&(var<SIZE_TOKEN)){     // Copy data from main "Strings" to commparing array.
         Token[var]=tokens[index][var];                        // Copy into temp array the strings from Main Database
         var++;                                                // index++
      }
     
}
//=============================================================================
//=============================================================================





//=============================================================================
//Searches token in the rx buffer
// Function returns:
//    1 - if token been found
//    0 - if not
//=============================================================================
int1 search_token(unsigned int8 index){

   // Loads into temp array the string to be found
   load_token(index);                     
   
   // Find String or Command in rf buffer
   if(STRSTR(buffer,Token)!=NULL)         
      return(1);                       
   else
      return(0);                       
}
//=============================================================================
//=============================================================================




//=============================================================================
// Used for debugging
// Counts TOKENS found in Rx buffer
//
// Function returns:
//    number of TOKENS found
//=============================================================================
unsigned int8 number_of_tokens_found(){

   unsigned int8 counter=0;
   unsigned int16 i;
   
   
   for(i=0;i<TOTAL_TOKENS;i++){
      //load_token(i);
      if(search_token(i)==1)counter++;
   }


   return counter;
}
//=============================================================================
//=============================================================================




//=============================================================================
// Search string in another string without built-in libraries
//
//
// Function returns: index of found string in another string
// (C) http://www.c4learn.com/c-programs/c-program-to-find-substring-of-string.html   
//=============================================================================
signed int16 search_string(char src[], char str[]) {
   int i, j, firstOcc;
   i = 0, j = 0;
 
   while (src[i] != '\0') {
 
      while (src[i] != str[0] && src[i] != '\0')
         i++;
 
      if (src[i] == '\0')
         return (-1);
 
      firstOcc = i;
 
      while (src[i] == str[j] && src[i] != '\0' && str[j] != '\0') {
         i++;
         j++;
      }
 
      if (str[j] == '\0')
         return (firstOcc);
      if (src[i] == '\0')
         return (-1);
 
      i = firstOcc + 1;
      j = 0;
   }
}
//=============================================================================
//=============================================================================





//=============================================================================
void clear_temp_buf(){
   
   unsigned int16 i;


   for(i=0;i<buf_max;i++){
      temp_buf[i] = 0;
   }
   
   
}
//=============================================================================
//=============================================================================





//=============================================================================
void copy_to_temp_buf(unsigned int16 from){

   unsigned int16 i,index;
   
   // Isvalom laikina masyva
   clear_temp_buf();
   
   index = 0;
   
   for(i=from;i<buf_max;i++){
      temp_buf[index] = buffer[i];
      index++;
   }



}
//=============================================================================
//=============================================================================




//=============================================================================
void clear_value_string(){
   
   unsigned int16 i;


   for(i=0;i<SIZE_STRING;i++){
      value_string[i] = 0;
   }
   
   
}
//=============================================================================
//=============================================================================





//=============================================================================
void extract_value_string(unsigned int16 til){

   unsigned int16 i;
   
   // Clear string where the extracted value will be placed
   clear_value_string();
   
   
   for(i=0;i<(til-1);i++){
      value_string[i] = temp_buf[i];
   }



}
//=============================================================================
//=============================================================================







//=============================================================================
//
// Searches for token and its value
// Returnes value parsed from string
// This is main parsing function
//=============================================================================
unsigned int16 assign_parsed_int_value(unsigned int8 index){

   unsigned int16 result=0;
   unsigned int16 j;
   char s[2];

         load_token(index);
         fprintf (PC, "Token '%s'\r\n", Token);
         
         loc = search_string(buffer, Token);
 /*
         // for debugging purposes
         if (loc == -1)
            fprintf(PC, "Not found\r\n\r\n");
         else
            fprintf(PC, "Found at location %d\r\n\r\n", loc + 1);
*/

         
         
         if(loc != -1){
         
           
            // Jump forvard behind found token position
            j = loc + strlen(Token);
//            fprintf(PC, "after token = %Lu\r\n\r\n", j);
         
            // Copying part of buffer[] after found <Token> to temp_buf[] array
            copy_to_temp_buf(j);
           
//            fprintf (PC, "temp_buf=:%s:\r\n", temp_buf);
         
         
           
         
            strcpy(s,";");
         
               loc = search_string(temp_buf, s);
/*
               // for debugging purposes
               if (loc == -1)
                  fprintf(PC, "; Not found\r\n\r\n");
               else
                  fprintf(PC, "; Found at location %d\r\n\r\n", loc + 1);
*/         
               
               // Extracting text value between '=' and ';'
               if(loc != -1){
                 
                  // Is tmp_buf[] --> i value_string[]
                  extract_value_string(loc + 1);
               
                  fprintf (PC, "value '%s'\r\n", value_string);
               
               
                  // assign value depending on  type in token_type[] array
                  switch(token_type[index]){
                 
                     case  1:    //boolean
                                 if(value_string[0]=='t') result = 1;
                                    else result = 0;
                                 break;
                 
                     case  2:    //unsigned int8
                                 result = atoi(value_string);
                                 break;
                     
                     case  3:    //unsigned int16
                                 result = atol(value_string);
                                 break;
                                 
                     case  4:    //string(array of values)
                                 // NOTHING TO DO HERE
                                 //  the string is in 'value_string' array
                                 // copy 'value_string' to your desired string variable
                                 break;           
                                 
                     case  5:    // signed int8
                                 if(value_string[0]!='-'){
                                    result = atoi(value_string); // positive value without '-' sign
                                    flag_negative = FALSE;
                                 }else{
                                    memmove(value_string,value_string+1,strlen(value_string));  // negative value
                                    result = atoi(value_string);
                                    flag_negative = TRUE;
                                 }
                                 break;           
                     
                     case  6:    // signed int16
                                 if(value_string[0]!='-'){
                                    result = atol(value_string); // positive value without '-' sign
                                    flag_negative = FALSE;
                                 }else{
                                    memmove(value_string,value_string+1,strlen(value_string));  // negative value
                                    result = atol(value_string);
                                    flag_negative = TRUE;
                                 }
                                 break;           
                 
                  }//switch
               
               }//if
               
               
               
         
         }

   return result; // unsigned int16 value
}
//=============================================================================
//=============================================================================




main.h
Code:

#include <18F46K22.h>
#device ADC=10
#device PASS_STRINGS=IN_RAM
#use delay(crystal=12MHz)


#define LED_RED      PIN_D0
#define LED_YELLOW   PIN_D1
#define MYG2         PIN_D2
#define MYG1         PIN_D3

#use fast_io(A)
#use fast_io(B)
#use fast_io(C)
#use fast_io(D)
#use fast_io(E)

#use rs232(uart1,baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8,stream=PC, Errors)
#use rs232(uart2,baud=9600,parity=N,xmit=PIN_D6,rcv=PIN_D7,bits=8,stream=WIFI, Errors)

#use i2c(Master,Fast,sda=PIN_C4,scl=PIN_C3,stream=pirmas) //
#use i2c(Master,Fast,sda=PIN_D5,scl=PIN_D6,stream=antras) //




#DEFINE  interface_used PC
#DEFINE  interrupt_used INT_RDA
#DEFINE  buf_max  256            // Rx buffer length

unsigned int8 datain, data_from_WIFI;

// Rx buffer
char buffer[buf_max];
unsigned int8 buf_index=0;

// array for parsing, proccesing and searching
char temp_buf[buf_max];



main.c
Code:

#include <main.h>
#include <el_parser.c>
#include <interrupts.c>



//*****************************************************************************
void main(){


   //disable_interrupts(GLOBAL);
 
   set_tris_A(0b00000000);
   set_tris_B(0b00000000);
   set_tris_C(0b10000000); 
   set_tris_D(0b10001100);
   set_tris_E(0b00000000);

   // Pull-up rezistory knopok
   // Podkliuchaem po neobhodimosti
   //port_b_pullups(0b00001100);
   
   setup_ccp1(CCP_OFF);
   setup_ccp2(CCP_OFF);
   setup_ccp3(CCP_OFF);

   setup_adc_ports(NO_ANALOGS);   
   SETUP_ADC(ADC_OFF);
   
   delay_ms(2000);

   //--------------------------------------------------------------------------
   //clear_interrupt(INT_EXT_H2L);
   clear_interrupt(INT_RDA);
   //clear_interrupt(INT_RDA2);

   //enable_interrupts(INT_EXT_H2L);
   //EXT_INT_EDGE(H_TO_L); 
   enable_interrupts(INT_RDA);
   //enable_interrupts(INT_RDA2);
 
   enable_interrupts(GLOBAL);
   //--------------------------------------------------------------------------

  while(TRUE){
     
      // for testing RS232 interface :-)
      if(input(MYG1)==0){
         output_toggle(LED_YELLOW);
         fprintf(PC, "MYG1 pressed successfully!\r\n");
         delay_ms(300);
      }
     
      // for testing RS232 interface :-)
      if(input(MYG2)==0){
         output_toggle(LED_RED);
         fprintf(WIFI, "MYG2 pressed successfully!\r\n");
         delay_ms(300);
      }
     
     
     
     
      // Check if values string received and parse it
      if(ready_to_parse()){
         fprintf(PC, "String received!\r\n");
         fprintf(PC, "Tokens qty=%u\r\n\r\n", number_of_tokens_found() );

         
         //--------------------------------------------------------------------
         // Assign parsed value to desired variable if token found
         if(search_token(8)){
            CRC=assign_parsed_int_value(8); // Token with index8 (CRC) value assign to the real CRC variable
            fprintf(PC, "CRC = %u\r\n\r\n", CRC );
         }else{ fprintf(PC, "CRC not found!\r\n\r\n" );}
         //--------------------------------------------------------------------
       
         
         //--------------------------------------------------------------------
         // Assign parsed value to desired variable if token found
         if(search_token(5)){
            WORD2=assign_parsed_int_value(5); // Token with index5 (WORD2) value assign to the real WORD2 variable
            fprintf(PC, "WORD2 = %Lu\r\n\r\n", WORD2 );
         }else{ fprintf(PC, "WORD2 not found!\r\n\r\n" );}
         //--------------------------------------------------------------------
       
       
         //--------------------------------------------------------------------
         // Assign parsed value to desired variable if token found
         // for boolean, int8 and int16 type variables
         if(search_token(4)){
            WORD1=assign_parsed_int_value(4); // Token with index4 (WORD1) value assign to the real WORD1 variable
            fprintf(PC, "WORD1 = %Lu\r\n\r\n", WORD1 );
         }else{ fprintf(PC, "WORD1 not found!\r\n\r\n" );}
         //--------------------------------------------------------------------
         
         //--------------------------------------------------------------------
         // Assign parsed value to desired variable if token found
         if(search_token(1)){
            BOOL2=assign_parsed_int_value(1); // Token with index1 (BOOL1) value assign to the real BOOL1 variable
            fprintf(PC, "BOOL2 = %u\r\n\r\n", BOOL2 );
         }else{ fprintf(PC, "BOOL2 not found!\r\n\r\n" );}
         //--------------------------------------------------------------------       

         
         //--------------------------------------------------------------------
         // Assign parsed value to desired variable if token found
         if(search_token(3)){
            BYTE2=assign_parsed_int_value(3); // Token with index3 (BYTE2) value assign to the real BYTE2 variable
            fprintf(PC, "BYTE2 = %u\r\n\r\n", BYTE2 );
         }else{ fprintf(PC, "BYTE2 not found!\r\n\r\n" );}
         //--------------------------------------------------------------------
         
         
         //--------------------------------------------------------------------
         // Assign parsed value to desired variable if token found
         if(search_token(2)){
            BYTE1=assign_parsed_int_value(2); // Token with index2 (BYTE1) value assign to the real BYTE1 variable
            fprintf(PC, "BYTE1 = %u\r\n\r\n", BYTE1 );
         }else{ fprintf(PC, "BYTE1 not found!\r\n\r\n" );}
         //--------------------------------------------------------------------
         
         
         //--------------------------------------------------------------------
         // Assign parsed value to desired variable if token found
         if(search_token(7)){
            dumm=assign_parsed_int_value(7); // Token with index7 (STRING2) value assign to the real STRING2 array
            strcpy(STRING2, value_string);
            fprintf(PC, "STRING2='%s'\r\n\r\n", STRING2 );
         }else{ fprintf(PC, "STRING2 not found!\r\n\r\n" );}
         //--------------------------------------------------------------------
         
         
         //--------------------------------------------------------------------
         // Assign parsed value to desired variable if token found
         if(search_token(6)){
            dumm=assign_parsed_int_value(6); // Token with index6 (STRING1) value assign to the real STRING1 array
            strcpy(STRING1, value_string);
            fprintf(PC, "STRING1='%s'\r\n\r\n", STRING1 );
         }else{ fprintf(PC, "STRING1 not found!\r\n\r\n" );}
         //--------------------------------------------------------------------
       
       
         //--------------------------------------------------------------------
         // Assign parsed value to desired variable if token found
         if(search_token(0)){
            BOOL1=assign_parsed_int_value(0); // Token with index0 (BOOL1) value assign to the real BOOL variable
            fprintf(PC, "BOOL1 = %u\r\n\r\n", BOOL1 );
         }else{ fprintf(PC, "BOOL1 not found!\r\n\r\n" );}
         //--------------------------------------------------------------------         
         
         
         //--------------------------------------------------------------------
         // Assign parsed value to desired variable if token found
         if(search_token(9)){
            TEMPERATURE1=assign_parsed_int_value(9); // Token with index9 (TEMPERATURE1) value assign to the real TEMPERATURE1 variable
            // positive or negative?
            if(flag_negative == TRUE)TEMPERATURE1 = TEMPERATURE1 * -1;
            fprintf(PC, "TEMPERATURE1 = %d\r\n\r\n", TEMPERATURE1 );
         }else{ fprintf(PC, "TEMPERATURE1 not found!\r\n\r\n" );}
         //--------------------------------------------------------------------
         
         
         //--------------------------------------------------------------------
         // Assign parsed value to desired variable if token found
         if(search_token(10)){
            LEVEL1=assign_parsed_int_value(10); // Token with index10 (LEVEL1) value assign to the real LEVEL1 variable
            // positive or negative?
            if(flag_negative == TRUE)LEVEL1 = LEVEL1 * -1;
            fprintf(PC, "LEVEL1 = %Ld\r\n\r\n", LEVEL1 );
         }else{ fprintf(PC, "LEVEL1 not found!\r\n\r\n" );}
         //--------------------------------------------------------------------
         
         
         
         // Do not forget to clear rx buffer after parsing and assigning is done
         clear_rx_buffer();
      }
     
     
     

   
   }//WHILE END



}// MAIN END
//*****************************************************************************


interrupts.c
Code:

/*
//************************** INTERRUPTS ***************************************
// 1 hz pulses from RTC ic MCP7940N to RB0
#INT_EXT
void  INT0_isr(void){
   output_toggle(CPU_LED);
   
   
   clear_interrupt(INT_EXT);
   clear_interrupt(INT_EXT_H2L);
}
//*****************************************************************************   
*/



//*****************************************************************************
// RS232, "PC"
#INT_RDA
void  RDA_isr(void){

   output_toggle(LED_YELLOW);   

   // Read BYTE from RxD buffer
   datain = fgetc(interface_used);
   
   buffer[buf_index] = datain;
   buf_index++;
   if(buf_index == buf_max) buf_index=0;


   clear_interrupt(interrupt_used);

}
//*****************************************************************************



//*****************************************************************************
// RS232 "ESP8266 wifi modulis"
#INT_RDA2
void  RDA2_isr(void){

   output_toggle(LED_RED);



   data_from_WIFI = fgetc(WIFI);
 
   //WIFI reply to PC console if enabled (DEBG=1)
   fputc(data_from_WIFI,PC);

/*
  Rec_Buf[buf_index] = data_from_WIFI;
 
  buf_index++;
 
  if(buf_index>=(Buf_Max-1)){
    buf_index = 0;
  }

  flag_received_WIFI = 1;
 
*/

  clear_interrupt(INT_RDA2);
   
   
}
//*****************************************************************************



/*
//*****************************************************************************
// CPU_LED blinker and hardware PULSE COUNTER reader
#INT_TIMER6
void  TIMER6_isr(void){

   timerio_daliklis++;
   
   if (timerio_daliklis == 50){ //~1sek periodas
      timerio_daliklis=0;

   }
}
//*****************************************************************************
*/
asmboy



Joined: 20 Nov 2007
Posts: 2128
Location: albany ny

View user's profile Send private message AIM Address

the ESP8266 code
PostPosted: Tue Sep 21, 2021 2:34 pm     Reply with quote

ESP8266- that wifi chip is rated to 72Mbps - i tried this code with a 2MB data rate , with no joy at all. further testing says you can't safely go much beyond 100 Kbps and with short packets -plus delays between blocks -without having dropped and malformed characters AND /OR buffer over runs in the data stream. It really can't handle steady no breaks- data safely as written. The coms implied by this program's needs are too lightweight and really need modification . Running the K22 at 12mhz with no PLL is not so helpful either. 16mhz MCLK and PLL and then you are getting somewhere.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> Code Library All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
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