[SOLVED] Problem in strlen calculation and comparision

Go To Last Post
13 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi all,

   Good Day! I have two problems.

Problem 1: I have problem in strlen calculation. I am trying to calculate CRC16 for a FRAME with initial value of CRC = 0xFFFF. In this code if i initialized unsigned char array as global then i am getting correct strlen value. after sending a frame i am getting strlen value as 62. it is giving the value 62 = 4 + 58(frame length). In this if i initialized unsigned char as local then i am getting strlen is 10. I am allocating only 4 byte but how i am getting 10 as strlen?

 

Frame Format:

*0,0,0,0,1,6,1,2,3,4,5,6,2,1,1,1,B,2,2,1,0.00,00.0,0.00,0#

 

Problem 2: How to compare crc0 value with crc1 value. crc0 is unsigned int and crc1 is unsigned char array. in the below code 

if(crc0 == crc1) Is this comparison is correct or not.

 Even i tried with pointers.

can you please give me a guidance to get a solution for these two problems.

Code is:

 

/*****************************************************
This program was produced by the
CodeWizardAVR V2.05.3 Standard
Automatic Program Generator
© Copyright 1998-2011 Pavel Haiduc, HP InfoTech s.r.l.
http://www.hpinfotech.com

Project :
Version :
Date    : 4/10/2015
Author  : Dev6
Company : sass
Comments:


Chip type               : ATmega128
Program type            : Application
AVR Core Clock frequency: 14.745600 MHz
Memory model            : Small
External RAM size       : 0
Data Stack size         : 1024
*****************************************************/

#include <mega128.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <delay.h>

unsigned char rx_rcv=0, rcv_comp=0;
unsigned char uartin_data[256];
unsigned char temp_uartin[26];
unsigned int uartin_length=0;



#ifndef RXB8
#define RXB8 1
#endif

#ifndef TXB8
#define TXB8 0
#endif

#ifndef UPE
#define UPE 2
#endif

#ifndef DOR
#define DOR 3
#endif

#ifndef FE
#define FE 4
#endif

#ifndef UDRE
#define UDRE 5
#endif

#ifndef RXC
#define RXC 7
#endif

#define FRAMING_ERROR (1<<FE)
#define PARITY_ERROR (1<<UPE)
#define DATA_OVERRUN (1<<DOR)
#define DATA_REGISTER_EMPTY (1<<UDRE)
#define RX_COMPLETE (1<<RXC)

// USART0 Receiver buffer
#define RX_BUFFER_SIZE0 256
char rx_buffer0[RX_BUFFER_SIZE0];

#if RX_BUFFER_SIZE0 <= 256
unsigned char rx_wr_index0,rx_rd_index0,rx_counter0;
#else
unsigned int rx_wr_index0,rx_rd_index0,rx_counter0;
#endif

// This flag is set on USART0 Receiver buffer overflow
bit rx_buffer_overflow0;

// USART0 Receiver interrupt service routine
interrupt [USART0_RXC] void usart0_rx_isr(void)
{
    char status,data;
    status=UCSR0A;
    data=UDR0;

    if(data == '*')
    {
        rcv_comp = 0;
        rx_wr_index0 = 0;
        rx_rcv = 1;
        uartin_length = 0;
    }

    if(data == '#')
    {
        rcv_comp = 1;
    }

    if ((status & (FRAMING_ERROR | PARITY_ERROR | DATA_OVERRUN))==0)
    {
       rx_buffer0[rx_wr_index0++]=data;
    #if RX_BUFFER_SIZE0 == 256
       // special case for receiver buffer size=256
       if (++rx_counter0 == 0) rx_buffer_overflow0=1;
    #else
       if (rx_wr_index0 == RX_BUFFER_SIZE0) rx_wr_index0=0;
       if (++rx_counter0 == RX_BUFFER_SIZE0)
       {
          rx_counter0=0;
          rx_buffer_overflow0=1;
       }
    #endif
    }
}

#ifndef _DEBUG_TERMINAL_IO_
// Get a character from the USART0 Receiver buffer
#define _ALTERNATE_GETCHAR_
#pragma used+
char getchar(void)
{
char data;
while (rx_counter0==0);
data=rx_buffer0[rx_rd_index0++];
#if RX_BUFFER_SIZE0 != 256
if (rx_rd_index0 == RX_BUFFER_SIZE0) rx_rd_index0=0;
#endif
#asm("cli")
--rx_counter0;
#asm("sei")
return data;
}
#pragma used-
#endif


