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

Comparing two strings over RS232

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
sean_tpc



Joined: 21 Aug 2008
Posts: 10

View user's profile Send private message

Comparing two strings over RS232
PostPosted: Tue Sep 23, 2008 5:40 am     Reply with quote

As a newbie specially on PIC-C programming, I have difficulty on comparing two strings of characters received form pc via RS232. Here's some part of my code:
Code:
/
/*******************************************************************************
   Variables
*******************************************************************************/
byte DATA_IN =0;              //write data register
byte DATA_OUT =0;             //read data register
byte DATA_RCV =false;         //mask for DATA_IN recieve
byte BANK1 =0;                //pntr for EEPROM read @ bank 1
byte BANK2 =0;                //pntr for EEPROM read @ bank 2
byte SAME  =FALSE;            //mask for same string recieve

byte i_1 = 0xA0;              //start offset of user data bank register
byte i_2 = 0;                 //end offset of user data bank register
byte i_3 = 0x120;


*******************************************************************************
   Interrupt from RS232
*******************************************************************************/
#int_RDA
void RS232_isr(){

   DATA_IN = getc();                      //get character from RS232
   write_bank(1,i_1, DATA_IN);            //save to bank1
   putc(DATA_IN);                         //send recieve byte
   i_2 = i_1;                             //Increment 'till end
   
   DATA_RCV = TRUE;                       //mask DATA_IN recieve
   output_high(RCV_CHAR_STAT);
}

/*******************************************************************************
   Process data receive over RS232
*******************************************************************************/
void CHECK_DATA_RCV(){
   
   byte i=0;
   
   if (DATA_RCV==TRUE){                //Do i recieve data from RS232?
      delay_ms(100);                      //..yes
   
   /**************************************************************
   /  Check for the first string recieve                         /
   /*************************************************************/
      BANK1=0xB2;
      BANK2=0x121;
   
         if (read_bank(2,BANK2)==0){
            i_1=0xA0;
            i_3=0x120;
     
            do{
               DATA_OUT = read_bank(1,i_1++);
               if (i_1>0xB2)                      //start copy at address 0xB2
                  write_bank(2,i_3++,DATA_OUT);  //save to bank2
               } while(i_1!=i_2);
         }
    /**************************************************************
    / Compare 2 strings , if not the same do something            /
    /*************************************************************/
   
         else{
            BANK1 = 0xB2;             // set pntr for read EEPROM operation
            BANK2 = 0x120;
            i=0;
            do{                         // compare string recieve from previous one
               i++;
               if(read_bank(1,BANK1++) == read_bank(2,BANK2++))
                    SAME =0 ;      // the same string recieve ?
               else { SAME =1 ;
                     i =15;        }
              }while(i !=15 );

        if (SAME ==0 )           // if the same string then do nothing!.....
              { ; }
        else
             {SAME =0 ;          // clr flag
             lcd_putc("Strings not the same");
              i_1 = 0xA0  ;
              i_3 = 0x120 ;
               do{                   // save new string to from BANK_1 to BANK_2
                    DATA_OUT = read_bank(1,i_1++);            // read byte @ BANK_1
                    if ( i_1 >0xB2 ){
                       write_bank(2,i_3++,DATA_OUT);           //Save to Bank2
                       }
                    else;
                 } while(i_1 !=i_2);
             }
         }
      DATA_RCV=FALSE;
   }
}


I'm using CCS ver 4.074
MCU: PIC16F876
OCS 16Mhz
Wayne_



Joined: 10 Oct 2007
Posts: 681

View user's profile Send private message

PostPosted: Tue Sep 23, 2008 7:06 am     Reply with quote

Where is the i_1 increment in your isr ?

You also use i_1 var in your CHECK_DATA_RCV() routine. If a char came in on the rs232 during this routine it would corrupt your buffer.
Ttelmah
Guest







PostPosted: Tue Sep 23, 2008 9:13 am     Reply with quote

Another problem. You seem to be trying to write the RS232 data to EEPROM.
EEPROM writes are _slow_. Typically 4mSec, and as much as 8mSec. You don't show the baud rate, but at 9600bps, a character can arrive every 1.04mSec. This will result in lost data (and possibly UART lock up). Also the write life of EEPROM is relatively low. Writing one byte every 4mSec, will destroy the EEPROM, in typically 400 seconds....

Best Wishes
sean_tpc



Joined: 21 Aug 2008
Posts: 10

View user's profile Send private message

PostPosted: Wed Sep 24, 2008 2:21 am     Reply with quote

