Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2009.09.20;
Скачать: CL | DM;

Вниз

WriteBuffer - error - Access violation at addr... почему???   Найти похожие ветки 

 
Zheksonz   (2009-07-14 17:38) [0]

Всем привет)) Сергей М., персональный.
решил всё-таки общаться с портом без помощи строк. В сабже ошибка выдаваемая на записи в буфер. Что это может быть???

Код:
procedure TForm1.Button1Click(Sender: TObject);
const
CmdHZ: array[0..3] of byte = (01, 06, 00, 04);
var
CmdData: Word;
CmdCRC16: Word;
ms: TMemoryStream;
begin
// ComPort.Open;
CmdData := UpDown1.Position;
ms.WriteBuffer(CmdHZ, SizeOf(CmdHZ));
CmdData := Swap(CmdData);
ms.WriteBuffer(CmdData, SizeOf(CmdData));
CmdCRC16 := Swap(GetCRC16(ms.Memory, ms.Size));
ms.WriteBuffer(CmdCRC16, SizeOf(CmdCRC16));
ComPort.Write(ms.Memory^, ms.Size);
ComPort.Close;
end;


function TForm1.GetCRC16(P: PChar; Len: Word): Word;
var
iByte, i: Word;
B: Byte;
begin
{$R-}
Result := $FFFF;
for iByte := 0 to Len-1 do
  begin
   B := Byte(Pointer(LongInt(P)+iByte)^);
   Result := (Result and $FF00) + (B xor Lo(Result));
   for i := 1 to 8 do
     begin
      if ((Result and $0001) <> 0) then
        Result := (Result shr 1) xor $A001
      else Result := (Result shr 1);
     end;
  end;
{$R+}
end;


на всякий случай привожу и ф-цию вычисления контрольной суммы.


 
Игорь Шевченко ©   (2009-07-14 17:45) [1]


> Что это может быть???


Invalid user. Replace and strike any key when ready


 
Rouse_ ©   (2009-07-14 17:48) [2]

А ms создавать кто будет?


 
Palladin ©   (2009-07-14 17:50) [3]

Пушкин вестимо


 
Zheksonz   (2009-07-14 18:28) [4]


> Invalid user. Replace and strike any key when ready

бан отменили???

procedure TForm1.Button1Click(Sender: TObject);
const
CmdHZ: array[0..3] of byte = (01, 06, 00, 04);
var
CmdData: Word;
CmdCRC16: Word;
ms: TMemoryStream;
begin
ComPort.Open;
ms := TMemoryStream.Create;
CmdData := UpDown1.Position;
ms.WriteBuffer(CmdHZ, SizeOf(CmdHZ));
CmdData := Swap(CmdData);
ms.WriteBuffer(CmdData, SizeOf(CmdData));
CmdCRC16 := Swap(GetCRC16(ms.Memory, ms.Size));
ms.WriteBuffer(CmdCRC16, SizeOf(CmdCRC16));
ComPort.Write(ms.Memory^, ms.Size);
ms.Free;
ComPort.Close;
end;


сейчас код проходит, но устройство не воспринимает создаваемую команду... буду разбираться...


 
Zheksonz   (2009-07-14 21:40) [5]

странно... просматриваю в отладчике значение ms.Memory, оно не меняется вне зависимости от присвоений... всегда равно $14A058 может я неправильно пишу в буфер???


 
Loginov Dmitry ©   (2009-07-14 21:44) [6]


> странно... просматриваю в отладчике значение ms.Memory,
> оно не меняется вне зависимости от присвоений... всегда
> равно $14A058 может я неправильно пишу в буфер???


Оно само изменится когда ему будет надо!


 
Zheksonz   (2009-07-14 22:01) [7]


> Оно само изменится когда ему будет надо!

кому, ему???


 
Rouse_ ©   (2009-07-14 22:15) [8]


> просматриваю в отладчике значение ms.Memory, оно не меняется
> вне зависимости от присвоений... всегда равно $14A058

А зачем менять указатель на буффер?


 
Loginov Dmitry ©   (2009-07-14 22:23) [9]


> кому, ему???


значению ms.Memory


 
Sha ©   (2009-07-14 23:23) [10]

> Zheksonz   (14.07.09 17:38)
> решил всё-таки общаться с портом без помощи строк

