![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
WriteBuffer - error - Access violation at addr... почему??? [D7, XP]
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