Thanks a lot guys. Here's my working code: Any suggestion the best way to do it? Maybe a simple example will be a great help. This code below can compare string of text w/ 33 characters only
Code:
#include <16F876.h>
#device icd =true
#fuses HS,NOWDT,NOPROTECT,NOLVP
#ocs 16 Mhz
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)

#include <LCD_Driver876.h>

BYTE value_1       = 0;               // pntr for EEPROM read @ Bank_1
BYTE value_2       = 0;               // pntr for EEPROM read @ Bank_2

BYTE data_in       = 0;               // data register (write)
BYTE data_out      = 0;               // data register (read)
BYTE byte_recieve  = 0;               // mask recieve_byte operation

BYTE i_1           = 0xA0;            // start recieve byte pointer register
BYTE i_2           = 0;               // end recieve byte pointer register
BYTE i_3           = 0x120;
BYTE SAME_TXT      = false;           //Flag to compare recieve string

#define SYS_LED      PIN_B3           //System LED indicator
#define RCV_STAT     PIN_B2           //Recieve character indicator             

/*************~-MCU Status indicator-~*************************************************************/
void MCU_STAT(){
   output_toggle(SYS_LED);
   delay_ms(200);
}

void EXECUTE_SOMETHING(){
   lcd_putc("\fNot the same\nstring recieve!");
   
}

void NO_EXECUTE(){
   lcd_putc("\fSame string\nrecieved....");
}

/*************~-Interrupt from RS232-~*************************************************************/
#int_rda                              //interrupt for Rx
void serial_isr(){
     data_in = getc();                //Get character from rs232
     write_bank(1,i_1++,data_in);     //Save to BANK_1
     putc( data_in );                 //Send string of characters to PC2
     i_2 = i_1;                       //increment begin(i_1) to end (i_2) pointer
     byte_recieve = 1;                //mask recieve operation
}

/************~-Recieved string processing function-~***********************************************/
void CHK_STRINGS(){
 int i =0;

 if(byte_recieve == 1)                //do we recieve byte?
 {                                    //yes.
     delay_ms(100);

/*************~-Check for first recieve characters-~***********************************************/
           value_1 = 0xB2;
           value_2 = 0x121;           //if from power up,.. first recieve ?
     if ( read_bank(2,value_2) == 0 )
            {
                i_1 = 0xA0  ;
                i_3 = 0x120 ;
                do{                                            // save batch to BANK_1
                      data_out = read_bank(1,i_1++);           // read byte @ BANK_1
                      if ( i_1 >0xB2 )                         // start copy at address 0xB2
                         {   write_bank(2,i_3++,data_out);   }  // save to BANK_2
                      else;
                  } while(i_1 !=i_2);         
                                               
            }

/*************~-Compare two strings.. if not the same execute something-~**************************/
     else{
          value_1 = 0xB2;                                   //set pntr for read EEPROM operation
          value_2 = 0x120;
          i=0;
          do{                                               //compare string recieve from previous one
              i++;
              if   ( read_bank(1,value_1++)   == read_bank(2,value_2++)   )
                   { SAME_TXT =false ;  }                   //the same string recieve ?
              else { SAME_TXT =true ;
                     i =15;        }

           }while(i !=15 );


        if (SAME_TXT ==false)                            //if the same string then do nothing!.....
            NO_EXECUTE();     
       
        else{
            SAME_TXT =false ;                            //clr flag
            EXECUTE_SOMETHING();
         
              i_1 = 0xA0  ;
              i_3 = 0x120 ;
               do{                                       //save new batch to from BANK_1 to BANK_2
                    data_out = read_bank(1,i_1++);        // read byte @ BANK_1
                    if ( i_1 >0xB2 )
                       {write_bank(2,i_3++,data_out);   }  // save to BANK_2
                    else;
                 }while(i_1 !=i_2);

             }
     }

      i_1 = 0xA0;
      i_2 = 0;                                           //clr the two pointer
      i_3 = 0x120;
      byte_recieve = 0;                                  //unmask recieve_byte operation

      output_high(RCV_STAT);                             //set character recieve LED on
      delay_ms(800);
      output_low(RCV_STAT);                              //clr character recieve LED on   
  }
}
/*************************~-MAIN PROGRAM-~*********************************************************/
#zero_ram                             
void main(){
   lcd_init();
   enable_interrupts(global);         
   enable_interrupts(int_rda);         
 
   
   for(;;){
      MCU_STAT();                      //MCU status indicator
      CHK_STRINGS();                   //Check recieve strings from pc1
      }
}
sean_tpc