Вот нафига тебя теперь в потоки занесло? Давай заюзай еще Мемо или файл.
Тебе ж в прошлой ветке было сказано, что достаточно packed record.

> на всякий случай привожу и ф-цию вычисления контрольной суммы

Судя по приведенной CRC у тебя используется Modbus протокол.
В нем при передаче CRC первым передается младший байт, а ты передаешь старший.


 
Zheksonz   (2009-07-14 23:28) [11]


> В нем при передаче CRC первым передается младший байт, а
> ты передаешь старший.

т.е. Swap не нужно делать???


> Вот нафига тебя теперь в потоки занесло? Давай заюзай еще
> Мемо или файл.Тебе ж в прошлой ветке было сказано, что достаточно
> packed record.


Сергей М. предложил этот вариант, я решил его попробовать...


 
Sha ©   (2009-07-14 23:31) [12]

> т.е. Swap не нужно делать???

Да, для CRC не надо


 
Zheksonz   (2009-07-14 23:52) [13]


> Sha ©   (14.07.09 23:23) [10]


const
CmdPref: array[0..3] of byte = (01, 06, 00, 04);
type
 CmdPack = packed record
   c_Pref: array[0..3] of byte;
   c_Data: array[0..1] of byte;
   c_crc16: array[0..1] of byte;
 end;


оно???


 
Sha ©   (2009-07-15 00:06) [14]


const
  CmdPref = $04000601;
type
  CmdPack = packed record
    Pref: integer;
    Data: word;
    crc16: word;
  end;
var
  cp: CmdPack;
begin
  cp.Pref:=CmdPref;
  cp.Data:=Swap(UpDown1.Position);
  cp.CRC16:=GetCRC16(cp, SizeOf(cp.Pref) + SizeOf(cp.Data));
 
  ComPort.Open;
  ComPort.Write(cp, SizeOf(cp));
  ComPort.Close;
end;


 
Zheksonz   (2009-07-15 00:10) [15]


> Sha ©   (15.07.09 00:06) [14]

красота... а я уже массивы подключил, для наполнения)))

а CRC16 Swap_нуть не нужно???


 
Zheksonz   (2009-07-15 00:17) [16]

всмысле Swap(GetCRC16(cp, SizeOf(cp.Pref) + SizeOf(cp.Data)));

и ещё, ф-ция GetCrc16 у меня принимает GetCRC16(P: PChar; Len: Word) а cp у нас имеет тип CmdPack

как проще привести их к одному типу???


 
Sha ©   (2009-07-15 00:18) [17]

> а CRC16 Swap_нуть не нужно???

Нет. В твоем процессоре целочисленные данные (например, типа word) хранятся в low-endian представлении (дословно: младшим концом вперед),
т.е. младший байт - в младшем адресе. А это как раз то, что тебе надо, если, конечно, у тебя используется протокол Modbus.


 
Zheksonz   (2009-07-15 00:21) [18]

да, протокол ModBus


 
Sha ©   (2009-07-15 00:22) [19]

> Zheksonz   (15.07.09 00:17) [16]
> как проще привести их к одному типу???

тогда надо так:
cp.CRC16:=GetCRC16(@cp, SizeOf(cp.Pref) + SizeOf(cp.Data));

ЗЫ. Вообще-то, GetCRC16 очень причудливо написана )


 
Германн ©   (2009-07-15 00:24) [20]


> Rouse_ ©   (14.07.09 22:15) [8]
>
>
> > просматриваю в отладчике значение ms.Memory, оно не меняется
> > вне зависимости от присвоений... всегда равно $14A058
>
> А зачем менять указатель на буффер?
>

А ты, Саш сначала попробуй объяснить автору что такое буфер, что такое указатель и что он (автор) видит в отладчике.
Даже твой богатый опыт на других форумах тебе не поможет. :)


 
Zheksonz   (2009-07-15 00:26) [21]

а то, что GetCRC16 считает контрольную сумму не от всего cp , а от cp.Pref и cp.Data не страшно???


 
Zheksonz   (2009-07-15 00:27) [22]


> А ты, Саш сначала попробуй объяснить автору что такое буфер,
>  что такое указатель и что он (автор) видит в отладчике.
>  Даже твой богатый опыт на других форумах тебе не поможет.
>  :)

0


 
Zheksonz   (2009-07-15 00:28) [23]


