uart_puts does not print anything after a 00 in an array

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

Hi, i am using some standard uart functions:

void uart_putc(char c)
{
	/* Wait for empty transmit buffer */
	while ( !( UCSR0A & (1<<UDRE0)) );
	UDR0 = c;
}
	
void uart_puts(char *str)
{
	while(*str)
	uart_putc(*str++);
}

The communication works perfect so no problems in setting up baud and other stuff.
Problem is that the uart_puts can print NIC_NACK but it does not prints NIC_ACK properly, i.e it only print 66 01 that's it :S

char NIC_ACK[4]={0x66, 0x01, 0x00, 0x09};
char NIC_NACK[4]={0x66, 0x01, 0x01, 0x09};

The only difference between the two is that NIC_ACK has a 0x00. Here is how the output screen looks:

1. When calling uart_puts(NIC_ACK):
Received data:66 01
2. When calling uart_puts(NIC_NACK);
Received data:66 01 01 09

Does it consider 00 to be end of array? :s

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

Correct behaviour. while (*str) evaluates to false as soon as the chacter to be printed is 0x00, the string termination character in C.

Einstein was right: "Two things are unlimited: the universe and the human stupidity. But i'm not quite sure about the former..."

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

DO1THL wrote:
Correct behaviour. while (*str) evaluates to false as soon as the chacter to be printed is 0x00, the string termination character in C.

So what should i do?

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

If you're sure there's something valid after the last nonzero character, just append a uart_putc(*str++) to your string output routine. And if you're sure the string continues after that zero character, continue with the string output routine. Only you can know if a zero in a stream of bytes/characters is meaningful data.

Einstein was right: "Two things are unlimited: the universe and the human stupidity. But i'm not quite sure about the former..."

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

DO1THL wrote:
If you're sure there's something valid after the last nonzero character, just append a uart_putc(*str++) to your string output routine. And if you're sure the string continues after that zero character, continue with the string output routine. Only you can know if a zero in a stream of bytes/characters is meaningful data.

Yes it is, and like in the array i posted in first post there is a 0x09 coming after 00. So what should i do so that no data is missed. Apart from manually inserting uart_putc

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

Again, only you know what is valid data in your array. If the number is a known value, then simply create a loop over this value and use the single-character output routine until you're done.

Einstein was right: "Two things are unlimited: the universe and the human stupidity. But i'm not quite sure about the former..."

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

HellsGuardian wrote:
So what should i do?
Don't use string functions with binary data. Maybe something like
void print_bin(char *data, int length)
{
    if (length == 0)
        return;
    while(length--)
        uart_putc(*data++);
}

Edit: Which is what DO1THL suggests, I missed the last post.

Last Edited: Wed. Oct 9, 2013 - 01:34 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

DO1THL wrote:
Again, only you know what is valid data in your array. If the number is a known value, then simply create a loop over this value and use the single-character output routine until you're done.

a side question, is this behavior same with STRCMP of string.h?
Because the function returns zero when i do a comparison with NACK (i.e contains no 00) but it does not returns 0 when comparison is made with ACK(containing a 0x00)

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

snigelen wrote:
HellsGuardian wrote:
So what should i do?
Don't use string functions with binary data. Maybe something like
void print_bin(char *data, int length)
{
    if (length == 0)
        return;
    while(length--)
        uart_putc(*data++);
}

Edit: Which is what DO1THL suggests, I missed the last post.

So i have to calculate the length using sizeof() and send it to this functions right?
Thanks!

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

Quote:

is this behavior same with STRCMP of string.h?

Yes. all c "string" (char array) functions use "C strings" which are arrays of data in which the special value of 0x00 is used as "the data ends here" marker. You therefore cannot use them with data that does have 0x00's in it.