Joined: 21 Aug 2008
Posts: 10

View user's profile Send private message

PostPosted: Fri Sep 26, 2008 3:13 am     Reply with quote

Any good suggestions!? Maybe a good example will help....pls
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Fri Sep 26, 2008 9:30 am     Reply with quote

Some remarks on your code:
Code:
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)
Add the ERRORS directive to this line. Doing so causes the compiler to create code for clearing the UART's error flags on every call to getc(). Without this keyword you are running the risk of the UART stopping on receive buffer overflow (only 3 characters).

Code:
BYTE i_3           = 0x120;
This is a bug, the maximum value fitting a byte is 0xFF.

Code:
BYTE value_1       = 0;               // pntr for EEPROM read @ Bank_1
BYTE value_2       = 0;               // pntr for EEPROM read @ Bank_2
Call the things by their right names. These are pointers to RAM banks, not to EEPROM.

Code:
 if(byte_recieve == 1)                //do we recieve byte?
 {                                    //yes.
     delay_ms(100);
Why is the delay of 100ms here? It is wasting processor time. Besides that, in the mean time more data is received and you might even get a receive buffer overflow, resulting in data loss.

The use of the functions read_bank and write_bank is only recommended for situations with special memory requirements. Problem of using these functions is that they are very low level and the compiler can not warn you for errors.
Your PIC16F876 can easily handle RAM buffers up to 80 characters so there is no need to use these low level functions. Simply allocate RAM by using an array:
Code:
char myBuffer[30];
This reserves memory for 30 bytes.

Enable the compiler to use 16 bit pointers. This will allow for larger RAM buffers.
Code:
#device *=16


Another improvement to your program would be to have the received string start and stop with a known character. This makes it a lot easier to synchronize the sender and receiver. For example, have the sender start the string with ASCII value STX (Start of Text, 0x02) and end the string with a linefeed character (LF, 0x0A).


Here is a test program that will display a text every time a new message is received. The message should start with a 0x02 and end with a linefeed (0x0A) character. The program compiles but is not tested.
Code:
#include <16F876.h>
#device icd =true
#device *=16
#fuses HS, NOWDT, NOLVP, NOPROTECT
#ocs 16 Mhz
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)

#include <string.h>

enum RECEIVE_STATES  {IDLE, RECEIVING};
enum RECEIVE_STATES receive_state = IDLE;

#define STX           0x02
#define LINEFEED      0x0A
#define MAX_STR_LEN   40

char RxBuff[MAX_STR_LEN + 1];           // +1 for terminating zero.
int8 rxBuffPtr = 0;

int8 new_string_received = FALSE;
char StringBuffer[MAX_STR_LEN + 1];     // +1 for terminating zero.


// Compare the new received string to the previous string.
// If a new string is found than the string is copied for comparison next time.
void CheckForNewString()
{
  if (strcmp(RxBuff, StringBuffer) != 0)
  {
    // New string found, copy the string and set flag.
    strcpy(StringBuffer, RxBuff);
    new_string_received = TRUE;
  }
}   

// Interrupt from RS232 receiver
#int_rda
void serial_isr()
{
  char data_in;
 
  data_in = getc();                // Get character from rs232
  putc( data_in );                 // Echo character to PC2

  switch (receive_state)
  {
    case IDLE:
      if (data_in == STX)
        receive_state = RECEIVING;
      break;
    case RECEIVING:
      if (data_in == LINEFEED)    // End of string terminator found?
      {
        RxBuff[rxBuffPtr] = '\0';     // Terminate string
        CheckForNewString();
        receive_state = IDLE;
        rxBuffPtr = 0;
      } 
      else
      {
        // Only process readable characters
        if ((data_in >= 0x20) && (data_in < 127))
        {
          if (RxBuffPtr < MAX_STR_LEN)
          {
            RxBuff[rxBuffPtr] = data_in;
            rxBuffPtr++;
          }
        } 
      } 
      break;
  }
}


void main()
{
  StringBuffer[0] = 0;  // Terminate string.
 
  enable_interrupts(int_rda);         
  enable_interrupts(global);         

  while (TRUE)
  {
    if (new_string_received == TRUE)
      printf("New string found: %s\n", StringBuffer);
  }
}
sean_tpc



Joined: 21 Aug 2008
Posts: 10

View user's profile Send private message

PostPosted: Fri Sep 26, 2008 4:20 pm     Reply with quote

thank you so much guys....!Smile
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion 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