> а то, что GetCRC16 считает контрольную сумму не от всего
> cp , а от cp.Pref и cp.Data не страшно???

виноват... длина же указана...


 
Sha ©   (2009-07-15 00:29) [24]

> Zheksonz   (15.07.09 00:26) [21]
> от всего cp , а от cp.Pref и cp.Data

А разве там, кроме них, есть еще что-то?
Я не представляю, как можно считать по-другому.


 
Zheksonz   (2009-07-15 00:42) [25]


> Sha ©   (15.07.09 00:29) [24]


в отладчике, перед записью в порт:
cp = (67110401, 34835, 24005)

это и есть четыре байта префикса = 01 06 00 04
два байта передаваемого значения = 5000
и два байта контрольной суммы???


 
Sha ©   (2009-07-15 00:47) [26]

Проверить на калькуляторе?


 
Zheksonz   (2009-07-15 00:49) [27]

)) нет конечно... просто может опытный глаз сразу разглядит какое-нибудь несоответствие...


 
Sha ©   (2009-07-15 00:52) [28]

Думаю, 3 оператора присваивания выполнились верно.


 
Zheksonz   (2009-07-15 00:58) [29]

)) к присваиванию подозрений нет, а вот к развороту байтов немного настороженно отношусь... правильно ли будет вопринята сформированая команда.


 
Sha ©   (2009-07-15 01:02) [30]

В калькуляторе переведи данные в hex и выпиши байты от младшего к старшему.
Почитай про представление целых в архитектуре I-32.


 
Zheksonz   (2009-07-15 01:07) [31]


> Sha ©   (15.07.09 01:02) [30]


Ок.

спасибо


 
Sha ©   (2009-07-15 07:19) [32]

> I-32
правильно, конечно, так: IA-32.


 
Slym ©   (2009-07-15 08:17) [33]

из под полы... через анонимные прокси пробиваюсь...
unit MVUComm;
interface
uses SysUtils,ComPortCtrl;
type
 TMVUPort=class(TComPort)
 public
   function GetState(Adr:byte;Reg:word;out State:boolean):boolean;
   function SetState(Adr:byte;Reg:word;State:boolean):boolean;
 end;

implementation
{
ASCII MODBUS- :CMD#13#10
MODBUS proto
1.adr:byte
2.Fn:byte =  read:$03, write:$10
3.Adr}

type
 TWordRec = packed record
   Hi,Lo:Byte;
 end;
 TMBRegReadCmd=packed record
   Adr:byte;
   Fn:byte;
   RegAdr:TWordRec;
   RegCnt:TWordRec;
   CRC:byte;
 end;
 TMBRegReadAnswer=packed record
   Adr:byte;
   Fn:byte;
   Len:byte;
   Data:TWordRec;
   CRC:byte;
 end;

 TMBRegWriteCmd=packed record
   Adr:byte;
   Fn:byte;
   RegAdr:TWordRec;
   RegCnt:TWordRec;
   Len:byte;
   Data:TWordRec;
   CRC:byte;
 end;
 TMBRegWriteAnswer=packed record
   Adr:byte;
   Fn:byte;
   RegAdr:TWordRec;
   RegCnt:TWordRec;
   CRC:byte;
 end;

//ModBus CRC routines
//Check ModBus command CRC
function MBCheckCRC(MBCmd:PByte;Size:integer):boolean;
var LRC:byte;
begin
 LRC:=0;
 repeat
   LRC:=LRC+MBCmd^;
   inc(MBCmd);
   Dec(Size);
 until Size=0;
 result:=(LRC=0);
end;

//Set ModBus command CRC
procedure MBSetCRC(MBCmd:PByte;Size:integer);
var LRC:byte;
begin
 Dec(Size);
 LRC:=0;
 repeat
   LRC:=LRC+MBCmd^;
   inc(MBCmd);
   Dec(Size);
 until Size=0;
 MBCmd^:=-LRC;
end;

//ModBus string routines
//Convert cmd to string with calc CRC
function MBCmdToStr(MBCmd:PByte;Size:integer):string;
begin
 MBSetCRC(MBCmd,Size);
 result:=&#39;&#39;;
 repeat
   result:=result+IntToHex(MBCmd^,2);
   inc(MBCmd);
   Dec(Size);
 until Size=0;
 result:=&#39;:&#39;+result+#13#10;
