c# FTDI 24bit 二进制补码工具

问题描述

我是 C# 的初学者,想要一些有关如何解决以下问题的建议:

我的代码从 ADC 真 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 

解决方法

转换数据左对齐,以便您的符号位落在您的 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;
,

好吧,这里唯一模糊的时刻是字节序(或大或小)。假设 byte[0] 代表您可以放置​​的最低有效字节

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,44}),你必须交换字节:

private static int FromInt24(byte[] data) {
  int result = (data[0] << 16) | (data[1] << 8) | data[2];

  return data[0] < 128
    ? result
    : -((~result & 0xFFFFFF) + 1);
}