Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

WriteBuffer - error - Access violation at addr... почему??? [D7, XP]


Страницы:   1 2 3

Zheksonz ©   (2009-07-14 17:38:00) 

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

Код:
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;


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


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

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


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


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


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


Sha   (2009-07-15 14:21:00) [3]

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

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

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

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


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

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

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


Sha   (2009-07-15 13:39:00) [5]

> 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 13:23:00) [6]

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


Sha   (2009-07-15 13:06:00) [7]

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


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

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


Sha   (2009-07-15 12:10:00) [9]

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

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


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


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


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


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

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


Zheksonz   (2009-07-15 11:07:00) [12]


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


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


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


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

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


Sha   (2009-07-15 10:58:00) [14]

> 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 10:41:00) [15]


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

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


Slym   (2009-07-15 10:33:00) [16]

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] пост... остальное не тот модбас


Sha   (2009-07-15 10:32:00) [17]

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

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


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

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


Sha   (2009-07-15 10:26:00) [19]

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

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

MBSetCRC16(@Query,SizeOf(Query));

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

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


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


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

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


Страницы:   1 2 3

Наверх

Титульная страница Поиск, карта сайта Написать письмо