Страница 1 из 2 12 ПоследняяПоследняя
Показано с 1 по 10 из 16

Тема: Упаковка переменных BOOL, INT, REAL в Modbus String

  1. #1

    По умолчанию Упаковка переменных BOOL, INT, REAL в Modbus String

    Здравствуйте.

    Возможно данный вопрос уже поднимался на форме, но я что-то ни как не могу найти подходящий ответ.

    Задача такая:
    К ПЛК110 подключен 3G-роутер посредством которого должна осуществляется связь по Modbus-TCP с удаленным компьютером. На компьютере установлена самописная программа, которая работает в режиме Modbus-slave.
    К программе планируется подключить с несколько десятков устройств. Для того чтобы разгрузить программу и канал 3G хотелось бы сделать так, чтоб контроллеры писали в Modbus-slave групповыми запросами.
    Групповой запрос в ПЛК110 в Universal Modbus Device реализуется через переменные STRING.
    Вопрос следующий:
    Как упаковать переменные в STRING?

    Пытался решить следующим способом:

    --------------------------------------------------------------
    VAR

    str1: STRING[8];
    str2: STRING[44];
    str3: STRING[36];

    ptr1: POINTER TO ARRAY[0..7] OF BYTE;
    ptr2: POINTER TO ARRAY[0..21] OF INT;
    ptr3: POINTER TO ARRAY[0..17] OF INT;

    END_VAR

    ptr1:=ADR(str1);
    ptr2:=ADR(str2);
    ptr3:=ADR(str3);

    ptr1^[0].0 := parametr11;
    ptr1^[0].1 := parametr12;
    ptr1^[0].2 := parametr13;
    ptr1^[0].3 := parametr14;
    ptr1^[0].4 := parametr15;
    ptr1^[0].5 := parametr16;
    ptr1^[0].6 := parametr17;
    ptr1^[0].7 := parametr18;
    и так далее для строки str1
    (parametr11...parametr18 - переменные типа BOOL)

    ptr2^[0] := parametr21;
    ptr2^[1] := parametr22;
    и так далее для строки str2
    (parametr21, parametr22 - переменные типа INT)

    ptr3^[0] := REAL_TO_INT(parametr31 * 100);
    ptr3^[1] := REAL_TO_INT(parametr32 * 100);
    и так далее для строки str3
    (paremetr31,parametr32 - переменные типа REAL)

    modbus_group1 := str1;
    modbus_group2 := str2;
    modbus_group3 := str3;

    (modbus_group1,modbus_group2,modbus_group3- переменные типа STRING Universal Modbus Device)
    --------------------------------------------------------------

    После заливки такого кода программа зависает, через некоторое время перезагружается контроллер (наверно watchdog срабатывает)

    Что не так в коде? И может какое другое решение есть?
    Подскажите пожалуйста.

  2. #2
    Пользователь
    Регистрация
    13.10.2011
    Адрес
    Златоуст
    Сообщений
    1,021

    По умолчанию

    Это происходит когда не соблюдается выравнивание (доступ к REAL по некратному 4 адресу или к WORD по некратному 2 адресу, например), либо от неудачного вылета за границы массива. Скорее всего, первое, потому что строки попадают на «кривые» адреса, которые вы потом разыменовываете. Можете попробовать SysLibMem — там есть SysMemCpy.

    Код:
    SysMemSet(ADR(modbus_group1), PACK(parameter11, parameter12...), 1);
    SysMemCpy(ADR(modbus_group2) + 0, ADR(parameter21), SIZEOF(parameter21));
    SysMemCpy(ADR(modbus_group2) + 2, ADR(parameter22), SIZEOF(parameter22));
    tmp := REAL_TO_INT(parameter31 * 100);
    SysMemCpy(ADR(modbus_group3) + 0, ADR(tmp), SIZEOF(tmp));
    tmp := REAL_TO_INT(parameter32 * 100);
    SysMemCpy(ADR(modbus_group3) + 2, ADR(tmp), SIZEOF(tmp));
    Последний раз редактировалось Yegor; 16.04.2015 в 11:08.

  3. #3

    По умолчанию

    сделайте ptr1: POINTER TO BYTE;
    ptr2: POINTER TO array [0..1] of BYTE;
    далее в коде
    ptr1:=ADR(str1);
    все бул переменные переприсваивайте в переменную байт или ворд. ( т.к. 8 бит то лучше в байт)
    ptr1^:=переменная типа байт;
    ptr1:=ptr1+1; перешли к следующему символу строки.
    тут пошли данные больше одного байта
    ptr2:=ADR(инт_переменная);
    ptr1^:=ptr2^[0];
    ptr1:=ptr1+1; перешли к следующему символу строки.
    ptr1^:=ptr2^[1];
    ptr1:=ptr1+1; перешли к следующему символу строки.

    и т.д.

  4. #4

    По умолчанию

    Какие-то чудеса с указателями.

    Код тестовой программы следующий:

    VAR

    i: INT;
    j: INT;

    str1: STRING[8];

    p1: POINTER TO BYTE;
    p2: POINTER TO ARRAY [0..1] OF BYTE;

    END_VAR

    p1 := ADR(str1);
    p2 := ADR( i);
    i := 124;
    p1^ := p2^[0];
    p1 := p1 + 1;
    p1^ := p2^[1];
    p1 := p1 + 1;

    p1 := ADR(str1);
    p2 := ADR(j);
    p2^[0] := p1^;
    p1 := p1 + 1;
    p2^[1] := p1^;

    Запускаю программу на контроллере и вижу:
    i = 124
    j = 124

    Далее изменяю имена переменных в редакторе p1 -> ptr1, p2 -> ptr2
    Запускаю программу на контроллере и вижу:
    i = -28924
    j = -18564

    Что за чудеса не понятно. Прошу помощи и разъяснений.

  5. #5
    Пользователь
    Регистрация
    19.11.2011
    Адрес
    г. Белгород
    Сообщений
    357

    По умолчанию

    Тип INT занимает 2 байта, поэтому учитываем это, и там где надо пишем p1:=p1+2

  6. #6

    По умолчанию

    Цитата Сообщение от amn Посмотреть сообщение
    Тип INT занимает 2 байта, поэтому учитываем это, и там где надо пишем p1:=p1+2
    p1^ := p2^[0];
    p1 := p1 + 1;
    p1^ := p2^[1];
    p1 := p1 + 1;

    На каждую переменную INT сдвиг осуществляется на два байта,
    Вопрос не в этом. А в том что имена переменных влияют на результат, что вообще не должно быть.
    Меняю имена переменных в редакторе p1 -> ptr1, p2 -> ptr2 (нажимаю Ctrl+H, меняю ptr на p) результат программы разный, вот в чем вопрос. Причем делаю Reset (Original) перед загрузкой каждого варианта программы.
    Последний раз редактировалось ПРОЕКТ-П; 19.04.2015 в 13:11.

  7. #7
    Пользователь
    Регистрация
    23.09.2008
    Адрес
    Центророссийск
    Сообщений
    2,250

    По умолчанию

    + "проект/очистить все" перед каждой загрузкой. Если не поможет - ищите ошибку в 22й строке
    С указателями всегда и везде - нормуль. Только руки портят. И вообще - какой-то сложный способ упаковки.

  8. #8
    Пользователь
    Регистрация
    19.11.2011
    Адрес
    г. Белгород
    Сообщений
    357

    По умолчанию

    Вот, что я имел в виду:

    Код HTML:
    VAR
    	i: INT:=257;
    	j: INT;
    	k: REAL:=12.5;
    	m: REAL;
    	b: BYTE:=120;
    	a: BYTE;
    	str1: STRING;
    
    	ptr1: POINTER TO BYTE;
    	ptr2: POINTER TO INT;
    	ptr3: POINTER TO REAL;
    END_VAR
    
    --------------------
    
    (*записываем в строку переменные разных типов*)
    ptr2 := ADR(str1);	(*ставим указатель на нашу стоку*)
    ptr2^ := i;	(*пишем переменную типа INT*)
    ptr3:=ptr2+2;	(*смещаем указатель на 2 байта*)
    
    ptr3^ := k;	(*пишем переменную типа REAL*)
    ptr1:=ptr3+4;	(*смещаем указатель на 4 байта*)
    
    ptr1^ := b;		(*пишем переменную типа BYTE*)
    
    (*читаем из строки переменные разных типов*)
    ptr2 := ADR(str1);	(*ставим указатель на нашу стоку*)
    j:=ptr2^;			(*читаем переменную типа INT*)
    ptr3 := ptr2 + 2;	(*смещаем указатель на 2 байта*)
    
    m:=ptr3^;			(*читаем переменную типа REAL*)
    ptr1:=ptr3+4;	(*смещаем указатель на 4 байта*)
    
    a:=ptr1^;		(*читаем переменную типа BYTE*)

  9. #9

    По умолчанию

    (*читаем из строки переменные разных типов*)
    ptr2 := ADR(str1); (*ставим указатель на нашу стоку*)
    j:=ptr2^; (*читаем переменную типа INT*)
    ptr3 := ptr2 + 2; (*смещаем указатель на 2 байта*)

    j := ptr2^;
    вот здесь "собака" - если str1 начинается с четного адреса - будет работать, если с нечетного - ватчдог! т.е. как фишка ляжет -50 на 50 ))) поработал код, добавили переменную и абзац! Егор правду глаголет! проверил сам.

  10. #10

    По умолчанию

    Цитата Сообщение от Дмитрий Артюховский Посмотреть сообщение
    (*читаем из строки переменные разных типов*)
    ptr2 := ADR(str1); (*ставим указатель на нашу стоку*)
    j:=ptr2^; (*читаем переменную типа INT*)
    ptr3 := ptr2 + 2; (*смещаем указатель на 2 байта*)

    j := ptr2^;
    вот здесь "собака" - если str1 начинается с четного адреса - будет работать, если с нечетного - ватчдог! т.е. как фишка ляжет -50 на 50 ))) поработал код, добавили переменную и абзац! Егор правду глаголет! проверил сам.
    У меня данная проблема как раз по этой причины и возникла (см. первое сообщение в теме).
    Поэтому в дальнейшем я использую решение предложенное Трофимовым Артемом - упаковываю и читаю по байтно, а не целыми INT или REAL.

Страница 1 из 2 12 ПоследняяПоследняя

Похожие темы

  1. Ответов: 20
    Последнее сообщение: 03.05.2015, 16:01
  2. Упаковка переменных ПЛК
    от ramilgim в разделе ПЛК1хх
    Ответов: 3
    Последнее сообщение: 28.04.2013, 22:06
  3. Переменная REAL ведет себя как Int при вычислениях
    от lomtik в разделе Сетевые технологии
    Ответов: 9
    Последнее сообщение: 16.01.2013, 12:50
  4. преобразование Real>string кракозябры
    от K580BB55A в разделе ПЛК1хх
    Ответов: 1
    Последнее сообщение: 09.11.2010, 17:07

Ваши права

  • Вы не можете создавать новые темы
  • Вы не можете отвечать в темах
  • Вы не можете прикреплять вложения
  • Вы не можете редактировать свои сообщения
  •