c# FTDI 24bit 二进制补码工具
c# FTDI 24bit two's complement implement
我是 C# 初学者,想就如何解决以下问题寻求一些建议:
我的代码从 ADC true FTDI ic 读取 3 个字节并计算值。问题是有时我得到的值小于零(小于 0000 0000 0000 0000 0000 0000)并且我的计算值跳到一个大数字。我需要实现二进制补码,但我和我都不知道如何实现。
byte[] readData1 = new byte[3];
ftStatus = myFtdiDevice.Read(readData1, numBytesAvailable, ref numBytesRead); //read data from FTDI
int vrednost1 = (readData1[2] << 16) | (readData1[1] << 8) | (readData1[0]); //convert LSB MSB
int v = ((((4.096 / 16777216) * vrednost1) / 4) * 250); //calculate
嗯,这里唯一模糊的时刻是 endianness(大或小)。假设 byte[0]
代表 least 有效字节,你可以把
private static int FromInt24(byte[] data) {
int result = (data[2] << 16) | (data[1] << 8) | data[0];
return data[2] < 128
? result // positive number
: -((~result & 0xFFFFFF) + 1); // negative number, its abs value is 2-complement
}
演示:
byte[][] tests = new byte[][] {
new byte[] { 255, 255, 255},
new byte[] { 44, 1, 0},
};
string report = string.Join(Environment.NewLine, tests
.Select(test => $"[{string.Join(", ", test.Select(x => $"0x{x:X2}"))}] == {FromInt24(test)}"));
Console.Write(report);
结果:
[0xFF, 0xFF, 0xFF] == -1
[0x2C, 0x01, 0x00] == 300
如果你有 大 字节顺序(例如 300
== {0, 1, 44}
)你必须 swap 字节:
private static int FromInt24(byte[] data) {
int result = (data[0] << 16) | (data[1] << 8) | data[2];
return data[0] < 128
? result
: -((~result & 0xFFFFFF) + 1);
}
转换数据左对齐,以便您的符号位落在您的 PC 处理器视为符号位的位置。然后右移回去,会自动进行符号扩展
int left_justified = (readData[2] << 24) | (readData[1] << 16) | (readData[0] << 8);
int result = left_justified >> 8;
等价地,可以将包含符号位的字节标记为有符号,因此处理器将进行符号扩展:
int result = (unchecked((sbyte)readData[2]) << 16) | (readData[1] << 8) | readData[0];
第二种强制转换方法仅在符号位已经在任何一个字节内左对齐时才有效。左对齐方法适用于任意大小,例如 18 位二进制补码读数。在这种情况下,转换为 sbyte
将无法完成工作。
int left_justified18 = (readData[2] << 30) | (readData[1] << 22) | (readData[0] << 14);
int result18 = left_justified >> 14;
我是 C# 初学者,想就如何解决以下问题寻求一些建议:
我的代码从 ADC true FTDI ic 读取 3 个字节并计算值。问题是有时我得到的值小于零(小于 0000 0000 0000 0000 0000 0000)并且我的计算值跳到一个大数字。我需要实现二进制补码,但我和我都不知道如何实现。
byte[] readData1 = new byte[3];
ftStatus = myFtdiDevice.Read(readData1, numBytesAvailable, ref numBytesRead); //read data from FTDI
int vrednost1 = (readData1[2] << 16) | (readData1[1] << 8) | (readData1[0]); //convert LSB MSB
int v = ((((4.096 / 16777216) * vrednost1) / 4) * 250); //calculate
嗯,这里唯一模糊的时刻是 endianness(大或小)。假设 byte[0]
代表 least 有效字节,你可以把
private static int FromInt24(byte[] data) {
int result = (data[2] << 16) | (data[1] << 8) | data[0];
return data[2] < 128
? result // positive number
: -((~result & 0xFFFFFF) + 1); // negative number, its abs value is 2-complement
}
演示:
byte[][] tests = new byte[][] {
new byte[] { 255, 255, 255},
new byte[] { 44, 1, 0},
};
string report = string.Join(Environment.NewLine, tests
.Select(test => $"[{string.Join(", ", test.Select(x => $"0x{x:X2}"))}] == {FromInt24(test)}"));
Console.Write(report);
结果:
[0xFF, 0xFF, 0xFF] == -1
[0x2C, 0x01, 0x00] == 300
如果你有 大 字节顺序(例如 300
== {0, 1, 44}
)你必须 swap 字节:
private static int FromInt24(byte[] data) {
int result = (data[0] << 16) | (data[1] << 8) | data[2];
return data[0] < 128
? result
: -((~result & 0xFFFFFF) + 1);
}
转换数据左对齐,以便您的符号位落在您的 PC 处理器视为符号位的位置。然后右移回去,会自动进行符号扩展
int left_justified = (readData[2] << 24) | (readData[1] << 16) | (readData[0] << 8);
int result = left_justified >> 8;
等价地,可以将包含符号位的字节标记为有符号,因此处理器将进行符号扩展:
int result = (unchecked((sbyte)readData[2]) << 16) | (readData[1] << 8) | readData[0];
第二种强制转换方法仅在符号位已经在任何一个字节内左对齐时才有效。左对齐方法适用于任意大小,例如 18 位二进制补码读数。在这种情况下,转换为 sbyte
将无法完成工作。
int left_justified18 = (readData[2] << 30) | (readData[1] << 22) | (readData[0] << 14);
int result18 = left_justified >> 14;