A way to convert hex value to decimal equivailent - hex

We have a problem right here we can't seem to get out of.
We have a hexadecimal byte array
Let's say its:
0x12 0x34
We now like to output this as ascii char on the display of our device so it should output:
0x31 0x32 0x33 0x34
So we'd like to convert between the values of the byte array, and the ascii equivailent of the number in the byte.
Is there anybody who knows how to do this?
Thanks in advance
edit:
ok so we know:
0x85 = 1000 0101
to get 8 we need to grab the left 4 bits.

In C you can use printf,
unsigned char array[2] = {0x12, 0x34};
printf("%x%x", array[0], array[1]);
prints out "1234"
Edit:
If you need it to print out "0x31 0x32 0x33 0x34" use this,
char ascii[] = {"0123456789ABCDEF"};
unsigned char array[] = {0x12, 0x34};
int length = sizeof(array)/sizeof(array[0]);
int i;
for (i = 0; i < length; ++i) {
printf("0x%02X 0x%02X ", ascii[(array[i] >> 4) & 0xf], ascii[array[i] & 0xf]);
}
prints out "0x31 0x32 0x33 0x34"

Related

Arduino read 20 bit number from 3 registers

I have an ADXL355 (EVAL-ADXL355-PMDZ) that I am trying to test against a very expensive industrial grade sensor. I am using I2C and I am able to read the device properties and settings as described in the datasheet.
The issue I'm having is how to read the 3 ZDATA (or XDATA, YDATA) registers as a single value. I have tried two approaches. Here is the first:
double values[3];
Wire.beginTransmission(addr);
Wire.write(0x08); // ACCEL_XAXIS
Wire.endTransmission();
Wire.requestFrom(addr, 9, true); // Read 9, 3 for each axis
byte x1, x2, x3;
for (int i = 0; i < 3; ++i){
x3 = Wire.read();
x2 = Wire.read();
x1 = Wire.read();
unsigned long tempV = 0;
unsigned long value = 0;
value = x3;
value <<= 12;
tempV = x2;
tempV <<= 4;
value |= tempV;
tempV = x1;
tempV >>= 4;
value |= tempV;
values[i] = SCALEFACTOR * value;
}
This will produce values that approach 1g for negative gravity and 3g for positive gravity. Also the unloaded axes will sometimes show offscale high instead of -0.0g. They bounce from 0.0 to 4.0 g's. This tells me I have a sign problem which I'm sure comes from using unsigned long. So I attempted to read it as a 16 bit value and retain the sign.
double values[3];
Wire.beginTransmission(addr);
Wire.write(0x08); // ACCEL_XAXIS
Wire.endTransmission();
Wire.requestFrom(addr, 9, true); // Read 9, 3 for each axis
byte x1, x2, x3;
for (int i = 0; i < 3; ++i){
x3 = Wire.read();
x2 = Wire.read();
x1 = Wire.read();
long tempV = 0;
long value = 0;
value = x3;
value <<= 8;
tempV = x2;
value |= tempV;
values[i] = SCALEFACTOR * value;
}
This produced values are good in terms of sign but they are (as expected) much lower in magnitude than they are supposed to be. I tried to create a 20 bit number like this long value:20; but I received
expected initializer before ':' token
same error for int.
How do I properly read from 3 registers to obtain a correct 20 bit value?
First of all, you really want to use unsigned types when using the left and right shift operators (see this question).
Taking a look to the avr-gcc type layout we learn that long are represented on 4 bytes (i.e. 32 bits) so they are long enough (no pun intended) to "hold" your 20 bits numbers (XDATA, YDATA, and ZDATA). On the other hand, int are represented on 2 bytes (i.e. 16 bits) and thus should not be used in your case.
According to the datasheet you linked page 33, the numbers are formatted as two's complement. Your first example correctly set the last 20 bits of your unsigned, 32 bits long value (in particular the left justification handling — right-shifting x1 by four — already looks correct) but the "new" 12 most significants bits are always set to 0.
To perform sign extension, you need to set the "new" 12 most significant bits to 0 if the number is a positive value, 1 if the number is a negative value (adaptation of your first example):
...
value |= tempV;
if (x3 & 0x80) /* msb is 1 so the number is a negative value */
value |= 0xFFF00000;
From there, what you should observe is about the same behaviour as previously: high positive values instead of small negative ones (but even higher than previously). This is caused by the fact that while your value is correct bitwise speaking, it is still intepreted as unsigned. This can be worked around by forcing the compiler to use value as signed:
values[i] = SCALEFACTOR * (long)value;
And now it should be working.
Note that this answer use the fact that your C/C++ implementation use two's complement to represent negative integers. While very rare in practice, the standard allow other representations (see this question for examples).
Here is one way to make it work. It does use bitshifting on a signed value. Various sources have said that this is a potential bug as it is implementation defined. It worked on my platform.
typedef union {
byte bytes[3];
long value:24;
} accelData;
double values[3];
Wire.beginTransmission(addr);
Wire.write(0x08); // ACCEL_XAXIS
Wire.endTransmission();
Wire.requestFrom(addr, 9, true); // Read 9, 3 for each axis
accelData raw;
for (int i = 0; i < 3; ++i){
raw.bytes[2] = Wire.read();
raw.bytes[1] = Wire.read();
raw.bytes[0] = Wire.read();
long temp = raw.value >> 4;
values[i] = SCALEFACTOR * (double)temp;
}
I prefer the solution presented by Alexandre Perrin.
union
{
struct
{
unsigned : 4;
unsigned long uvalue : 20;
};
struct
{
unsigned : 4;
signed long ivalue : 20;
};
unsigned char rawdata[3];
}raw;
for (int i = 0; i < 3; ++i){
raw.bytes[2] = Wire.read(); //if most significant part is transfered first
raw.bytes[1] = Wire.read();
raw.bytes[0] = Wire.read();
values[i] = SCALEFACTOR * (double)raw.ivalue;
}

