gpt4 book ai didi

ada - 从大端数据中提取记录

转载 作者:行者123 更新时间:2023-12-03 15:11:53 26 4
gpt4 key购买 nike

我有以下用于网络协议(protocol)实现的代码。由于协议(protocol)是大端的,我想使用 Bit_Order 属性和 High_Order_First 值,但似乎我犯了一个错误。

With Ada.Unchecked_Conversion;
with Ada.Text_IO; use Ada.Text_IO;
with System; use System;

procedure Bit_Extraction is

type Byte is range 0 .. (2**8)-1 with Size => 8;

type Command is (Read_Coils,
Read_Discrete_Inputs
) with Size => 7;

for Command use (Read_Coils => 1,
Read_Discrete_Inputs => 4);

type has_exception is new Boolean with Size => 1;

type Frame is record
Function_Code : Command;
Is_Exception : has_exception := False;
end record
with Pack => True,
Size => 8;

for Frame use
record
Function_Code at 0 range 0 .. 6;
Is_Exception at 0 range 7 .. 7;
end record;

for Frame'Bit_Order use High_Order_First;
for Frame'Scalar_Storage_Order use High_Order_First;

function To_Frame is new Ada.Unchecked_Conversion (Byte, Frame);

my_frame : Frame;
begin
my_frame := To_Frame (Byte'(16#32#)); -- Big endian version of 16#4#
Put_Line (Command'Image (my_frame.Function_Code)
& " "
& has_exception'Image (my_frame.Is_Exception));
end Bit_Extraction;

编译没问题,但结果是
raised CONSTRAINT_ERROR : bit_extraction.adb:39 invalid data

我忘记或误解了什么?

更新

真正的记录其实是

type Frame is record
Transaction_Id : Transaction_Identifier;
Protocol_Id : Word := 0;
Frame_Length : Length;
Unit_Id : Unit_Identifier;
Function_Code : Command;
Is_Exception : Boolean := False;
end record with Size => 8 * 8, Pack => True;

for Frame use
record
Transaction_Id at 0 range 0 .. 15;
Protocol_Id at 2 range 0 .. 15;
Frame_Length at 4 range 0 .. 15;
Unit_id at 6 range 0 .. 7;
Function_Code at 7 range 0 .. 6;
Is_Exception at 7 range 7 .. 7;
end record;

其中 Transaction_Identifier、Word 和 Length 为 16 位宽。

如果我删除 Is_Exception 字段并将 Function_Code 扩展为 8 位,这些将正确显示。

要解码的帧的转储如下:
00000000  00 01 00 00 00 09 11 03  06 02 2b 00 64 00 7f

所以我唯一的问题是提取最后一个字节的第 8 位。

最佳答案

所以,

    for Frame use
record
Transaction_Id at 0 range 0 .. 15;
Protocol_Id at 2 range 0 .. 15;
Frame_Length at 4 range 0 .. 15;
Unit_id at 6 range 0 .. 7;
Function_Code at 7 range 0 .. 6;
Is_Exception at 7 range 7 .. 7;
end record;

看来您希望 Is_Exception 成为最后一个字节的 LSB?
for Frame'Bit_Order use System.High_Order_First; LSB 将是第 7 位,

(另外, 16#32# 永远不会是 -- Big endian version of 16#4# ,位模式不匹配)

指定所有字段相对于它们所在的单词而不是字节可能更直观和清晰:

         Unit_ID at 6 range 0..7;
Function_Code at 6 range 8 .. 14;
Is_Exception at 6 range 15 .. 15;

给定 Command 的定义上面,最后一个字节的合法值将是:
  • 2 -> READ_COILS FALSE
  • 3 -> READ_COILS TRUE
  • 8 -> READ_DISCRETE_INPUTS FALSE
  • 9 -> READ_DISCRETE_INPUTS 真

  • 顺便提一句,
    通过将您的更新应用到您的原始程序,并添加/更改以下内容,您的程序对我有用

    添加

        with Interfaces;

    添加

        type Byte_Array is array(1..8) of Byte with Pack;

    改变,因为我们不知道定义

        Transaction_ID : Interfaces.Unsigned_16;
    Protocol_ID : Interfaces.Unsigned_16;
    Frame_Length : Interfaces.Unsigned_16;
    Unit_ID : Interfaces.Unsigned_8;

    改变

        function To_Frame is new Ada.Unchecked_Conversion (Byte_Array, Frame);

    改变

        my_frame := To_Frame (Byte_Array'(00, 01, 00, 00, 00, 09, 16#11#, 16#9#));

    关于ada - 从大端数据中提取记录,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56656184/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com