NerdKits - electronics education for a digital generation

You are not logged in. [log in]

NEW: Learning electronics? Ask your questions on the new Electronics Questions & Answers site hosted by CircuitLab.

Microcontroller Programming » Sending a string in UART

December 12, 2010
by met_fredrik
met_fredrik's Avatar

Hi! As the title says I am trying to send a string through UART. I recently got the well-known 434 MHz RF Link Transmitter/Receiver from sparkfun in the mail.

I searched some on the net and found some examples with sending some bytes between two micro controllers with a simple encoding. The problem now is that I want to send a whole string as my "data packet" instead of the 8 bit integer. When I try to implement it within the code I was already using I get a warning in the compiler saying I am "making an integer from a pointer without a cast". I guess it has something to do with the code tries to send my string as an int. Don't worry about the while loop, I just didn't remove it from the original code which just sent a byte repeatedly for testing purposes.

What am I doing wrong?

Main code:

int main(void)
    {
    /****************INITIALIZATIONS*******************/
    lcd_init();     //Initialize lcd
    DDRC |= (1<<PC4);
    uartInit();  // initialize the UART (serial port)
    uartSetBaudRate(2400);// set the baud rate of the UART for our debug/reporting output
    rprintfInit(uartSendByte);// initialize rprintf system

    receive();   //Go to the subroutine responsible for receiving, it is located in "rf_rx.c"
    //transmit();  //Go to the subroutine responsible for transmitting, it is located in "rf_rx.c"

return 0;
    }

rf_rx.c:

#include "../libnerdkits/lcd.h"
#include "../libnerdkits/delay.h"

// Get Byte Subroutine
int GetByte(void)  // Subroutine to get a byte from the UART 
{
    //Syntax is var= GetByte(); where var is any variable capable of storing a byte
    while((UCSR0A&(1<<RXC0)) == 0);  // wait until a byte is received
    return UDR0;  // once a byte is received send back to the program the byte
}

// Send Byte Subroutine
void SendByte(char c) {  //Subroutine to send a byte to the UART
    // Syntax is SendByte(#);  where # is any number
  while (!(UCSR0A & (1<<UDRE0))); // Wait until you are able to send a byte
  UDR0 = c;  // pass the value of the c variable into the UDR , which in turn sends the byte out the UART
}

// The Receive Subroutine
void receive(void)
{
int start;      // create variable named start
int addr;       // create variable named addr
int data;       // create variable named data
int chksum;     // create variable named chksum

while(1) // Do an infinite loop
{

//Sample program for receiving packet with contents - 0x55, 0x8E ,0x27,0xB3

    start = GetByte();  // Store received UART byte into the variable "start"
    if (start == 0x55) // if data is equal to 0x55 , Start Byte
        {   
        UDR =0;  //clear UDR
        data = GetByte(); // Store received UART byte into the variable "data"
        UDR =0;    //clear UDR
        addr = GetByte(); // Store received UART byte into the variable "addr"
        UDR =0;    //clear UDR
        chksum = GetByte(); // Store received UART byte into the variable "chksum"
            if (chksum == (start+addr))  //if chksum is equal to data+addr then
            {
                lcd_line_two();
                FILE lcd_stream = FDEV_SETUP_STREAM(lcd_putchar, 0, _FDEV_SETUP_WRITE);
                fprintf_P(&lcd_stream, PSTR("string: %c "), data);
            }//endif
        }//endif
} //endwhile
} //end sub

// The Transmit subroutine
//Sample program for transmitting packet with contents - 0x55, 0x8E ,0x27,0xB3
void transmit(void)
{

int start;      // create variable named start
int addr;       // create variable named addr
char data;      // create variable named data
int chksum;     // create variable named chksum

start = 0x55 ; // put 0x55 into the variable
addr = 0x8E;        // put 0x8E into the variable
data = ("hey");     // put 0x27 into the variable
chksum = (addr + start);        // put the checksum into the variable

    while(1)  //run an infinite loop
    {   
    SendByte(start);  // Send start byte
    SendByte(data);     // Send data byte
    SendByte(addr); // Send address byte
    SendByte(chksum);   // Send checksum byte
    delay_ms(2);    // delay for 2 milliseconds
    PORTC |= (1<<PC4);
    delay_ms(20);
    PORTC &= ~(1<<PC4);
    } //endwhile
}//endsub

