Просмотр полной версии : Как циклически опрашивать регистры?
Радонежский
04.09.2014, 15:08
Например, ModBus (slave) имеет 40 регистров. В программе работает «свой» цикл, который записывает значения на каждом шаге только двух регистров из этих 40. Этот цикл отличен от цикла самого ПЛК. Каким образом можно обраться из цикла и записать регистры. Т.е. должна работать следующая схема
[цикл №1]=> [регистр 2 byte №1] и [регистр 2 byte №2]
[цикл №2]=> [регистр 2 byte №3] и [регистр 2 byte №4]
…..
[цикл №20]=> [регистр 2 byte №19] и [регистр 2 byte №20]
заново
[цикл №1]=> [регистр 2 byte №1] и [регистр 2 byte №2]
Конечно можно использовать Case , но нет ли компактнее решения?
14249
Это не опрос регистров. Сервер/slave не может опрашивать сам себя. Опрашивается извне мастером сети.
Индексация регистров во втором кодесисе не предусматривается. Можно попробовать взять адрес первого регистра при помощи ADR() и посмотреть, что там есть дальше, и если следующие регистры идут через равномерные промежутки, то прибавлять к адресу первого регистра произведение расстояния на индекс нужного регистра. Таким образом у вас будет адрес переменной соответствующего регистра, словно вы его из массива взяли. Но если кому-то из-за таких извращений оторвёт конечности, то я вам ничего не говорил. Лучше уж кейсом в отдельную подпрограмму вынесите.
А так попахивает индусским кодом. Что вы там сделать пытаетесь, конкретнее?
Радонежский
05.09.2014, 09:10
Предназначение системы. ПЛК опрашивает 20 модулей МК110 (разного типа). В принципе их количество может варьироваться, главное быстро изменить код программы. Поэтому выбран для хранения массив, т.е. ПЛК держит всю информацию в массиве, где строчка содержит информацию об одном МК110 и производит операции управления вне зависимости от команд ModBus (Master). Другими словами ПЛК осуществляет местное управление, а ModBus (Master) удаленное. Конечно существует вопрос приоритета команд, но это здесь не требуется. Т.е. Сигнал управления (запись регистра выхода) на МК110 может прийти от:
1) самого ПЛК
2)с внешнего устройства ModBus (Master)
Вот для осуществления последнего варианта (управление и передачи состояния) как раз и хотелось бы из цикла обратиться и записать значение регистра ModBus (slave). Например
VAR_GLOBAL
In_0 AT%QW9.1.0:WORD;
In_1 AT%QW9.2.0:WORD;
In_2 AT%QW9.3.0:WORD;
…
In_19 AT%QW9.19.0:WORD;
END_VAR
FUNCTION Byte2_to_Word : WORD; (*объединяет два байта в WORD *)
программа:
FOR i:=0 TO 19 DO (*массив c 20 строчками, содержащий регистры МК110*)
Massiv[i, 0]:=…; (*запись в массив прочитанного регистра входа МК110*)
Massiv[i, 1]:=…; (*запись в массив прочитанного регистра выхода МК110*)
CASE i OF
0: In_0:= Byte2_to_Word (Massiv[0, 0], (Massiv[0, 1]); (*Regist_MK110_N1*)
1: In_1:= Byte2_to_Word (Massiv[1, 0], (Massiv[1, 1]); (*Regist_MK110_N2*)
2: In_2:= Byte2_to_Word (Massiv[2, 0], (Massiv[2, 1]); (*Regist_MK110_N3*)
…
19: In_19:= Byte2_to_Word (Massiv[19, 0], (Massiv[19, 1]); (*Regist_MK110_N20*)
END_CASE
END_FOR
Вот хотелось бы без Case обойтись. Предполагается, что объявленные переменные ModBus (slave) будут располагаться в памяти контроллера последовательно и без пропусков. Надо попробовать указатели ADR() применить, но я в них не силен. Пока думаю в цикле надо вместо Case:
p:= ADR(In_0)+I; (*i-индекс массива, [Byte]*)
p1:=p+1; (*адрес следующего байта *)
А как, зная адрес, записать значение по этому адресу? Я прав:
p^:= Massiv[I, 0]; (*первый байт WORD*)
p1^:= Massiv[I, 1]; (*втрой байтWORD*)
Почему «попахивает индусским кодом?». Можете предложить более рациональную логику программы?
Предполагается, что объявленные переменные ModBus (slave) будут располагаться в памяти контроллера последовательно и без пропусков.
Указатель на массив структур/фблоков
Радонежский
05.09.2014, 15:26
По яснее, пример или ссылку можете написать?
Выкиньте все %. В 9.1.0 вбейте имя. Например x
f.block mk
var_input
x1 : ...
x2 : ...
...
end_var
код - ";"
f.block slave //если область io сложнее чем только массив
var_input
..
mk : array [1..??] of mk;
..
end_var
код - ";"
global_var
pslave : pointer to slave;
pslave := adr(x);
for i := 1 to .. do
pslave^.mk[i](x1 := ...., x2 := ..., ...); //забиваем поля //типа with
end_for
!!! Ровнять под 4 байта.
PS
Т.к. сама задача непонятна, что за мк неясно, привел как идею.
"попахивает индусским кодом" когда начинаете возню с какими-то дурацкими байтами и т.п. Работайте с структурами целиком или с целевыми типами
Бонус.
Забываете про платформу. Портация - наколотить 4 или 2 byte в слейв и забить имя x
Радонежский
08.09.2014, 09:27
"Тип with" - это специализированных тип данных, определяемых пользователем?
Типа оператора with из делфи и др.
Установка полей при вызове фб-пустышки
Радонежский
09.09.2014, 15:46
Спасибо за критику и ответы. Применение вместо функционального блока mk, структуры ниже чем будет хуже или лучше для распределения памяти? Стоит ли применять перечисление, или лучше чтобы все поля были WORD так как для 32 разрядного процессора это не играет роли? Был бы признателен, за какой-нибудь пример.
TYPE mk :
STRUCT
Adress: BYTE; (*сетевой адрес*)
Type_MK: BYTE; (*тип модуля: модуль управления или расширения*)
(**)Group_MK: BYTE; (*поддерживает ли модуль групповое чтение регистра*)
Number_RS485: BYTE; (*Номер интерфейса RS-485*)
NumReg_In: BYTE; (*адрес регистра входов МК*)
NumReg_Out: BYTE; (*адрес регистра выходов МК*)
Project_Pozhar: WORD; (*содержимое регистра выходов МК записываемое при пожаре*)
….
END_STRUCT
END_TYPE
Powered by vBulletin® Version 4.2.3 Copyright © 2026 vBulletin Solutions, Inc. All rights reserved. Перевод: zCarot