I2C ,Wire.read and signed int

When Wire.read() returns an int, what is this int is is signed or unsigned.

If the register i read with Wire.read has values(signed) that are save with 2's complements method the return int what type is it?

Is it always signed? or Depends?

The receive buffer contains unsigned char so:

If the receive buffer is empty the integer returned is -1.
If the receive buffer is not empty, the integer returned is between 0 and 256 255.

so why do i get negative number and not -1

kyrpav:
When Wire.read() returns an int, what is this int is is signed or unsigned.

The data type int is signed.

How to use this forum

Post your code.

kyrpav:
so why do i get negative number and not -1

I suspect you are trying to cram a value greater than 127 into a signed char. The value returned by .read() is a 'signed int' from -1 to 255.

i will try to make a sketch to send it to you but since i work with eclipse i have to combine the files. I will. I get negative values smaller than -1. I know that wire.read() returns byte so an unsigned int and give -1 if there is an "error". Is there any possibility that wire.read can understands that the values that are stored in the registers are set in 2's compliment(i think not)?

If you are seeing a value outside the -1 to 255 range then there is probably something wonky in your code.

well i am sorry i forgot to mention something the values that i read are stored in 16bit. I read 2 registers (2 different bytes) and i combine them.I store each to a byte and then i combine them.This result brings negative results. i will give you the code.

int n=6;
	byte result[6];
	readRegValue(DATA,n,result);//this reads the bytes and stores them at the array.
	int x= (( result[0] | result[1]<<8)>>2);//here i combine them and i need only the 14bits
	if (x&0x2000){///and this is what i should do if i the value is negative in order to keep it negative at 2s compliment
		x=x|0xc000;
	}
	xAxes=x*(getSensivity()/8192.0);

It is for the BMA180 accelerometer.

byte result[6];
...	
result[1]<<8

result [1] shifted left 8 bits will be zero, no matter what is in it.

i thought that shifting it and using a | i can make a 16bit variable

Looks like you are right. But what about this?

	if (x&0x2000){///and this is what i should do if i the value is negative in order to keep it negative at 2s compliment
		x=x|0xc000;

How does or'ing in 0xC000 help?

i have 2 bytes that i read from the register.The value inside lies on 3-16 bit. So i shifted the msb and used bitwise or to combine and then i shifted again to the right and get the number i wanted.

The int that i stored the number tho is not signed int16_t (propably this is mistake).
Because i shifted the number to get only the 14bit i use c000 to retain the negative value from 14 to 16bit

	int x= (( result[0] | result[1]<<8) >>2);
	if (x&0x2000){///and this is what i should do if i the value is negative in order to keep it negative at 2s compliment
		x=x|0xc000;

I think the problem here is that the right-shift is done on an unsigned value.

	int x= result[0] | (result[1]<<8);
        x >>= 2;  // Drop the bottom two bits.

I'm not sure if the result of (result[1]<<8) is signed or unsigned but in either case it's an int because all smaller data types are promoted to int or unsigned int when used in an expression.

These are some picture from the Datasheet of the accelerometer that you can see what i try to do. The values that i want to extract from the registers are in 2's compliment. I do not know what happens when i do this shifting to the bytes and also set them to an int that i think in this case is not uint8_t or uint16_t. Propably it is signed int32_t.

If you have something better to suggest in order to get these values please tell me.

No, unsigned char/char/byte/etc. under go the normal arithmetic conversion operators and the expression will be done in int (possibly unsigned int in rare ports). On systems like Arm (Due, Teensy 3.0, etc.) where int is 32-bits, shorts/unsigned shorts will also be promoted to int, while on the AVR based Arduinos, it won't.

sorry i did not understand your point can you explain it again? propably my english does not help me.

I read the accelerometer and values with this code:

void BMA180Acc::readAccel() {

	int n=6;
	byte result[6];
	readRegValue(DATA,n,result);

	int x= (( result[0] | result[1]<<8)>>2);
	Serial.println(x);
	if (x&0x2000){
		x=x|0xc000;
	}
	xAxes=x*(getSensivity()/8192.0);

	int y= (( result[2] | result[3]<<8 )>>2);
	if(y&0x2000){
		y=y|0xc000;
	}
	yAxes=y*(getSensivity()/8192.0);

	int z= (( result[4] | result[5]<<8 )>>2);
	if(z&0x2000){
		z=z|0xc000;
	}
	zAxes=z*(getSensivity()/8192.0);
}

getSensitivity() is set returns an enumerated int(this is not the problem)

function readRegValue() is:

void BMA180Acc::readRegValue(int adr,int addcount,byte buffer[]) {


	  Wire.beginTransmission(BMA180);
	  Wire.write(adr);
	  Wire.endTransmission();
	  Wire.requestFrom((int)BMA180, addcount);
	  int i=0;
	  while (Wire.available())
	  {
	    buffer[i] = Wire.read();
	    i++;
	  }
	  Wire.endTransmission();
}

and the results are:

553
580
636
-1311
-271
418
2029
2020
411
2969
-7633
1650
6210
7878
-1222
-5030
-3733
282
-5006
-4806

The results is at a Serial.print inside the readAccel()
Since byte is what wire.read returns why the code give negative numbers, how does it understand that this values are stored in 2's compliment (or it doesn't and there is other problem)

kyrpav:
Since byte is what wire.read returns why the code give negative numbers, how does it understand that this values are stored in 2's compliment (or it doesn't and there is other problem)

When used in an expression, a 'byte' (unsigned char) gets promoted to an 'int'. That makes your code equivalent to:

int x= ((((int)result[0]) | ((int)result[1])<<8)>>2);

If the two bytes you get are 0x68 and 0xB1 the calculations work out to be:

int x= (0x0068 | (0x00B1<<8)) >>2;
int x= (0x0068 |  0xB100      ) >>2;
int x= 0xB168 >>2; // It's and int so it gets sign extended
int x= 0xEC5A;

0xEC5A == -5030

Thank you so cast makes the unsigned --->signed