Thanks!

December 13, 2010
by hevans
(NerdKits Staff)

hevans's Avatar

Hi met_fredrik,

Which line is the compiler saying there is a problem in. I see an issue on line 63. You are putting a string, which essentially is a pointer to a character array into a char variable. I think it might throw that warning when you try to do that.

Humberto

December 13, 2010
by met_fredrik
met_fredrik's Avatar

Thank you for your answer!

That's the line my compiler is talking about. Anyway, I don't quite understand the problem. Shouldn't this work?

Also the example I have modified here talks about bytes, I mean, I am sending one byte for start, one for address, and then a whole string, and then one byte again. How is this handled by the USART? Can I really do it like this? Just using single bytes and big variables containing lots of bytes in the same mix?

Hope there is a simple way of explaining this to me!

-Fredrik

December 13, 2010
by met_fredrik
met_fredrik's Avatar

EDIT: rf_rx.c:64: warning: assignment makes integer from pointer without a cast is the error I get. This is really line 63 in the code I posted.

December 13, 2010
by bretm
bretm's Avatar

The SendByte function sends exactly one byte. If you want to send a string you'll have to send each byte of the string separately and the receiver has to know where the string bytes start and end so it can reconstruct the string on the receiving end.

December 14, 2010
by met_fredrik
met_fredrik's Avatar

Okay, this seems doable in my application because I am going to send a string that I know the exact length of each time.

But what if I wanted to send a string with unknown length? Can I, maybe, send the length of the string as a byte before the actual string is sent and then store it again with the correct length in the receiver?

December 14, 2010
by hevans
(NerdKits Staff)

hevans's Avatar

Hi met_fredrik,

Your solution of sending the length of the string first is a good solution, however you can get around it by knowing how strings work in C. Strings are just arrays of chars terminated with a null character (0), with each value in the array holding one character. In C when you do something line "Hi" the expression evaluates to a pointer to first element in the array that is holding your string. That first memory location holds the character H, the second holds the character i, and the third location holds 0 (note that is the actual value 0, not the ASCII representation of the character 0).

To send strings you can just send them one character at a time, and send the null terminating byte at the end, this will signal the receiver that the full string has come in. In this scheme you will still have to have a maximum size that you can receive, since you need to allocate that memory before hand on the receiver side. Otherwise you would not have any place to put the bytes as they come in.

Hope that makes sense.

Humberto

January 27, 2012
by tchilzer2
tchilzer2's Avatar

Hello,

I too am having trouble with strings right now. I have been searching through the threads for similar situations but I don't see my question asked anywhere. Anyway since this thread touches real close I want to ask:

How do you compare a string? I assume from what I read that there is no such thing as an actual string variable. Instead it is always an array of char variables right? If so, I understand that "looping out" each char can "appear" to be a string when output one after another to lcd or uart but what about a comparison of the entire collection of characters as a string? For instance; If I type "flash" it is actualy represented as:

int array=0;
char My_string[20];
My_string [array] = {'f','l','a','s','h'};

right?

How can I tell the compiler to compare that? I dont want a pre defined char string, it has to be variable and then compared to a set comparison... something like this:

