Как получить верхний и нижний байт целого числа в C # и поместить его в массив символов для отправки на com-порт, как? - PullRequest
10 голосов
/ 24 марта 2011

В C я бы сделал это

int number = 3510;

символ верхнего = число >> 8;

символ ниже = число && 8;

SendByte (верхний);

SendByte (низший);

Где верхний и нижний оба = 54

В C # я делаю это:

            int number = Convert.ToInt16("3510");
            byte upper = byte(number >> 8);
            byte lower = byte(number & 8);
            char upperc = Convert.ToChar(upper);
            char lowerc = Convert.ToChar(lower);
            data = "GETDM" + upperc + lowerc;
            comport.Write(data);

Однако в номере отладчика = 3510, верхний = 13 и нижний = 0 это не имеет смысла, если я поменяю код на >> 6 upper = 54, что абсолютно странно.

По сути, я просто хочу получить старший и младший байт из 16-битного числа и отправить его через com-порт после "GETDM"

Как я могу это сделать? Это так просто в C, но в C # я полностью озадачен.

Ответы [ 5 ]

33 голосов
/ 24 марта 2011

Ваша маскировка неверна - вы должны маскироваться против 255 (0xff) вместо 8. Сдвиг работает в терминах «биты для сдвига», тогда как побитовое и / или работает со значением, которое нужно маскировать ... так что если выЕсли вы хотите сохранить только 8 младших битов, вам нужна маска, в которой установлены только 8 младших битов, то есть 255.

Обратите внимание, что если вы пытаетесь разделить число на два байта, оно действительно должно бытькороткий или ushort для начала, а не int (который имеет четыре байтов).

ushort number = Convert.ToUInt16("3510");
byte upper = (byte) (number >> 8);
byte lower = (byte) (number & 0xff);

Обратите внимание, что я использовал ushort вместо byteпобитовую арифметику легче думать, когда вам не нужно беспокоиться о расширении знака.В данном случае это не имеет никакого значения из-за того, как работает сужающее преобразование в byte, но об этом следует подумать.

4 голосов
/ 24 марта 2011

Вы, вероятно, хотите и это с 0x00FF

byte lower = Convert.ToByte(number & 0x00FF);

Полный пример:

ushort number = Convert.ToUInt16("3510");
byte upper = Convert.ToByte(number >> 8);
byte lower = Convert.ToByte(number & 0x00FF);
char upperc = Convert.ToChar(upper);
char lowerc = Convert.ToChar(lower);
data = "GETDM" + upperc + lowerc;
2 голосов
/ 10 февраля 2015

Даже если принятый ответ подходит для вопроса, я считаю его неполным из-за того простого факта, что вопрос содержит int, а не short в заголовке и вводит в заблуждение в результатах поиска, и, как мы знаем, Int32 в C # имеет 32 бита и таким образом 4 байта. Я опубликую здесь пример, который будет полезен в случае использования Int32. В случае Int32 имеем:

  1. LowWordLowByte
  2. LowWordHighByte
  3. HighWordLowByte
  4. HighWordHighByte.

И, таким образом, я создал следующий метод для преобразования значения Int32 в шестнадцатеричную строку с прямым порядком байтов, в которой каждый байт отделяется от других пробелом. Это полезно, когда вы передаете данные и хотите, чтобы получатель выполнял обработку быстрее, он может просто разделить ("") и получить байты, представленные в виде отдельных шестнадцатеричных строк.

public static String IntToLittleEndianWhitespacedHexString(int pValue, uint pSize)
{
    String result = String.Empty;

    pSize = pSize < 4 ? pSize : 4;

    byte tmpByte = 0x00;
    for (int i = 0; i < pSize; i++)
    {
        tmpByte = (byte)((pValue >> i * 8) & 0xFF);
        result += tmpByte.ToString("X2") + " ";
    }

    return result.TrimEnd(' ');
}

Использование:

String value1 = ByteArrayUtils.IntToLittleEndianWhitespacedHexString(0x927C, 4);
String value2 = ByteArrayUtils.IntToLittleEndianWhitespacedHexString(0x3FFFF, 4);
String value3 = ByteArrayUtils.IntToLittleEndianWhitespacedHexString(0x927C, 2);
String value4 = ByteArrayUtils.IntToLittleEndianWhitespacedHexString(0x3FFFF, 1);

Результат:

  1. 7C 92 00 00
  2. FF FF 03 00
  3. 7C 92
  4. FF.

Если трудно понять метод, который я создал, то следующее может быть более понятным:

public static String IntToLittleEndianWhitespacedHexString(int pValue)
{
    String result = String.Empty;
    byte lowWordLowByte = (byte)(pValue & 0xFF);
    byte lowWordHighByte = (byte)((pValue >> 8) & 0xFF);
    byte highWordLowByte = (byte)((pValue >> 16) & 0xFF);
    byte highWordHighByte = (byte)((pValue >> 24) & 0xFF);

    result = lowWordLowByte.ToString("X2") + " " +
            lowWordHighByte.ToString("X2") + " " +
            highWordLowByte.ToString("X2") + " " +
            highWordHighByte.ToString("X2");

    return result;
}

Примечания:

  1. Конечно, вместо uint pSize может быть перечисление, определяющее Byte, Word, DoubleWord
  2. Вместо преобразования в шестнадцатеричную строку и создания строки с прямым порядком байтов вы можете преобразовать в символы и делать все, что захотите.

Надеюсь, это кому-нибудь поможет!

2 голосов
/ 24 марта 2011

Не должно ли быть:

byte lower = (byte) ( number & 0xFF );
1 голос
/ 24 марта 2011

Чтобы быть немного более креативным

[System.Runtime.InteropServices.StructLayout( System.Runtime.InteropServices.LayoutKind.Explicit )]
public struct IntToBytes {
    [System.Runtime.InteropServices.FieldOffset(0)]
    public int Int32;
    [System.Runtime.InteropServices.FieldOffset(0)]
    public byte First;
    [System.Runtime.InteropServices.FieldOffset(1)]
    public byte Second;
    [System.Runtime.InteropServices.FieldOffset(2)]
    public byte Third;
    [System.Runtime.InteropServices.FieldOffset(3)]
    public byte Fourth;
}
...