end;

//Convert string to cmd with checking CRC
function StrToMBCmd(Str:string;MBCmd:PByte;Size:integer):boolean;
var LRC:byte;
begin
 FillChar(MBCmd^,Size,0);
 result:=false;
 if copy(Str,1,1)<>&#39;:&#39; then exit;
 if copy(Str,length(Str)-1,2)<>#13#10 then exit;
 Str:=copy(Str,2,length(Str)-3);
 if (length(Str) mod 2)<>0 then exit;
 if (length(Str) div 2)<>Size then exit;

LRC:=0;
 repeat
   MBCmd^:=byte(StrToInt(&#39;$&#39;+copy(Str,1,2)));
   Delete(Str,1,2);
   LRC:=LRC+MBCmd^;
   inc(MBCmd);
   Dec(Size);
 until Size=0;
 result:=(LRC=0);
end;

{ MVUPort }

function TMVUPort.GetState(Adr: byte; Reg: word;
 out State: boolean): boolean;
var
 Query:TMBRegReadCmd;
 Answer:TMBRegReadAnswer;
 QueryStr,AnswerStr,Str:string;
begin
 result:=false;
 FillChar(Query,SizeOf(Query),0);
 Query.Adr:=Adr;
 Query.Fn:=$03;
 Query.RegAdr.Lo:=Reg;
 Query.RegCnt.Lo:=1;
 QueryStr:=MBCmdToStr(@Query,SizeOf(Query));

 AnswerStr:=&#39;&#39;;
 Lock;
 try
   Purge;
   WriteBuffer(PChar(QueryStr)^,Length(QueryStr));
   repeat
     SetLength(Str,256);
     SetLength(Str,Read(PChar(Str)^, Length(Str)));
     if Str=&#39;&#39; then break;
     AnswerStr:=AnswerStr+Str;
   until (pos(#13#10,AnswerStr)=0) and (length(AnswerStr)<256);
 finally
   Unlock;
 end;
 if StrToMBCmd(AnswerStr,@Answer,SizeOf(Answer)) then
 begin
   if (Answer.Adr<>Query.Adr) or (Answer.Fn<>Query.Fn) then exit;
   result:= (Answer.Data.Lo=Lo(1000)) and (Answer.Data.Hi=Hi(1000));
end;
end;

function TMVUPort.SetState(Adr: byte; Reg: word;
 State: boolean): boolean;
var
 Query:TMBRegWriteCmd;
 Answer:TMBRegWriteAnswer;
 QueryStr,AnswerStr,Str:string;
begin
 result:=false;
 FillChar(Query,SizeOf(Query),0);
 Query.Adr:=Adr;
 Query.Fn:=$10;
 Query.RegAdr.Lo:=Reg;
 Query.RegCnt.Lo:=1;
 Query.Len:=SizeOf(Query.Data);
ifState then
 begin
   Query.Data.Lo:=Lo(1000);
   Query.Data.Hi:=Hi(1000);
 end else
 begin
   Query.Data.Lo:=Lo(0);
   Query.Data.Hi:=Hi(0);
 end;
 QueryStr:=MBCmdToStr(@Query,SizeOf(Query));
 AnswerStr:=&#39;&#39;;
 Lock;
 try
   Purge;
   WriteBuffer(PChar(QueryStr)^,Length(QueryStr));
   repeat
     SetLength(Str,256);
     SetLength(Str,Read(PChar(Str)^, Length(Str)));
     if Str=&#39;&#39; then break;
     AnswerStr:=AnswerStr+Str;
   until (pos(#13#10,AnswerStr)=0) and (length(AnswerStr)<256);
 finally
   Unlock;
 end;

 if StrToMBCmd(AnswerStr,@Answer,SizeOf(Answer)) then
   result:=CompareMem(@Answer,@Query,SizeOf(Answer)-1);
end;

end.


 
Slym ©   (2009-07-15 08:40) [34]

итоговая процедурка должна выглядеть примерно так
procedure writedata(data:word);
type
 TMBSingleRegWriteCmd=packed record
   Adr:byte;
   Fn:byte;
   RegAdr:TWordRec;
   Data:TWordRec;
   CRC:byte;
 end;
var
 Query:TMBSingleRegWriteCmd;
begin
 Query.Adr:=$01;
 Query.Fn:=$06;
 Query.RegAdr.Lo:=$04;
 Query.RegAdr.Hi:=$00;
 Query.Data.Lo:=Lo(data);
 Query.Data.Hi:=Hi(data);
 MBSetCRC(@Query,SizeOf(Query));
 ComPort.Write(Query, SizeOf(Query));
end;


 
Slym ©   (2009-07-15 09:27) [35]

финальный релиз
procedure MBSetCRC16(MBCmd:PByte;Size:integer);
var
 CRC:word;
 i:integer;
 loCRC:byte;
begin
 Dec(Size,SizeOf(word));
 CRC:= $FFFF;
 repeat
   WordRec(CRC).Lo:=MBCmd^ xor WordRec(CRC).Lo;
   for i := 1 to 8 do
   begin
     loCRC:=lo(CRC);
     CRC := (CRC shr 1);
     if (loCRC and $01)<>0 then
       CRC:=CRC xor $A001;
    end;
   inc(MBCmd);
   Dec(Size);
 until Size=0;
 PWord(MBCmd)^:=Swap(CRC);
end;

procedure WriteData(data:word);
type
 TWordRec = packed record
   Hi,Lo:Byte;
 end;
 TMBSingleRegWriteCmd=packed record
   Adr:byte;
   Fn:byte;
   RegAdr:TWordRec;
   Data:TWordRec;
   CRC:word;
 end;
var
 Query:TMBSingleRegWriteCmd;
begin
 Query.Adr:=$01;
 Query.Fn:=$06;
 Query.RegAdr.Lo:=$04;
 Query.RegAdr.Hi:=$00;
 Query.Data.Lo:=Lo(data);
 Query.Data.Hi:=Hi(data);
 MBSetCRC16(@Query,SizeOf(Query));
 ComPort.Write(Query, SizeOf(Query));
end;


 
Sha ©   (2009-07-15 09:43) [36]

> Slym ©   (15.07.09 08:40) [34]

1. В протоколе Modbus все данные, кроме CRC, передаются в big-endian представлении. Поэтому у тебя вместо адреса устройства $0004 будет передан адрес $0400. Кроме того, передаваемые в процедуру данные придется предварительно свопить.

2. У автора CRC двухбайтовая и вычисляется по другому алгоритму.


 
Slym ©   (2009-07-15 09:56) [37]

Sha ©   (15.07.09 9:43) [36]
1. В протоколе Modbus все данные, кроме CRC, передаются в big-endian представлении. Поэтому у тебя вместо адреса устройства $0004 будет передан адрес $0400. Кроме того, передаваемые в процедуру данные придется предварительно свопить.

поэтому применена собственная TWordRec с переставленными байтами :)
Sha ©   (15.07.09 9:43) [36]
2. У автора CRC двухбайтовая и вычисляется по другому алгоритму.

это точно: я привел ASCII Modbus там LRC однобайтовый
но я поправился в [35] :) с ошибкой PWord(MBCmd)^:=Swap(CRC); Swap убрать


 
Sha ©   (2009-07-15 10:12) [38]

> Slym ©   (15.07.09 09:56) [37]
> поэтому применена собственная TWordRec

Извини, не заметил, имя типа очень похоже на WordRec из SysUtils


 
Zheksonz   (2009-07-15 10:20) [39]


> Sha ©   (15.07.09 07:19) [32]

Всё проверил, всё отлично работает. Спасибо.

ну а теперь самое вкусное)))

всё это дело нужно прикрутить к ДОСовской тачке(к сожалению без этого никак) + на языке программирования СИ.

Впринципе этапы инициализации порта и наполнения команды пройдены... но вот не воспринимаются эти команды инвертором. Может быть это связано с тем, что я просто в цикле посылал 8 байт не разворачивая их, т.е. не меняя верхний с нижним???

for(i=0;i<7;i++) out_byte(send[i]);

где send[] = 0x01, 0x06, 0x00, 0x04, 0x13, 0x88, 0xC5, 0x5D


 
Zheksonz   (2009-07-15 10:25) [40]


> Slym ©   (15.07.09 08:17) [33]

всё хорошо, но юнит требует ComPortCtrl.dcu


 
Sha ©   (2009-07-15 10:26) [41]

> Slym ©   (15.07.09 09:27) [35]

похоже, оператор

MBSetCRC16(@Query,SizeOf(Query));

надо заменить на

MBSetCRC16(@Query,SizeOf(Query)-2);


 
Zheksonz   (2009-07-15 10:29) [42]

прикрученые вместо него CPort и CPortCtl не восприняли многие ф-ции из этого юнита.


 
Sha ©   (2009-07-15 10:32) [43]

> Zheksonz   (15.07.09 10:20) [39]
> Может быть это связано с тем, что я просто в цикле посылал 8 байт не разворачивая их, т.е. не меняя верхний с нижним???

ДА и АД вроде разные слова


 
Slym ©   (2009-07-15 10:33) [44]

Sha ©   (15.07.09 10:26) [41]
ниче нинадо

procedure MBSetCRC16(MBCmd:PByte;Size:integer);
var
CRC:word;
i:integer;
loCRC:byte;
begin
Dec(Size,SizeOf(word));
CRC:= $FFFF;
repeat
  WordRec(CRC).Lo:=MBCmd^ xor WordRec(CRC).Lo;
  for i := 1 to 8 do
  begin
    loCRC:=lo(CRC);
    CRC := (CRC shr 1);
    if (loCRC and $01)<>0 then
      CRC:=CRC xor $A001;
   end;
  inc(MBCmd);
  Dec(Size);
until Size=0;
PWord(MBCmd)^:=CRC;
end;

Zheksonz   (15.07.09 10:25) [40]
пользуй только [35] пост... остальное не тот модбас


 
Zheksonz   (2009-07-15 10:41) [45]


> ДА и АД вроде разные слова

это да... остаётся одно непонятно... с какой целью были сделаны все эти развороты??? неужели не проще было бы использовать более читаемую структуру запроса???


 
Sha ©   (2009-07-15 10:58) [46]

> Slym ©   (15.07.09 10:33) [44]
> ниче нинадо

Ужас. Понимаю, что хотелось упростить. Но в результате получаем лишнюю запутанность.
В процедуру вычисления CRC передаем не размер данных, подлежащих суммированию, а размер+2. Кроме того, используем различающиеся между собой TWordRec и WordRec.

> Zheksonz   (15.07.09 10:41) [45]
>  с какой целью были сделаны все эти развороты???

Понемногу начинаю привыкать к твоей терминологии ).
Данные передаются в представленнии big-endian с целью соблюдения протокола Modbus/


 
Zheksonz   (2009-07-15 11:05) [47]