Either rewrite to use a different end mark (that doesn't occur normally in the data) or, as suggested/shown above instead pass a length which each array so you know how many bytes to process.

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

No, sizeof(something) is the static size of something, but not the number of valid bytes/characters within an array of length N.

ALL string functions are based around the convention of having a binary zero as the termination character, so strlen(something) will only count the number of consecutive nonzero bytes within . If you do have valid bytzes beyond the first zero byte in there, you simply must not use string functions, as already being mentioned above.

But surely you do know the size of your array, or the number of valid bytes you had put into that array before???

Einstein was right: "Two things are unlimited: the universe and the human stupidity. But i'm not quite sure about the former..."

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

I don't know why I checked if (length == 0) since that case is covered by the while loop anyway.

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

google yield this:

http://stackoverflow.com/questions/9120065/best-way-to-compare-two-int-arrays-of-the-same-length

i changed array types to int and use this function:

if (memcmp(receivedByte,NIC_ACK,sizeof(receivedByte)) == 0 )

The comparison part seems to be working but its messing my receive buffer.

p.s so the above sizeof is also a string function and will not return proper results?
yes for now i know the length of the array i.e 4 (and its fixed) but just for my knowledge, how can one then calculate length of an array which contains integers?

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

You really need to get yourself a book on C and learn the language... The original bible is "The C Programming Language" by Dennis Ritchie (RIP) and Brian Kernighan - google it...

sizeof is a COMPILE time directive. The COMPILER computes the value based on the element, array or structure size in bytes.

cheers,
george.

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

However as you are doing a memcmp between your received buffer (which may vary in length of valid data) and the fixed NIC_ACK array then the latter is NOT going to change so sizeof() that will remain valid and given that it contains 4 bytes what would be the point in comparing any more (or less) anyway? So either:

memcmp(receivedByte,NIC_ACK,sizeof(NIC_ACK))

or even just:

memcmp(receivedByte,NIC_ACK,4)

(if you did this you probably want to "#define SOMETHING 4" then use SOMETHING every where 4 appears (including the actual dimension of NIC_ACK).

BTW "receivedByte" is an extraordinarily misleading name for a byte array with more than one byte in it!

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

clawson wrote:
However as you are doing a memcmp between your received buffer (which may vary in length of valid data) and the fixed NIC_ACK array then the latter is NOT going to change so sizeof() that will remain valid and given that it contains 4 bytes what would be the point in comparing any more (or less) anyway? So either:

memcmp(receivedByte,NIC_ACK,sizeof(NIC_ACK))

or even just:

memcmp(receivedByte,NIC_ACK,4)

(if you did this you probably want to "#define SOMETHING 4" then use SOMETHING every where 4 appears (including the actual dimension of NIC_ACK).

BTW "receivedByte" is an extraordinarily misleading name for a byte array with more than one byte in it!

The receive buffer will always be of 4-bytes. Noted and thanks!

georges80 wrote:
You really need to get yourself a book on C and learn the language... The original bible is "The C Programming Language" by Dennis Ritchie (RIP) and Brian Kernighan - google it...

sizeof is a COMPILE time directive. The COMPILER computes the value based on the element, array or structure size in bytes.

cheers,
george.


Well yes i studied just one course of C++ in my first semester which was not very practical. I remember i made a very good personal organizer using structures though...

Then in fourth semester we programmed microcontrollers (8051 and later PIC18F452) but i guess those were very simple projects e.g displaying data on LCD, dc servo motor control etc. Since it was Mechatronics engineering, the focus was more on machine side then on programming itself.
And now you can say i am forced to work on firmware side... Thank you for suggestion, ill be going through it in my one week vacation :)

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

clawson wrote:
However as you are doing a memcmp between your received buffer (which may vary in length of valid data) and the fixed NIC_ACK array then the latter is NOT going to change so sizeof() that will remain valid and given that it contains 4 bytes what would be the point in comparing any more (or less) anyway? So either:

memcmp(receivedByte,NIC_ACK,sizeof(NIC_ACK))

or even just:

memcmp(receivedByte,NIC_ACK,4)

(if you did this you probably want to "#define SOMETHING 4" then use SOMETHING every where 4 appears (including the actual dimension of NIC_ACK).

BTW "receivedByte" is an extraordinarily misleading name for a byte array with more than one byte in it!


When i tried putting 4 as the size, the code does not work as intended. So i did:

uart_putc(sizeof(receivedByte));

and the value it returned was 08 :s both my buffers are of fixed length i.e 4 What am i doing wrong now...

int receivedByte[4];
int NIC_ACK[4]={0x66, 0x01, 0x00, 0x09};
int NIC_NACK[4]={0x66, 0x01, 0x01, 0x09};

Edit: i get it its because of int array. If it was char array only then the size would be of 4.

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

Quote:

Edit: i get it its because of int array. If it was char array only then the size would be of 4.

Spot on.

On AVR sizeof(int) == 2.

(on your PC it is 4 or possibly even 8).

Last Edited: Thu. Oct 10, 2013 - 10:02 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
(on your PC it is 4 or possibly even 8).

The smiley should be read as: "... possibly even 8 )."

[corrected above - I turned smilies off for that post]

Einstein was right: "Two things are unlimited: the universe and the human stupidity. But i'm not quite sure about the former..."