Qbytearray byte to int and storing it as string value

I want to convert byte data that stored in QBytearray into string value. that string value am using it for displaying in ui window..
QByteArray array;
array.append( 0x02 );
array.append( 0xC1);
qDebug()<<( uint )array[0]<<" "<<( uint )array[1];
uint i = 0x00000000;
i |= array[1];
qDebug()<<i;
uint j = 0x00000000 | ( array[0] << 8 );
qDebug()<<j;
i |= j;
bool b = false;
QString str = QString::number( i );
qDebug()<<str;
but the str prints "4294967233"...this code works for some of the bytes like 0x1, 0x45 and for some of other..but this code not working perfectly for all bytes of data into string..please help me with this and write code for this and post it here..thanks
All values equal or bigger than 0x80 interprets in your sample as negative values, so it need cast to unsigned type before bitwise operations.
QByteArray array;
array.append( 0x02 );
array.append( 0xC1);
unsigned int value = 0;
for (int i = 0; i < array.size(); i++)
value = (value << 8) | static_cast<unsigned char>(array[i]);
QString str = QString::number(value);
qDebug() << value << str;

Difference normal cast and pointer cast

i've written a following code:
void union_bytes() {
float fnum = 1209.1996f;
union endian {
float fnum;
int inum;
unsigned char cnum[4];
}instance;
instance.fnum = fnum;
printf("Number = %f\nLittle Endian = %.2x %.2x %.2x %.2x\nHex = %x\n", instance.fnum, instance.cnum[0],
instance.cnum[1], instance.cnum[2], instance.cnum[3], instance.inum);
}
void pointer_bytes() {
float fnum = 1209.1996f;
int *ptr_inum = (int*)&fnum;;
unsigned char *cbytes = (unsigned char *)&fnum;
printf("Number = %f\nLittle Endian = %.2x %.2x %.2x %.2x\nHex = %x\n", fnum, cbytes[0], cbytes[1], cbytes[2], cbytes[3], *ptr_inum);
}
and i want to know, why i have to do such things : int *ptr_inum = (int*)&fnum; in order to get little-endian, and i cant do so like this:
int inum = (int)fnum;
i suppose, the last option forces fnum to lose some bytes, but i still dont know how such numbers are represent in memory(and which bytes are exactly to lose).
Why in this case:
unsigned char ch[4] = { 0x3b, 0x51, 0x7a, 0x24 };
float f = *(float*)ch;
When comes to casting, ch doesnt give the first nible 0x3b which is then a float, rather than it converts all the bytes in table compounding the entire float.
Thanks
why i have to do such things : int ptr_inum = (int)&fnum; in order
to get little-endian, and i cant do so like this: int inum =
(int)fnum;
There is some terminology confusion here. Little-endian is a specific order of bytes for multi-byte structures, and is usually mentioned as opposed to big-endian.
What you are getting is as a result of execution of the first statement is:
make the variable that points to integer point to a location where a floating-point number is stored, so that later its word representation can be retrieved/modifed int by int. Say, for number 1.9 in IEEE-754 compliant implementations is represented as 0x3ff33333, so on little-endian architectures if your int is 32bit you would get 0x3ff33333.
Second statement would mean: give me an integer variable, that results from a float pointing number. By standard, that means dropping of the decimal, so out of 1.9 you will get 1.

