Перебор структур в Twincat PLC (Структурированный текст)
Скажем, у меня есть следующая структура, заполненная информацией об оси:
TYPE AxisInfo :
STRUCT
AxisStatus : ARRAY [0..3] OF BYTE;
DriveStatis : ARRAY [0..3] OF BYTE;
FeedRate : ARRAY [0..3] OF BYTE;
Inputs : BYTE;
Outputs : BYTE;
Extra : BYTE;
CurPosW: UDINT;
CurPosX: UDINT;
CurPosY: UDINT;
CurPosZ: UDINT;
CurVelX: UDINT;
CurVelY: UDINT;
CurVelZ: UDINT;
ComPos : UDINT;
SetVel : UDINT;
DacVel : UDINT;
WinchErrPos : UDINT;
XYZErrPos : UDINT;
EnFaults : UDINT;
ActFaults : UDINT;
BpFaults : UDINT;
BpTimeLeft : UDINT;
Эта структура содержит 82 байта. У меня будет 8 таких структур, работающих постоянно (так как у меня 8 осей). Это составляет 656 байтов в сочетании со всеми структурами.
Теперь у меня есть переменная с именем Buffer:
Buffer: ARRAY [0..1023] OF BYTE;
Я хотел бы иметь возможность заполнить этот буфер каждой из 8 структур, по порядку. Например:
Buffer[0] := AxisStatus[0]; //this is for the 1st axis
Buffer[1] := AxisStatus[1]; //this is for the 1st axis
….
Buffer[78] := BpTimeLeft; //this is for the 1st axis
…
Buffer[648] := BpFaults;
Buffer[652] := BpTimeLeft; //this is for the 8th axis
Есть ли способ в ST на ПЛК, итерировать элементы структуры, а затем помещать эти элементы в буфер и проверять, что они находятся в нужных местах? Знаете ли вы какие-нибудь хитрости, чтобы сделать это?
Я спрашиваю об этом, потому что я могу сделать это следующим способом,
For axisIndex:=1 to 8 DO
Buffer[0] := AxisStatus[0];
Buffer[1] := AxisStatus[1];
…
Buffer[78] := BpTimeLeft; this is for the 1st axis
END_FOR
но я должен напечатать каждую строку, для которой должен быть выделен буфер, а затем должен выполнить какой-то трюк после того, как я заполнил буфер первой осью, чтобы избежать перезаписи первых 82 байтов. Должен быть какой-то способ сделать это автоматически в случае, если я буду менять членов структуры в будущем.
4 ответа
Я предлагаю использовать {attribute 'pack_mode' := '1'}
в декларации структуры, а затем вы можете легко скопировать данные с MEMCPY.
Структурная декларация:
{attribute 'pack_mode' := '1'}
TYPE AxisInfo :
STRUCT
Теперь вы можете скопировать всю структуру, например, в массив байтов или просто в некоторые переменные. Например, скопировать Inputs
из вашей структуры в байтовый массив, вы можете использовать что-то вроде
MEMCPY(ADR(Buffer[2]), ADR(AxisStatus) + 12, 1)
который копирует один байт из (адрес AxisStatus + 12 байт, что равно Inputs
) в буфер [2]. Если вы копируете более одного байта, он скопирует их в буфер [2], буфер [3], буфер [4] и так далее.
Memcpy очень полезен в подобных ситуациях.
Чтобы скопировать всю структуру в начало буфера, вы можете простоMEMCPY(ADR(Buffer), ADR(AxisStatus), SIZEOF(AxisStatus))
Копировать следующую структуру после нееMEMCPY(ADR(Buffer) + SIZEOF(AxisStatus), ADR(AxisStatus), SIZEOF(AxisStatus))
Честно говоря, я бы не стал зацикливаться на структуре, чтобы просто получить нужную информацию о состоянии. Что если у вас 100 осей?
Это не хорошо масштабируется.
Что если вы измените дизайн своей программы?
Вы можете создать функциональный блок (назовем его AxisDevice), который, например, моделирует ось.
AxisDevice
будет иметь все функциональные блоки, необходимые для работы axis
внутри него. Затем вы пройдете AXIS_REF
в AxisDevice
и может получить информацию о состоянии axis
благодаря свойству (например: getStatus:= AxisStatusStruct).
Таким образом, вам просто нужно решить и реализовать один раз, какая информация об оси является "общедоступной".
Все твои 8 axis
может быть типа AxisDevice
и предоставить информацию во время выполнения при необходимости.
Вы пытались использовать функции MEMCPY? Это должно быть гораздо меньше усилий... Вы можете скопировать Struct и Byte Array в обоих направлениях. С некоторым указателем индекса и смещения.
Вы не можете гарантировать местоположение байтов и расположение элементов, потому что компилятор оптимизирует пространство на основе аппаратной цели. Вы не можете выиграть эту битву - вы летите против того, что такое структура.
1). Вы можете вручную упаковать свой собственный байтовый массив, чтобы гарантировать положение вместо использования структуры (но тогда вы могли бы также программировать на машинном языке, потому что вы побеждали программирование высокого уровня...
BUFFER: = ARRAY [0..7] OF AxisInfo;
BUFFER [0] будет осью 0, BUFFER[1] будет осью 1 и т. Д.
2). Вы можете определить свой буфер как массив вашей структуры и прекратить доступ к определенным ячейкам памяти (что становится зависимым от оборудования / платформы!)
3). Если вы отправляете данные в HMI или другое устройство, которое не знает структуру, а только байты, то вы застряли вручную, отображая элементы структуры в положения в байтовом массиве. Это нормальное решение для связи с полевой шиной, такой как ModbusTCP.