Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 2009.09.20;
Скачать: [xml.tar.bz2];

Вниз

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;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.63 MB
Время: 0.005 c
2-1247658555
b/@.
2009-07-15 15:49
2009.09.20
Можно ли поместить на форме графикс поверх винконтрол ?


15-1248335496
oxffff
2009-07-23 11:51
2009.09.20
Artificial brain ten years away


15-1248422799
GanibalLector
2009-07-24 12:06
2009.09.20
Win2003 ограничение запуска приложения


2-1248162543
lewka
2009-07-21 11:49
2009.09.20
нажатие на ссылку в TWebbrowser


15-1248294604
Юрий
2009-07-23 00:30
2009.09.20
С днем рождения ! 23 июля 2009 четверг





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский