Просмотр полной версии : СЧИТЫВАНИЕ ДАННЫХ ПО MODBUS RTU В МНОГОМЕРНЫЙ МАССИВ ДАННЫХ
Здравствуйте!
Подскажите, пожалуйста, можно ли осуществить считывание данных панелью СПК207 по MODBUS RTU в многомерный массив вида ARRAY [1..2] OF ARRAY [1..79] OF WORD?
В моем примере имеется переменная DataInput:ARRAY [1..2] OF ARRAY [1..79] OF WORD.
При конфигурировании каналов MODBUS RTU и привязке их к переменным программы я указываю: Application.MIRS.DataInput[1][1]. Как я выяснила, такое обращение не корректно. Можно ли осуществить данную задачу или считывание осуществляется только в одномерный массив?
22640
Евгений Кислов
15.02.2016, 13:04
В моем примере имеется переменная DataInput:ARRAY [1..2] OF ARRAY [1..79] OF WORD.
При конфигурировании каналов MODBUS RTU и привязке их к переменным программы я указываю: Application.MIRS.DataInput[1][1]. Как я выяснила, такое обращение некорректно.
Добрый день.
Каким образом вы это выяснили?
Конфигуратор среды ожидает одномерный массив, и вероятно, поэтому просто так подставить многомерный нельзя. Но можно:
а) воспользоваться библиотекой SysLibMem (или SysMem — не помню, как в третьем кодесисе), а именно функцией SysMemCpy, чтобы скопировать содержимое одномерного массива в многомерный в один приём;
б) просто объявить указатель на многомерный массив, присвоить ему адрес одномерного массива, и обращаться через указатель.
VAR
plainArray: ARRAY [0..79] OF WORD;
ptrMdArray: ARRAY [1..2] OF ARRAY[0..39] OF WORD;
END_VAR
ptrMdArray := ADR(plainArray);
test := ptrMdArray^[1][23];
Добрый день.
Каким образом вы это выяснили?
Т.к. возникает ошибка при компиляции.
Евгений Кислов
15.02.2016, 13:26
Т.к. возникает ошибка при компиляции.
Тогда покажите ее, пожалуйста. Какой версией CODESYS вы пользуетесь?
Тогда покажите ее, пожалуйста. Какой версией CODESYS вы пользуетесь?
Версия CODESYS V3.5 SP6 Patch 4
22641
Евгений Кислов
15.02.2016, 13:40
Версия CODESYS V3.5 SP6 Patch 4
22641
У вас имя ФБ совпадает с именем slave-устройства. Попробуйте задать им разные имена. Если ошибки не исчезнут, выкладывайте архив проекта.
Да, все верно, ошибки были из-за одинаковых имен.
Спасибо!
У меня возник еще один вопрос, связанный со считыванием данных.
Есть устройство, с которого необходимо считать данные по Modbus RTU в обычный одномерный массив (рисунок 1).
22655
В том случае, когда я объявляю функциональный блок в программе PLC_PRG (рисунок 5), данные с опрашиваемого устройства приходят корректно (рисунок 4)
22657
22658
Если я объявляю функциональный блок в списке глобальных переменных GVL (рисунок 2) и не объявляю его в PLC_PRG (рисунок 6), тогда данные с устройства в массив не приходят (рисунок 3)
22659
22660
22661
Получается, что так делать нельзя?
Евгений Кислов
16.02.2016, 09:00
У меня возник еще один вопрос, связанный со считыванием данных.
Есть устройство, с которого необходимо считать данные по Modbus RTU в обычный одномерный массив (рисунок 1).
22655
В том случае, когда я объявляю функциональный блок в программе PLC_PRG (рисунок 5), данные с опрашиваемого устройства приходят корректно (рисунок 4)
22657
22658
Если я объявляю функциональный блок в списке глобальных переменных GVL (рисунок 2) и не объявляю его в PLC_PRG (рисунок 6), тогда данные с устройства в массив не приходят (рисунок 3)
22659
22660
22661
Получается, что так делать нельзя?
Выложите архив проекта, пожалуйста.
https://yadi.sk/d/tqw8VMdbouKzg
Евгений Кислов
16.02.2016, 12:53
https://yadi.sk/d/tqw8VMdbouKzg
Проверил проект - обмен идет. Не обращайте внимания на надпись NoBP в компоненте Modbus - смотрите на значения переменных в программе.
На скриншоте - считал из слэйва число 10 в один из элементов массива.
22668
Здравствуйте, не хочу новую тему открывать.
По нестандартному протоколу приходит(буфер) массив байт, его хочу преобразовать в массив типа INT.
решил через цикл FOR записывать из буфера в двумерный массив
Как присвоить значения из одномерного массива в двумерный?
-------------------
a_a_byte: ARRAY [1..10] OF ARRAY [1..2] OF byte;
a_byte: OF ARRAY [1..20] OF byte;
i, w :int;// i - номер массива байт; w- номер байта массива
-------------
a_a_byte[i,w]:=a_byte[i+5],a_byte[i+4] --компилятор ругается,а я не знаю как правильно..
Евгений Кислов
22.06.2022, 06:15
Здравствуйте, не хочу новую тему открывать.
По нестандартному протоколу приходит(буфер) массив байт, его хочу преобразовать в массив типа INT.
решил через цикл FOR записывать из буфера в двумерный массив
Как присвоить значения из одномерного массива в двумерный?
-------------------
a_a_byte: ARRAY [1..10] OF ARRAY [1..2] OF byte;
a_byte: OF ARRAY [1..20] OF byte;
i, w :int;// i - номер массива байт; w- номер байта массива
-------------
a_a_byte[i,w]:=a_byte[i+5],a_byte[i+4] --компилятор ругается,а я не знаю как правильно..
Добрый день.
Отвечая на конкретный вопрос - проще всего добавить в проект библиотеку CAA Memory и сделать так:
MEM.MemMove(ADR(a_byte), ADR(a_a_byte), SIZEOF(a_a_byte) );
Но если "по нестандартному протоколу приходит(буфер) массив байт", то можно сразу разместить эти байты в "массиве типа INT" без использования каких-то промежуточных двумерных и одномерных байтовых массивов.
не понимаю, как собрать из байт int без промежуточных вариантов. Я сделал объединение, чтоб указывать объединение.массивбайт[3]:=байт_буфера[4]; объединение.массивбайт[4]:=байт_буфера[3];
Евгений Кислов
22.06.2022, 11:00
не понимаю, как собрать из байт int без промежуточных вариантов. Я сделал объединение, чтоб указывать объединение.массивбайт[3]:=байт_буфера[4]; объединение.массивбайт[4]:=байт_буфера[3];
Покажите скриншотом фрагмент кода, в котором у вас "по нестандартному протоколу приходит(буфер) массив байт".
А лучше - вырежите этот фрагмент и выложите в виде небольшого демонстрационного проекта.
Zerling
BitConverter.ToInt(массив байт, позиция). более правильнее посмотрите в справке. возможно предварительно надо будет переставлять байты. в зависимости в куда, функция возьмет требуемое количество байт с указанной позиции.
ой, тут по ПЛК, извиняюсь :)
Код пока не написан, только разбираюсь, что к чему.
Принимаю посылку через CAA COM.Read / OCL.UNM_SerialRequest, дальше - фб в котором отделяю и собираю адрес и значение переменной(сейчас использую одну, а потом нужно будет с десяток). Собственно, поэтому и использовал юнион - не знаю других способов собрать из двух байт тип инт.
Евгений Кислов
23.06.2022, 07:36
CAA COM.Read / OCL.UNM_SerialRequest возращают считанные данные по указателю - то есть можно передать на входы pBuffer / pResponse адрес чего угодно - например, сразу массива INT'ов.
Я так изначально делал, увидел кашу внутри и понял, что нужно менять порядок байтов. Сейчас собрался использовать массив из объединения.
Наверное, просто нужно написать фб, заменяющий значения в массиве, а его отправлять в массив INT
FUNCTION_BLOCK buff2int
VAR_INPUT
Pt_of_buff: POINTER TO ARRAY [1..255] OF BYTE;//
Pt_of_int: POINTER TO ARRAY [1..125] OF INT;//
END_VAR
VAR_INPUT
x_START: BOOL;// Старт пересборки буфера
END_VAR
VAR
i: byte;// шаг FOR/ номер ячейки буфера байт
m: BYTE;// Номер ячейки выходного массива
dut_var: W2ab;// объединение, массив 2 байта + инт
END_VAR
IF x_START THEN i := 0; END_IF
FOR i := 1 TO 20 DO ///20 условно, нужно смотреть или 3 или 7 ячейку для определения размера пакета
m:=i/2; // номер ячейки конечного массива
IF i.0 THEN //смотрим бит. тру значит число нечетное
// присваиваем значение из нечетной ячейки массива в [0] подъячейку объединения
MEM.MemMove(ADR(Pt_of_buff^[i]), ADR(dut_var.ab_digit[0]), SIZEOF(Pt_of_buff^[i]) );
ELSE
//присваиваем значение из четной ячейки массива в [1] подъячейку объединения
MEM.MemMove(ADR(Pt_of_buff^[i]), ADR(dut_var.ab_digit[1]), SIZEOF(Pt_of_buff^[i]) );
//по идее - ИНТ число уже сформировано, его можно записать в массив инт
MEM.MemMove(ADR(dut_var), ADR(Pt_of_int^[m]), SIZEOF(dut_var) );
END_IF END_FOR
получилось как-то так...
Powered by vBulletin® Version 4.2.3 Copyright © 2024 vBulletin Solutions, Inc. All rights reserved. Перевод: zCarot