web-dev-qa-db-ja.com

C#で整数の上位バイトと下位バイトを取得し、それをchar配列として配置して、comポートに送信するにはどうすればよいですか?

Cではこれを行います

int番号= 3510;

char upper = number >> 8;

char lower = number && 8;

SendByte(upper);

SendByte(lower);

上下が両方とも= 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、upper = 13、lower = 0では、コードを>> 6 upper = 54に変更すると、これは意味がありません。これはまったく奇妙なことです。

基本的には、16ビットの数値から上位バイトと下位バイトを取得し、「GETDM」の後にCOMポートに送信したいだけです。

これどうやってするの? Cではとてもシンプルですが、C#では完全に困惑しています。

10
rolls

マスキングが正しくありません。8ではなく255(0xff)に対してマスキングする必要があります。シフトは「シフトするビット」の観点から機能しますが、ビット単位および/またはマスクする値に対して機能します...したがって、下位8ビットを保持します。下位8ビットが設定されたマスク(つまり255)が必要です。

数値を2バイトに分割しようとしている場合は、intfourバイト)ではなく、実際にはshortまたはushortである必要があることに注意してください。

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

ここでは、ushortの代わりにbyteを使用していることに注意してください。これは、符号拡張について心配する必要がない場合に、ビット演算の方が考えやすいためです。この場合、byteへのナロー変換が機能する方法のため、実際には問題にはなりませんが、それはあなたが考えるべき種類のことです。

34
Jon Skeet

あなたはおそらくしたいと思うでしょうそしてそれを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;
4
SwDevMan81

受け入れられた回答が質問に当てはまる場合でも、質問のヘッダーにintが含まれ、ヘッダーが短くなく、検索結果で誤解を招くという単純な事実のため、不完全であると考えています。C#のInt32は32ビット、つまり4バイトです。 。 Int32を使用する場合に役立つ例をここに投稿します。 Int32の場合、次のようになります。

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

そのため、Int32値をリトルエンディアンの16進文字列に変換するための次のメソッドを作成しました。この文字列では、すべてのバイトが空白で他のバイトから分離されています。これは、データを送信し、受信者に処理を高速化させたい場合に便利です。受信者は、Split( "")を実行して、スタンドアロンの16進文字列として表されるバイトを取得できます。

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. 16進文字列に変換してリトルエンディアン文字列を作成する代わりに、charsに変換して、やりたいことを何でも行うことができます。

これが誰かを助けることを願っています!

2
XMight

それはすべきではありません:

byte lower = (byte) ( number & 0xFF );
2
Nick

もう少しクリエイティブになる

[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;
}
1
MaLio