在C#中获取整数的上下字节并将其作为字符数组发送到com端口,如何?

发布于 2024-10-26 08:29:12 字数 719 浏览 1 评论 0原文

在 CI 中会这样做

整数 = 3510;

字符上部=数字>> 8;

字符下位 = 数字 && 8;

SendByte(上);

SendByte(下);

其中 upper 和 lower 都 = 54

在 C# 中我正在这样做:

 int number = Convert.ToInt16("3510");
            上字节 = 字节(数字>>8);
            低字节=字节(数字&8);
            char upperc = Convert.ToChar(upper);
            char lowerc = Convert.ToChar(lower);
            数据 = "GETDM" + upperc + lowerc;
            comport.Write(数据);

然而,在调试器中,编号 = 3510,上限 = 13,下限 = 0 如果我将代码更改为>>,这就没有意义了6 上= 54 这绝对是奇怪的。

基本上我只想从 16 位数字中获取高字节和低字节,并在“GETDM”之后将其发送到 com 端口

我该怎么做?在 C 中是如此简单,但在 C# 中我完全被难住了。

In C I would do this

int number = 3510;

char upper = number >> 8;

char lower = number && 8;

SendByte(upper);

SendByte(lower);

Where upper and lower would both = 54

In C# I am doing this:

            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);

However in the debugger number = 3510, upper = 13 and lower = 0
this makes no sense, if I change the code to >> 6 upper = 54 which is absolutely strange.

Basically I just want to get the upper and lower byte from the 16 bit number, and send it out the com port after "GETDM"

How can I do this? It is so simple in C, but in C# I am completely stumped.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

忆悲凉 2024-11-02 08:29:12

您的屏蔽不正确 - 您应该屏蔽 255 (0xff) 而不是 8。移位以“要移动的位”的形式进行,而按位和/或对要屏蔽的值进行工作...所以如果您只想保留底部 8 位,您需要一个仅设置底部 8 位的掩码 - 即 255。

请注意,如果您尝试将一个数字拆分为两个字节,那么它实际上应该是一个short或ushort,而不是一个int(有四个字节)。

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

请注意,我在这里使用了 ushort 而不是 byte,因为当您不需要担心符号扩展时,按位算术更容易思考。在这种情况下,由于缩小转换为 byte 的工作方式,这实际上并不重要,但这是您应该考虑的事情。

Your masking is incorrect - you should be masking against 255 (0xff) instead of 8. Shifting works in terms of "bits to shift by" whereas bitwise and/or work against the value to mask against... so if you want to only keep the bottom 8 bits, you need a mask which just has the bottom 8 bits set - i.e. 255.

Note that if you're trying to split a number into two bytes, it should really be a short or ushort to start with, not an int (which has four bytes).

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

Note that I've used ushort here instead of byte as bitwise arithmetic is easier to think about when you don't need to worry about sign extension. It wouldn't actually matter in this case due to the way the narrowing conversion to byte works, but it's the kind of thing you should be thinking about.

哀由 2024-11-02 08:29:12

您可能想要使用 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;

You probably want to and it with 0x00FF

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

Full example:

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;
童话 2024-11-02 08:29:12

即使接受的答案符合问题,我也认为它不完整,因为问题包含 int 并且标头不短,并且它在搜索结果中具有误导性,并且我们知道 C# 中的 Int32 有 32 位,因此有 4 个字节。我将在这里发布一个在使用 Int32 时有用的示例。对于 Int32,我们有:

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

因此,我创建了以下方法,用于将 Int32 值转换为小端十六进制字符串,其中每个字节都通过空格与其他字节分隔。当您传输数据并希望接收器更快地进行处理时,这非常有用,他只需 Split(" ") 并获取表示为独立十六进制字符串的字节。

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. 而不是转换为十六进制字符串并创建小尾数字符串,您可以转换为字符并执行您想做的任何操作。

希望这会对某人有所帮助!

Even if the accepted answer fits the question, I consider it incomplete due to the simple fact that the question contains int and not short in header and it is misleading in search results, and as we know Int32 in C# has 32 bits and thus 4 bytes. I will post here an example that will be useful in the case of Int32 use. In the case of an Int32 we have:

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

And as such, I have created the following method for converting the Int32 value into a little endian Hex string, in which every byte is separated from the others by a Whitespace. This is useful when you transmit data and want the receiver to do the processing faster, he can just Split(" ") and get the bytes represented as standalone hex strings.

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(' ');
}

Usage:

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

The result is:

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

If it is hard to understand the method which I created, then the following might be a more comprehensible one:

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;
}

Remarks:

  1. Of course insteand of uint pSize there can be an enum specifying Byte, Word, DoubleWord
  2. Instead of converting to hex string and creating the little endian string, you can convert to chars and do whatever you want to do.

Hope this will help someone!

倾城月光淡如水﹏ 2024-11-02 08:29:12

不应该是:

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

Shouldn't it be:

byte lower = (byte) ( number & 0xFF );
等待圉鍢 2024-11-02 08:29:12

更有创意一点

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

To be a little more creative

[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;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文