QByteArrray invalid crc32 values

I'm trying to get CRC32 hash from QByteArray. The problem is that, everytime I run program, it gives different results if using QByteArray::operator=() but right if I use QByteArray::setRawData(). could anyone explain why I'm getting these strange results? Thanks.
crc32 function:
unsigned int crc32_tab[256] = {
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
};
...
unsigned int MyClass::crc32(unsigned int crc, const void *buf, unsigned int size)
{
const unsigned int *p;
p = (const unsigned int *)buf;
crc = crc ^~ 0xFFFFFFFF;
while(size--)
{
crc = this->crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8);
}
return crc ^~ 0xFFFFFFFF;
}
and string to be calculated.
QByteArray crcval = "abc";
MyClass mclass;
QMessageBox::information(0, 0, QString::number(mclass.crc32(0, crcval.constData(), crcval.size()))); // returns random numbers.
...
QByteArray crcval;
crcval.setRawData("abc", 3);
MyClass mclass;
QMessageBox::information(0, 0, QString::number(mclass.crc32(0, crcval.constData(), crcval.size()))); // OK.
Why?
In first case your string converted to QString. So it's byte representation will be a string in utf-16 with trailing zero (total 8 bytes).
In first case you path 4 bytes - a, b, c, \0
In second - to char[3]
What you mean by "random numbers"?

Why QString("FFFFFFFF").toInt(0, 16); returns 0?

As you may know, 0xFFFFFFFF in the Two's Complement representation equals -1 (for 32 bits). But the following code:
qint32 aa = QString("FFFFFFFF").toInt(0, 16);
qDebug()<<aa;
prints 0. The code below:
qint32 aa = 0xffffffff;
qDebug()<<aa;
prints -1!
Why is this?
If you read the documentation you can see that toInt "Returns 0 if the conversion fails."
Your input does not fit in a signed 32 bit integer, so presumably the conversion fails.
You can verify this by using the ok-parameter:
bool ok;
qint32 aa = QString("FFFFFFFF").toInt(&ok, 16);
if (ok) qDebug() << aa;
else qDebug() << "Conversion failed!";
FFFFFFFF is not an integer format. 0xFFFFFFFF is. And also 0xFFFFFFFF is out of int range. Try use usigned integer. Change the conversion function toInt to toUInit. Here is the code:
quint32 aa = QString("0xffffffff").toUInt(0, 16);
quint32 bb = 0xffffffff;
qDebug()<<aa;
qDebug()<<bb;
It has been tested on my machine. The output is 4294967295.

Resources