|
|
View previous topic :: View next topic |
Author |
Message |
dbotkin
Joined: 08 Sep 2003 Posts: 197 Location: Omaha NE USA
|
Dumb C question - byte swapping |
Posted: Wed Mar 11, 2009 12:13 am |
|
|
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
|
|
Posted: Wed Mar 11, 2009 12:28 am |
|
|
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:
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
|
|
Posted: Wed Mar 11, 2009 3:18 am |
|
|
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
|
|
Posted: Wed Mar 11, 2009 9:00 am |
|
|
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?? |
|
|
|
|
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
|