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 support@ccsinfo.com

Dumb C question - byte swapping

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



Joined: 08 Sep 2003
Posts: 197
Location: Omaha NE USA

View user's profile Send private message Send e-mail Visit poster's website

Dumb C question - byte swapping
PostPosted: Wed Mar 11, 2009 12:13 am     Reply with quote

Hi all,

I have a device (VNC1L) that gives me a string consisting of a filename, a space, and the file size as a 32-bit value, MSB first. I receive the bytes via a serial connection, so it's in a string. I need to make that into an int32. I've found dozens and dozens of ways that don't work. What's the best way that will work? I've tried various combinations of pointers without much success. Here's my latest failure, but it's only the latest in a long, long string of them - no pun intended.

Code:

int32 USBMasterDirFile(char * filename) {
    int8 i;
    int32 l = 0;
    char response[40];
    char q;

//(here is some stuff that gets the string and puts it in response[])
    if(strstr(response,filename)) {
        q = strchr(response, ' ') - response;        // Find the space
        q += 5;                                                //  Point at the last byte of
                                                                   //  the file size
        for(i=0;i<4;i++) {
            *(((int8*)&l + i)) = response[q];
            q--;
        }
    }
}


I'm lost, I admit it. The hazards of self-taught programming, I'm afraid. I stick to C because I can't think abstractly enough for C++, I guess this is where it shows.

Helpful pointers (again, no pun intended)?
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Mar 11, 2009 12:28 am     Reply with quote

If it's truly a string (of ASCII numbers) and you have a pointer to it,
then you can use the atoi32() function to convert the string to an integer.
The test program shown below has the following output:
Quote:
result = 12345678

Code:

#include <16F877.H>
#fuses XT, NOWDT, NOPROTECT, BROWNOUT, PUT, NOLVP
#use delay(clock=4000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)

#include <stdlib.h>

//======================================
void main()
{
char string[] = {"12345678"};
int32 result;

result = atoi32(string);

printf("result = %lu \n\r", result);

while(1);
}
Wayne_



Joined: 10 Oct 2007
Posts: 681

View user's profile Send private message

PostPosted: Wed Mar 11, 2009 3:18 am     Reply with quote

You nearly had it

Code:

int32 USBMasterDirFile(char * filename) {
    int8 i;
    int32 l = 0;
    char response[40];
    char *q; // Should be a pointer

//(here is some stuff that gets the string and puts it in response[])
    if(strstr(response,filename)) {  // This does NOT copy filename to response! try
    strcpy(response, filename); // but this is NOT needed.

        // I see what you are doing here now, trying to get the index. Just use a pointer, much better.
        q = strchr(response, ' ') - response;        // Find the space
       
        q += 5;                                                //  Point at the last byte of
                                                                   //  the file size
        for(i=0;i<4;i++) {
            //*(((int8*)&l + i)) = response[q];       // q is a pointer to the char not an index! try
            *(((int8*)&l + i)) = *q;       // q is a pointer to the char
            q--;
        }
    }
}


I think you have definately over complicated it though.
strstr does NOT copy filename to response and I don't think you need response at all!

PCM programmer, I thiink you missed the important "and the file size as a 32-bit value" if it was a string of numchars then you would have been correct.

To simplify
Code:

int32 USBMasterDirFile(char * filename) {
    int32 l = 0;
    char *q;

   q = strchr(filename, ' '); // problem if filename may contain a space ? get pointer to first space
   if (q != null)
   {
      q++; // Skip space
      l = *q++;  // MSB
      l = (l << 8) + *q++;  // Shift lft l by 8 bits and add next byte
      l = (l << 8) + *q++;  // Shift lft l by 8 bits and add next byte
      l = (l << 8) + *q++;  // Shift lft l by 8 bits and add LSB

   }
    return(l);
}


Actually this may work but without checking the endian ness of CCS I am not sure
Code:

int32 USBMasterDirFile(char * filename) {
    char *q;
    int32 *lp;

   q = strchr(filename, ' '); // problem if filename may contain a space ? get pointer to first space
    lp = q + 1; // Skip space and make lp point to the valule
    return (*lp); // Get the contents of lp which is a pointer to a 32bit value!
}

If you know for sure that filename will always contain a filename, space and size then you can remove the if (q != null) check.

now are you sure it is a 32 bit value and not a string of numerical chars that make up a 32bit value such as "123" or "342536256" ?
dbotkin



Joined: 08 Sep 2003
Posts: 197
Location: Omaha NE USA

View user's profile Send private message Send e-mail Visit poster's website

PostPosted: Wed Mar 11, 2009 9:00 am     Reply with quote

Guys, thanks for the answers!! I still don't understand *why* the pointer manipulations were not working, and that bothers me. Actually I think I may have had it once or twice and not known it. I found a problem with how I was receiving the string from the VNC1L. Since it's got a 32-bit binary value embedded in it, get_string() strips out the non-ASCII characters! I had to make a new function to receive all the bytes and not strip anything out.

PCMProgrammer: Yeah, if it were an ASCII string I would have used atol(). But, it's not. It's an ASCII string for the filename, followed by a big-endian 32-bit binary number.

Wayne:
Code:
if(strstr(response,filename))

This isn't meant to copy filename to response. It's meant to make sure the name of the file in response matches filename. Here's why... I give the VNC1L a "dir <filename>" command. If the file exists, it returns "<filename> <size in bytes>". If it *doesn't* exist, it returns "CF" for "Command Failed". I want to make sure I get the filename back, not something else.

Code:

      l = *q++;  // MSB
      l = (l << 8) + *q++;  // Shift lft l by 8 bits and add next byte
      l = (l << 8) + *q++;  // Shift lft l by 8 bits and add next byte
      l = (l << 8) + *q++;  // Shift lft l by 8 bits and add LSB


That actually will copy the bytes and *not* reverse them, but at least it helped find the get_string() problem for me. Once I fixed that, this works:
Code:
    if(strstr(response,filename)) {     // Make sure we got the filename
        q = strchr(response,' ');   // Find the space
        q += 4;        // Point to the last byte of the number
        l = *q--;  // MSB
        l = (l << 8) + *q--;  // Shift lft l by 8 bits and add next byte
        l = (l << 8) + *q--;  // Shift lft l by 8 bits and add next byte
        l = (l << 8) + *q--;  // Shift lft l by 8 bits and add LSB
    }


And yes, I do feel just a little silly that I hadn't thought of shifting the int32 instead of trying to stuff bytes into it. Many thanks, guys. I'm now getting the correct result all around. I can read & write files to the USB drive now! On to the USB keyboard input... now, where did I put that big bottle of aspirin??
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