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

Тема: _REAL:=_POINTER_TO_REAL^ НЕ РАБОТАЕТ?!

  1. #1

    По умолчанию _REAL:=_POINTER_TO_REAL^ НЕ РАБОТАЕТ?!

    Здравствуйте.
    Столкнулся с непонятным явлением. Исходный текст:

    VAR_OUTPUT
    Rate:REAL; (* рабочий расход *)
    NormRate:REAL; (* нормализованный расход *)
    Pressure:REAL; (* давление *)
    Temperature:REAL; (* температура *)
    TimeError:WORD; (* нерабочее время *)
    Acc:BYTE; (* признак ошибки по питанию *)
    END_VAR

    VAR
    Response:STRING[1024]; (* буфер для приёма данных, считанных с порта *)
    pnt_Data_Byte:POINTER TO BYTE;
    pnt_Data_Word:POINTER TO WORD;
    pnt_Data_Real:POINTER TO REAL;
    END_VAR


    (************************************************* *********************************)
    (************************************************* *********************************)
    (* если добрались до сюда, то извлекаем данные из ответа *)


    pnt_Data_Real:= ADR(Response)+15;
    (*!!!*) Rate:= pnt_Data_Real^;

    pnt_Data_Real:= pnt_Data_Real+4;
    NormRate:= pnt_Data_Real^;


    pnt_Data_Real:= pnt_Data_Real+4;
    Pressure:= pnt_Data_Real^;

    pnt_Data_Real:= pnt_Data_Real+4;
    Temperature:= pnt_Data_Real^;

    pnt_Data_Word:= ADR(Response)+31;
    TimeError:= pnt_Data_Word^;

    pnt_Data_Byte:= ADR(Response)+33;
    Acc:=pnt_Data_Byte^;

    Когда программа выполняет строку, помеченную восклицательными знаками, контроллер пикает и перезагружается, а CoDeSys выбрасывает окно обрыва коммуникации. Причем, все четыре байта, на которые в этот момент указывает pnt_Data_Real равны нулю, это я проверил.

    В чём может быть дело?

    Проект на текущий момент.
    Опрос Гобой-1 ПЛК 100 Р.rar
    Последний раз редактировалось Serj_N; 06.08.2008 в 11:29.

  2. #2

    По умолчанию

    Возникают большие сомнения по поводу того, как вообще должен себя вести компилятор процессора типа ARM, при попытке размещения REAL на произвольные байтовые адреса (десериализация данных с игнорированием правил выравнивания)? Скорее всего, будет непредсказуемый результат или повисание. Если система исполнения ПЛК действительно ловит такую ситуацию и перезапускается, то большой респект и уважение разработчикам Овен!

    Я бы объявил нормальную переменную типа REAL, взял бы на нее указатель и уже туда копировал бы данные из строки побайтно. Еще лучше оформить такой преобразователь в виде функции с проверкой допустимости формата данных.

  3. #3

    По умолчанию Игорю Петрову

    По сути, я попал ногой в капкан, о котором в документации туманно сообщено, что он есть, но не больше. Ошибка нашлась часа через два после того, как разместил свой вопрос, но не стал сразу писать решение. Интересно было посмотреть, кто что скажет. Проблемка ведь не тривиальная. А на счёт такого варианта:
    "Я бы объявил нормальную переменную типа REAL, взял бы на нее указатель и уже туда копировал бы данные из строки побайтно."
    то я предпочёл другой способ
    "SysMemCpy(ADR (Rate), ADR(Response)+15, 4);"
    В четыре раза короче и, по-моему, нагляднее.

    "Если система исполнения ПЛК действительно ловит такую ситуацию и перезапускается, то большой респект и уважение разработчикам Овен!"

    Я не сомневаюсь, что если возникает фатальная ошибка, то лучше всего аварийно остановить работу контроллера. Но зачем его перезагружать? Я так и не нашёл способа получить информацию о причине остановки и рестарта от самого контроллера. Может, плохо ещё систему знаю, а может, и нет такой возможности вообще. Контроллер вылетает, перезагружается и стартует заново. Почему произошла остановка? В какой точке программы? Никакой информации. Как хочешь, так и ищи...

    "Еще лучше оформить такой преобразователь в виде функции с проверкой допустимости формата данных."

    А не могли бы Вы подбросить прототип такой функции? Может уже сталкивались и есть наработка?

    P.S. Краткое резюме: Работа с указателями - как пересечение болота. Когда есть карта проверенных тропинок и известных опасных участков - пройдёшь без особых приключений. Хорошо бы в новых версиях документации посвятить отдельный параграф особенностям использования указателей на данной платформе.

  4. #4

    По умолчанию

    1. Указатель - как атомная энергия, может дать тепло и свет, но может и жахнуть
    2. Вы наступили на грабли выравнивания. Побайтовое копирование - единственный выход. Но по настоящему верным решением будет создать структуру данных, содержащихся в строке, передавать начало строки в указатель на эту структуру и работать с её полями. Компилятор сам учтёт выравнивания и проблем не возникнет.
    Определение структуры на языке C также можно получить при необходимости, создав внешнюю (external) библиотеку с этой структурой. При записи создается .h файл со всеми прототипами функций и структурами данных.
    3. По ошибке невыровненного доступа к памяти восстановление невозможно, поэтому единственным выходом является перезагрузка.

  5. #5

    По умолчанию Владиславу Филоненко

    Вы наступили на грабли выравнивания.
    Во-во, ещё бы эти грабли были подробнее описаны в мануале (опять я за старое, да )
    Побайтовое копирование - единственный выход.
    А вариант с SysMemCpy хуже? Может тут тоже есть что-то, о чём ещё предстоит узнать?
    На счёт структуры - надо подумать.
    По ошибке невыровненного доступа к памяти восстановление невозможно, поэтому единственным выходом является перезагрузка.
    А разве я говорил о восстановлении? По моему скромному мнению, в случае фатальной ошибки контроллер должен:
    1. Остановить выполнение программы.
    2. Перевести выходы в безопасные состояния.
    3. Записать максимум информации об ошибке в энергонезависимую память.
    4. Сохранить возможность коммуникаций со средой программирования.
    5. Ни в коем случае не пытаться самостоятельно стартовать снова (и сделать это только по нажатию кнопки "Сброс").
    6. Стоять и ждать программиста.

    Было бы хорошо, если бы Вы добавили контроллеру операцию автоматической записи информации об ошибке (при её возникновении) в энергонезависимую память (минимально - тип ошибки и программый блок, где она произошла (в идеале - номер строки)). И возможность считать эту инфу через PLC-Browser, добавив соответствующую команду (типа GetLastError). Естественно, эта информация не должна теряться при перезагрузке.

  6. #6

    По умолчанию

    Всё это хорошо и правильно. НО!
    Ошибка происходит на аппаратном уровне и остановить чего либо уже нельзя.

  7. #7

    По умолчанию

    Игорь Петров
    Если система исполнения ПЛК действительно ловит такую ситуацию и перезапускается, то большой респект и уважение разработчикам Овен!
    Филоненко Владислав
    Ошибка происходит на аппаратном уровне и остановить чего либо уже нельзя.



    Получается, что ошибку с указателем обнаруживает сам процессор и сам себе делает резет? И никаких прерываний, ничего, куда можно всунуть перед резетом процедурку записи инфы об ошибке? По идее, в этом случае он должен предоставить какой-то регистр, где сохраняет код причины рестарта?...

  8. #8

    По умолчанию

    При перезагрузке индицируется коды последней причины перезагрузки (на гипертерминале) и зап. соотв. информация в лог-файлы

  9. #9

    По умолчанию

    А где эти логи лежат?

  10. #10

    По умолчанию

    На внутреннем диске ПЛК. log.txt и debug.txt
    Команда filedir рулит.

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

Ваши права

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