if (My_string[array] == "flash" //or {{'f','l','a','s','h'}
{//do something};

what is the syntax for this? or what is the appropriate way to perform such a check? Thanks so much!

January 27, 2012
by hevans
(NerdKits Staff)

hevans's Avatar

There are a couple of functions included in avr-libc that you can use for this. Of particular interest to you will be the strstr() function, or the strcmp() function, http://www.nongnu.org/avr-libc/user-manual/group__avr__string.html.

Note that both of these functions expect the string to be in RAM, not program memory. So if you are storing the string to compare against in program memory you will have to copy into RAM first. Hope that gets you started!

Humberto

January 27, 2012
by tchilzer2
tchilzer2's Avatar

Thank you Humberto!

I will look at this right away!

January 27, 2012
by tchilzer2
tchilzer2's Avatar

Ok,

strcmp() looks like what I want... I still have a qustion though:

it says that the function returns an integer based on whether s1 is less than the same as or greater than s2. What does that mean? What I am confused about is what exactly is being compared. Is it the total value of the characters in the char array? or is it the number of characters in the char array?

If the former then wouldnt it make mistakes? like if the total value of the characters m,e,s,s may be the same as the total character value as a,a,a,a for instance.

If the later then its not going to be accurate at all as m,e,s,s would come up the same as t,r,u,e.

Or is there another kind of value being compared like the exact value of each char 1 by 1 in both strings? cause that would work. What Am I missing in all of this?

thank you for your patience,

T.C.

January 27, 2012
by treymd
treymd's Avatar

I believe this is a good explanation.

January 27, 2012
by BobaMosfet
BobaMosfet's Avatar

One of the most useful things any developer can do, is learn how things sit in memory- it's memory your working with, everything else is generic data.

Strings aren't difficult. They are just bytes, consecutively spaced in memory. For the OP, the original error was: "making an integer from a pointer without a cast".

All that means is that you are trying to treat the address (location) of an object (contents) as a content value, not an address OF a content value.

Everything has to sit in memory somewhere.

If you want to compare to strings, either find a library that contains a function to do it, or write it yourself.

/* PROTOTYPE */
bool strcompare(char*,char*);

/* FUNCTION */
bool strcompare(char *str1,char *str2)
    {
    if(strlen(str1) != strlen(str2))           /* lengths don't match */
        return(FALSE);

    while((str1 != 0x00) && (str2 != 0x00))    /* loop through until hit end-marker */
        if(str1++ != str2++)
            return(FALSE);

    return(TRUE);
    }

This is from my head, quick and dirty- probably needs some fixes; gives you a start.

BM

January 27, 2012
by BobaMosfet
BobaMosfet's Avatar

tchilzer2-

"it says that the function returns an integer based on whether s1 is less than the same as or greater than s2. "

The function can be used to sort strings- By knowing whether one string evaluates as 'less than' or 'greater than' another string, you can order it. If they're equal, it returns zero (as I recall).

BM

January 27, 2012
by tchilzer2
tchilzer2's Avatar

Awsome! Its a lexicoographic comparison! That clears it right up and I can use strcmp() to do what I need to. Thank you for that very clear explanation Treymd! This concept has eluded me for the past year even with c++. That explanation took all the uncertainty right out of my head!

Boba, I am slowly working my way toward learning how to use more advanced programming techniques I want to thank you for posting your example because I know it will be there when I come to it.

January 27, 2012
by tchilzer2
tchilzer2's Avatar

Oh my! Please forgive my exceeding frustration. what ever happened to a string = b string or if a string = b string? Jeez whats all this pointer stuff? why am I comparing const char's Im trying to compare variable characters! I dont know if I am assigning my variable char array wrong

char cmd_flash[6]={'f','l','a','s','h'};

or what const char *s1 is supposed to be... a pointer to what?

here is what I got ... please explain to me what in the world is so darn complicated with comparing a string!

char cmd_flash[6]={'f','l','a','s','h'};
char cmd_str[16];
int ltr=0;

input cmd_str[ltr]; // I know this middle part isn't actual code... I am 
                        roughing it as a general whats goin on.
ltr ++ and repeat // basically

int strcmp (const char* cmd_str[], const char* cmd_flash[]);
if (strcmp == 0){do something}

why wont this work?

January 27, 2012
by treymd
treymd's Avatar

strcmp is a function, you can either store its result in a variable, or use it within your if statement, passing it the parameters within, like I do in the following:

// char array way of initializing
// this will work, it's just not as easy as the next method
//char str1[] = {'a','b','c','\0'};
//char str2[] = {'1','b','c','\0'};

// C-string or char* way of initializing
char* str1 = "abc";
char* str2 = "def";

if ( strcmp(str1,str2) == 0)
{
    printf("strings are equal");
}
else if ( strcmp(str1,str2) < 0)
{
    printf("str1 is less");
}
else
{
    printf("str1 is greater");
}
January 27, 2012
by treymd
treymd's Avatar

the backslash-0 in the char arrays is a null character, terminating the string. If you use double quotes, the c compiler adds this for you, note that the null char is there in memory, so a 3 char string takes up 4 bytes in memory.

January 27, 2012
by treymd
treymd's Avatar

By the way you CAN manipulate a C-string with the bracket operators if you are wondering. I'm a little rusty, but I believe the compiler treats a C-string just like a char array, so str1[0], str1[2], etc. are valid ways of manipulating char* str1

Post a Reply

Please log in to post a reply.

Did you know that you can use printf and scanf functions to talk to your computer from your USB NerdKit? Learn more...