unsigned int crc16_update_little_endian(unsigned int crc, unsigned char arr[])
{
    // Least significant bit first (little-endian)
   // x^16+x^15+x^2+1 = 1010 0000 0000 0001 (1) = 0xA001  (CRC 16 POLYNOMIAL REVERSED)

    unsigned int i,j;

    for(j =0; j<26/*strlen(arr)*/; ++j)
    {
        crc ^= arr[j];
        for (i = 0; i < 8; ++i)   // Assuming 8 bits per byte
        {
            if (crc & 0x0001)   // if rightmost (most significant) bit is set
            {
                crc = (crc >> 1) ^ 0xA001;
            }
            else
            {
                crc = (crc >> 1);
            }
        }
        //printf("\nj: %d, \tcrc: %X", j,crc);
    }
    return crc;
}


void uartin_function(void)
{
    unsigned int i=0,j=0,k=0;
    unsigned int crc0 = 0xFFFF;   //0x0000
    unsigned char crc1[4] = {'0','0','0','0'};
    //unsigned char *pcrc = "0000";
    //pcrc = malloc(4);

    //printf("\nstrlen_crc1: %d, \tstrlen_a: %d", strlen(crc1),strlen(a));
//    printf("\nstrlen_crc1: %d", strlen(crc1));

    //uartin_length = rx_wr_index0;

    if(rx_rcv == 1)
    {
        if(rcv_comp == 1)
        {
            strcpy(uartin_data,rx_buffer0);
            puts(uartin_data);

            for(i=1; i<32;)
            {
                temp_uartin[j] = uartin_data[i];
                //printf("\ntemp_uartin[%d]: %c", j,temp_uartin[j]);
                i+=2;
                ++j;
            }
            for(i=41; i<57;)
            {
                temp_uartin[j] = uartin_data[i];
                if((i==41)||(i==44)||(i==47)||(i==49)||(i==51)||(i==56))
                {
                    i+=2;
                }
                else
                {
                    ++i;
                }
            }
            crc0 = crc16_update_little_endian(crc0, temp_uartin);
            //printf("\ncrc0 = %X", crc0);

            for(i=33; i<40;)
            {
                crc1[k] = uartin_data[i];
                //*(pcrc) = uartin_data[i];
                //printf("\ncrc1[%d]: %c", k,crc1[k]);
                i+=2;
                ++k;
                //++pcrc;
            }
            puts(crc1);
            //pcrc=crc1;
            //puts(pcrc);

            if(crc0 == crc1)
            {
                puts("\nTRUE");
                puts(crc1);
            }
            else
            {
                puts("\nFALSE");
                puts(crc1);
            }
        }
        rcv_comp = 0;
    }
    rx_rcv = 0;
}      // end of uartin_function


void main(void)
{
// Declare your local variables here

// Input/Output Ports initialization
// Port A initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T
PORTA=0x00;
DDRA=0x00;

// Port B initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T
PORTB=0x00;
DDRB=0x00;

// Port C initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T
PORTC=0x00;
DDRC=0x00;

// Port D initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T
PORTD=0x00;
DDRD=0x00;

// Port E initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T
PORTE=0x00;
DDRE=0x00;

// Port F initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T
PORTF=0x00;
DDRF=0x00;

// Port G initialization
// Func4=In Func3=In Func2=In Func1=In Func0=In
// State4=T State3=T State2=T State1=T State0=T
PORTG=0x00;
DDRG=0x00;

// USART0 initialization
// Communication Parameters: 8 Data, 1 Stop, No Parity
// USART0 Receiver: On
// USART0 Transmitter: On
// USART0 Mode: Asynchronous
// USART0 Baud Rate: 9600
UCSR0A=0x00;
UCSR0B=0x98;
UCSR0C=0x06;
UBRR0H=0x00;
UBRR0L=0x5F;

// Global enable interrupts
#asm("sei")

    puts("\nstart");


while (1)
      {
           uartin_function();
           delay_ms(2000);
      }
}

 

This topic has a solution.

-----------------------

Thanks & Regards,

Sasi

-----------------------

GO GREEN

Last Edited: Tue. Apr 21, 2015 - 11:03 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

sasireka wrote:
crc0 is unsigned int and crc1 is unsigned char array.