> Sha ©   (15.07.09 10:58) [46]

т.е. как мне правильно отправить формируемую мной команду???, которая в шестнадцатиричном представлении выглядит вот так: 0x01, 0x06, 0x00, 0x04, 0x13, 0x88, 0xC5, 0x5D


 
Zheksonz   (2009-07-15 11:07) [48]


> Slym ©   (15.07.09 10:33) [44]


кстати да... код не прошёл... вернее не был адекватно воспринят инвертором((( хоть MBSetCRC16(@Query,SizeOf(Query));, хоть MBSetCRC16(@Query,SizeOf(Query)-2);


 
Sha ©   (2009-07-15 11:08) [49]

Так и отправь, сначала первый байт, потом второй...


 
Zheksonz   (2009-07-15 11:50) [50]


> Sha ©   (15.07.09 11:08) [49]


меня запутал вот этот формат... тут вообще все байты задом наперёдCmdPref = $04000601;


 
Sha ©   (2009-07-15 12:10) [51]

> Zheksonz   (15.07.09 11:50) [50]
> тут вообще все байты задом наперёд CmdPref = $04000601

Это число такое большое. При хранении в памяти занимает 4 байта, а его адресом является адрес самого младшего байта $01. В следующем байте хранится $06, далее $00 и $04. Когда мы станем его передавать, то укажем его адрес, т.е. адрес самого младшего байта. С него и начнется передача. Затем последовательно передадутся оставшиеся байты. Получается в точности тот же эффект, как при передаче массива байтов $01, $06, $00, $04.


 
Zheksonz   (2009-07-15 12:56) [52]

понятно, а байты 5 и 6, которые служат для передачи параметра и 2 байта контрольной суммы, в ДОСе, на СИ, нужно разворачивать???


 
Sha ©   (2009-07-15 13:06) [53]

Устройству безразлично, на каком языке написана программа и под какой ОС она выполняется.
Твоя задача - обеспечить передачу такой последовательности байт, которую требует протокол обмена.


 
Zheksonz   (2009-07-15 13:23) [54]

Sha ©   (15.07.09 13:06) [53]
согласен, ,т.е., с точки зрения протокола ModBus, правильным будет развернуть байты данных и байты контролной суммы перед отправкой???


 
Sha ©   (2009-07-15 13:39) [55]

> Zheksonz   (15.07.09 13:23) [54]

"с точки зрения протокола ModBus" ты должен обеспечить передачу той же последовательности байт, которую передает код из [14].
По-разному объявленные структуры должны заполняться по-разному, например:

const
 CmdPref = $04000601;
type
 CmdPack = packed record
   Pref: integer;
   Data: word;
   crc16: word;
 end;
......
 cp.Pref:=CmdPref;

или

const
 CmdPref1 = $0601;
 CmdPref2 = $0400;
type
 CmdPack = packed record
   Pref1: word;
   Pref2: word;
   Data: word;
   crc16: word;
 end;
......
 cp.Pref1:=CmdPref1;
 cp.Pref2:=CmdPref2;

или

const
 CmdPref1 = $01;
 CmdPref2 = $06;
 CmdPref3 = $00;
 CmdPref4 = $04;
type
 CmdPack = packed record
   Pref1: byte;
   Pref2: byte;
   Pref3: byte;
   Pref4: byte;
   Data: word;
   crc16: word;
 end;
......
 cp.Pref1:=CmdPref1;
 cp.Pref2:=CmdPref2;
 cp.Pref3:=CmdPref3;
 cp.Pref4:=CmdPref4;


> правильным будет развернуть байты данных и байты контролной суммы перед отправкой???

На мой взгляд, лучше воздерживаться от употребления слова "развернуть",
такая "терминология" находится за гранью понимания нормального программиста.


 
Zheksonz   (2009-07-15 14:13) [56]

а что, кто-то ещё считает меня нормальным программистом???)) ок. учту.

с однобайтовыми значениями понятно, а как быть с Data и crc16, которые насчитывают по 2 байта???


 
Sha ©   (2009-07-15 14:21) [57]

> Zheksonz   (15.07.09 14:13) [56]
> ок. учту.

Просто я привык к тому, что обычно развертывают циклы, и впадаю в ступор при необходимости развернуть данные.

> а как быть с Data и crc16, которые насчитывают по 2 байта???

В точности так, как в [14].
Или ты еще раз хочешь поговорить об этом?


 
Zheksonz   (2009-07-15 14:30) [58]


> Sha ©   (15.07.09 14:21) [57]


спасибо огромное!


 
Slym ©   (2009-07-16 04:59) [59]

Zheksonz   (15.07.09 11:07) [48]
procedure MBSetCRC16(MBCmd:PByte;Size:integer);
var
CRC:word;
i:integer;
loCRC:byte;
begin
Dec(Size,SizeOf(word));
CRC:= $FFFF;
repeat
 WordRec(CRC).Lo:=MBCmd^ xor WordRec(CRC).Lo;
 for i := 1 to 8 do
 begin
   loCRC:=lo(CRC);
   CRC := (CRC shr 1);
   if (loCRC and $01)<>0 then
     CRC:=CRC xor $A001;
  end;
 inc(MBCmd);
 Dec(Size);
until Size=0;
PWord(MBCmd)^:=CRC;
end;

попробуй поиграться c присвоением +swap как в [35] посте
PWord(MBCmd)^:=swap(CRC);

со свапом генерирует такойже црц как и твой код... да и кто мешает тебе использовать твою функцию вычисления CRC



Страницы: 1 2 вся ветка

Текущий архив: 2009.09.20;
Скачать: CL | DM;

Наверх




Память: 0.64 MB
Время: 0.013 c
2-1247736038
Кирей
2009-07-16 13:20
2009.09.20
Ошибка неизвестного типа


2-1248020231
bag
2009-07-19 20:17
2009.09.20
статический массив


15-1246915947
Германн
2009-07-07 01:32
2009.09.20
Система "Экспресс-3" от РЖД


2-1247762842
fics)
2009-07-16 20:47
2009.09.20
Отчет в *.RTF


6-1206621682
Vikindos
2008-03-27 15:41
2009.09.20
clientSocket посылка строкой