Obviously (surely?), they need to be in the same form to directly compare them.

 

So you have 2 choices:

 

  1. Convert crc1 to unsigned int, and do an unsigned int comparison;
  2. Convert crc0 to an unsigned char array, and compare the two arrays.

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

sasireka wrote:
I am allocating only 4 byte

Well that is a major bug right there!

 

Quote:
but how i am getting 10 as strlen?

Because strlen just searches through memory until it finds a bytes with value 0 - which it takes as the string terminator.

 

You have a classic buffer overrun error!

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks Awneil. I will convert unsigned int to unsigned char array then i will  do compare it.

-----------------------

Thanks & Regards,

Sasi

-----------------------

GO GREEN

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

okay how to solve this buffer overrun error?

-----------------------

Thanks & Regards,

Sasi

-----------------------

GO GREEN

This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

You do know that strlen() only works on 0x00 terminated character strings don't you?

 

The implementation of strlen() is basically something like:

int strlen(char * str) {
    int len = 0;
    while (*str++) {
        len++;
    }
    return len;
}

So if you try

strlen("hello");

then 'len' starts at 0. The first "*str" is 'h' which is non-0 so it does len++, same for 'e' and len++ and so on until 'o' when len reaches 5. For the next *str the value is the "hidden" 0x00 that follows 'o' in "hello". That causes the while() loop to end so it returns len==5.

 

This only works because there is that hidden 0x00 beyond 'o'.

 

Now if I had written:

char text[5] = "hello";
strlen(text);

this is a very tricky situation. When you create a character array with a very exact dimension ([5] in this case) then the initialiser you give it ("hello") is exactly 5 characters long C has no room to add the terminating 0x00 at the end. As such when you call strlen() and pass it this text[] array it is unpredictable what will happen. The text[] array itself certainly will not have the 0x00 that strlen() looks for at the end. If you are lucky it could be that "hello" is positioned in RAM in just such a way that the very next byte happens to be 0x00 and then strlen () will return 5. However the next 0x00 in memory could be 73 bytes further on. In which case strlen() will return 78. Or it could be any seemingly random length.

 

You have made exactly this mistake when you used:

    unsigned char crc1[4] = {'0','0','0','0'};

The [4] there only has room for exactly the four '0' characters but no room for a terminating 0x00 that strlen() will need to see. So when you call:

    //printf("\nstrlen_crc1: %d, \tstrlen_a: %d", strlen(crc1),strlen(a));

or similar the result will be unpredictable. Maybe try:

   unsigned char crc1[5] = {'0','0','0','0', 0x00};

and the strlen() will be 4. Or more generally forget passing the dimension and let C work it out for you:

   unsigned char crc1[] = {'0','0','0','0', 0x00};

C can see there are 5 bytes there so it will make the array 5 bytes long and you are guaranteed that the 0x00 that MUST exist for strlen() will be in place.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

Make the buffer (at least) the right size!

 

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 2

PS You do seem to post a lot of questions that are falling over the very most basic questions of C programming. Using an AVR makes it very tricky to see this kind of error. To learn the basics of C programming I'd highly recommend you write PC programs in C using a powerful IDE like Visual Studio or Pelles or Code::Blocks. You can then very easily using printf() to see what's going on and, when that's not enough to determine a problem they all have very powerful and easy to use debuggers. Also, because you are building straight to .exe files on the PC there's no issues about needing to wire up chips or burn code and it is MUCH, MUCH easier to instantly debug.

 

When you have learned C then using it on an AVR should be trivial.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

yes clawson. Same mistake.

 

unsigned char crc1[5] = "0000";

i tried like above now i got strlen = 4.

-----------------------

Thanks & Regards,

Sasi

-----------------------

GO GREEN

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi awneil,

  Good Day! I have converted hex value to char array and then i compared using strcmp. Now it is working good. thanks a lot. 

-----------------------

Thanks & Regards,

Sasi

-----------------------

GO GREEN

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks a lot awneil and clawson for great help to analyse my mistake. thanks  to all. smiley

-----------------------

Thanks & Regards,

Sasi

-----------------------

GO GREEN

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You're welcome - thanks for the feedback.

 

As you know you have 4 characters - and only 4 characters - you could probably just do the comparison as 'for' loop; or even just four '==' operations...

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yes it is working good. Thanks a lot awneil. 

-----------------------

Thanks & Regards,

Sasi

-----------------------

GO GREEN