Страница 3 из 6 ПерваяПервая 12345 ... ПоследняяПоследняя
Показано с 21 по 30 из 54

Тема: SysLibCom

  1. #21

    По умолчанию

    ВладОвен Мне Евгений Кислов помогал с подобным примером.
    Судя по этому примеру (и реальной жизни) такой принцип работы - норма (а я тогда как глупый как раз и думал, что все мои байты придут за один раз, и из-за мой код не хотел работать).
    В примере Евгения Кислова был такой алгоритм-принцип: сколько байт получили - столько и склеиваем в один общий массив байт, пока не наберём нужную длину посылки.
    После этого посылка идёт на обработку (проверка корректности и прочего).
    Если посылка верная - то что-то с ней делаем.
    Если ошибочная (или в течение таймаута не пришло заданное число байт) - обнуляем буфер, счётчик принятых байт, и начинаем всё сначала.

    Добавил: если там длина неизвестна - то так по байтам и клеить и парсить на лету (искать заголовок или какую-то инфу, которая покажет о том, что началась новая посылка данных). Скажем, так: приняли байт - запустили таймер TOF. Если были байты, пока он ещё считает - то значит это наша посылка. А если байтов не было - то посылка кончилась.
    Последний раз редактировалось Cs-Cs; 26.08.2022 в 19:01.
    Пишите код так, как будто сопровождать его будет склонный к насилию психопат, который знает, где вы живёте. © Steve McConnell
    Мой рабочий блог со статьями про щиты и автоматику ОВЕН - Cs-Cs.Net | Почта: Info@Cs-Cs.Net

  2. #22

    По умолчанию

    Привет.
    Решил эту задачу. Пока работает нормально.
    Я просто каждый раз после полученного пакета N1 (длинна не равна 0) сразу же принимаю второй пакет и если его длинна N2 не равна 0 , то я их склеиваю:

    Код:
    CASE bStep OF
        01: ...
        02: // Ожидаем пакет (N1)
              myComRead(xExecute := TRUE, hcom := hCom, pBuffer := ADR(arrBufferN1), szBuffer := 255, udiTimeOut := 0);
              IF myComRead.xDone THEN
                  bStep := 3;
              END_IF
        03: // Проверяем длину принятого пакета (N1)
              IF myComRead.szSize = 0 THEN // Нулевая длина
                  myComRead(xExecute := FALSE);
                  bStep := 2; // Повторно ожидаем пакет (N1)
                  END_IF
              ELSE
                  udiSizeN1 := myComRead.szSize; // Длинна пакета (N1) была не нулевой
                  myComRead(xExecute := FALSE);
                  bStep := 04;
              END_IF
        04: // Принимаем пакет (N2)
              myComRead(xExecute := TRUE, hcom := hCom, pBuffer := ADR(arrBufferN2), szBuffer := 255, udiTimeOut := 0);
              IF myComRead.xDone THEN
                  bStep := 5;
              END_IF
        06: // Проверяем длину принятого пакета (N2)
              IF myComRead.szSize <> 0 THEN // Длина не нулевая. Значит пакет был разбил на два отдельных. Склеиваем их.
                  udiSizeN2 := myComRead.szSize;
                  MEM.MemMove(ADR(arrBufferN2), ADR(arrBufferN1) + udiSizeN1, UDINT_TO_UINT(udiSizeN2));
              END_IF
              myComRead(xExecute := FALSE);
                  bStep := 5;
        05: ...
    END_CASE
    Последний раз редактировалось ВладОвен; 29.08.2022 в 11:24.

  3. #23

    По умолчанию

    ВладОвен Приятно посмотреть на код: везде комментарии и, если со стороны читать, то всё понятно. Я такое люблю.
    Ты не занимаешься уходом от магических чисел (это программистский термин)? Не хочу навязывать, но я все шаги именую через константы, то есть:
    Код:
    VAR_CONSTANT
        wStep_Wait : WORD := 0;
        wStep_Recieve : WORD := 1;
        wStep_Process : WORD := 2;
    ...
    END_VAR
    Так код и Case выглядят лучше, чем цифирки: с цифирками легко запутаться, когда добавляешь или удаляешь шаги.

    А ещё хотел спросить: у тебя в коде есть защита от ухода за границы буфера?
    Вот в этом месте
    Код:
    ADR(arrBufferN1) + udiSizeN1
    у тебя есть защита от того, чтобы этот адрес не ушёл за границы длины arrBufferN1?
    Про такие вещи надо думать, иначе потом они могут вызывать сбой программы.
    Пишите код так, как будто сопровождать его будет склонный к насилию психопат, который знает, где вы живёте. © Steve McConnell
    Мой рабочий блог со статьями про щиты и автоматику ОВЕН - Cs-Cs.Net | Почта: Info@Cs-Cs.Net

  4. #24

    По умолчанию

    Цитата Сообщение от Cs-Cs Посмотреть сообщение
    ВладОвен Приятно посмотреть на код: везде комментарии и, если со стороны читать, то всё понятно. Я такое люблю.
    Ты не занимаешься уходом от магических чисел (это программистский термин)? Не хочу навязывать, но я все шаги именую через константы, то есть:
    Код:
    VAR_CONSTANT
        wStep_Wait : WORD := 0;
        wStep_Recieve : WORD := 1;
        wStep_Process : WORD := 2;
    ...
    END_VAR
    Так код и Case выглядят лучше, чем цифирки: с цифирками легко запутаться, когда добавляешь или удаляешь шаги.
    Ещё удобно использовать перечисления (создать пользовательский тип данных) например:
    Код:
    TYPE enStateMotor : (
    	gc_iMotorStopped	 :=	0	, 
    	gc_iMotorStopping	 :=	1	, 
    	gc_iMotorBlocked	 :=	2	, 
    	gc_iMotorErrStart	 :=	3	, 
    	gc_iMotorWork	 :=	4	,
    	gc_iMotorStarting	 :=	5	,
    	gc_iMotorNoFeedback	 :=	6	
    );
    END_TYPE
    При этом с типом enStateMotor можно работать как с INT

  5. #25

    По умолчанию

    1exan Ага, я про перечисления знаю, но не хочу их использовать, так как перечисления внутри FB не объявишь, а у меня чаще всего автоматы состояний находятся и работают в FB. Мне хочется, чтобы FB был максимально самодостаточен и при копировании его по другим проектам не надо было ещё и DUT тащить.
    Поэтому внутри FB мне удобнее константы сделать.
    Если я не прав и внутри FB можно перечисление объявить - прошу меня поправить.
    Пишите код так, как будто сопровождать его будет склонный к насилию психопат, который знает, где вы живёте. © Steve McConnell
    Мой рабочий блог со статьями про щиты и автоматику ОВЕН - Cs-Cs.Net | Почта: Info@Cs-Cs.Net

  6. #26

  7. #27

    По умолчанию

    Цитата Сообщение от Cs-Cs Посмотреть сообщение
    1exan Ага, я про перечисления знаю, но не хочу их использовать, так как перечисления внутри FB не объявишь, а у меня чаще всего автоматы состояний находятся и работают в FB. Мне хочется, чтобы FB был максимально самодостаточен и при копировании его по другим проектам не надо было ещё и DUT тащить.
    Поэтому внутри FB мне удобнее константы сделать.
    Если я не прав и внутри FB можно перечисление объявить - прошу меня поправить.
    Можно, это же получается такой-же тип данных как BOOL, WORD - можно использовать и внутри блоков.
    Но тут надо не забывать если переносишь блок в другую программу, то и перечисление, используемое внутри тоже надо переносить. (если через импорт-экспорт надо выделить и блок и свой тип данных при экспорте).

    UPD:
    Можно - это я конечно имел в виду использование, а не объявление перечисления. Про фичу не знал.

    Перечисления удобны, если переменная состояния FB используется и снаружи FB.
    Последний раз редактировалось 1exan; 30.08.2022 в 08:26.

  8. #28

    По умолчанию

    1exan Вот, сначала пишем, потом читаем =) Я говорил о FB, так как снаружи это наоборот - не должно быть доступно.

    Евгений Кислов О! СПАСИБО!
    Хм... как бы уже придумать то, как этот FAQ распечатать со всех страниц сразу в PDF. Там сведений куча, а не все упомнишь!
    Сделал пока себе скриншот ответа!
    Пишите код так, как будто сопровождать его будет склонный к насилию психопат, который знает, где вы живёте. © Steve McConnell
    Мой рабочий блог со статьями про щиты и автоматику ОВЕН - Cs-Cs.Net | Почта: Info@Cs-Cs.Net

  9. #29

    По умолчанию

    Цитата Сообщение от Cs-Cs Посмотреть сообщение
    ВладОвен, ... Ты не занимаешься уходом от магических чисел (это программистский термин)? Не хочу навязывать, но я все шаги именую через константы ...
    Да. Этот способ тоже хорош. Но в этом проекте я решил пока от этого отказаться.
    Потому что последовательность очень длинная - на 100 шагов. Я просто боюсь, что потом запутаюсь в последовательности действий.
    Всё таки: числа дают последовательность перечисления, а слова - нет.

    Т.е. мы всегда знаем, что после шага 56 идет шаг 57, а потом и шаг 58.
    И наоборот, если со словами: после startZeroOperation идет waitCountOffset? Или waitCoeffView? Или, может быть, waitJeater? А, вспомнил! Потом идет goStableFlow! (но это не точно...).
    Но с числами есть недостаток: если понадобится вставить доп.промежуточный шаг в будущем, то придется сдвигать все числа вручную. И это неудобно.

    Наверное, оптимально делать всё же перечисление, но такого формата:
    10_startZeroOperation,
    20_waitCountOffset,
    30_waitCoeffView,
    40_waitJeater,
    50_goStableFlow.
    В этом случае и понятна последовательность шагов (за счет чисел), и смысл шага (за счет слов), и вставить доп.промежуточный шаг можно за счет предварительного пропуска чисел (например, 35_smokeDocsOwen).
    Последний раз редактировалось ВладОвен; 30.08.2022 в 10:50.

  10. #30

    По умолчанию

    Цитата Сообщение от ВладОвен Посмотреть сообщение
    Да. Этот способ тоже хорош. Но в этом проекте я решил пока от этого отказаться.
    Потому, что последовательность очень длинная - на 100 шагов. Я просто боюсь, что потом запутаюсь в последовательности действий.
    Всё таки: числа дают последовательность перечисления, а слова - нет.

    Т.е. мы всегда знаем, что после шага 56 идет шаг 57, а потом и шаг 58.
    И наоборот, если со словами: после startZeroOperation идет waitCountOffset? Или waitCoeffView? Или, может быть, waitJeater? А, вспомнил! Потом идет goStableFlow! (но это не точно...).
    Но с числами есть недостаток: если понадобится вставить доп.промежуточный шаг в будущем, то придется сдвигать все числа вручную. И это неудобно.

    Наверное, оптимально делать всё же перечисление, но такого формата:
    10_startZeroOperation,
    20_waitCountOffset,
    30_waitCoeffView,
    40_waitJeater,
    50_goStableFlow.
    В этом случае и понятна последовательность шагов (за счет чисел), и смысл шага (за счет слов), и вставить доп.промежуточный шаг можно за счет предварительного пропуска чисел (например, 35_waitSmokeDocsOwen).
    Я конечно не знаю как у вас организована программа, но я в таких случаях делаю так:
    Если мне надо добавить шаг, я просто вставляю его в нужное место перечисления и перенумеровываю значения заново (в екселе - делается за 1 сек если разделители - табуляция):
    Например:
    Код:
    Было
    
    TYPE enStateMotor : (
    	gc_iMotorStopped	 :=	0	, 
    	gc_iMotorStopping	 :=	1	, 
    	gc_iMotorBlocked	 :=	2	, 
    	gc_iMotorErrStart	 :=	3	, 
    	gc_iMotorWork	 :=	4	,
    	gc_iMotorStarting	 :=	5	,
    	gc_iMotorNoFeedback	 :=	6	
    );
    END_TYPE
    
    Стало:
    
    TYPE enStateMotor : (
    	gc_iMotorStopped	 :=	0	,
    	gc_iMotorStopping	 :=	1	,
    	gc_iMotorBlocked	 :=	2	,
    
    	gc_iMotor_NEW_STATE	 :=	3	,
    
    	gc_iMotorErrStart	 :=	4	,
    	gc_iMotorWork	 :=	5	,
    	gc_iMotorStarting	 :=	6	,
    	gc_iMotorNoFeedback	 :=	7	
    
    );
    END_TYPE
    При этом оператор
    Код:
    CASE State OF
    gc_iMotorStopped..gc_iMotorWork, gc_iMotorNoFeedback:
    	...
    и конструкции типа
    Код:
    State > gc_iMotorStopped AND State < gc_iMotorNoFeedback
    ну и т.д. не перестают работать

Страница 3 из 6 ПерваяПервая 12345 ... ПоследняяПоследняя

Похожие темы

  1. SysLibCom
    от Антон12345 в разделе ПЛК1хх
    Ответов: 36
    Последнее сообщение: 21.11.2013, 15:44
  2. Syslibcom
    от Назаров Александр в разделе ПЛК1хх
    Ответов: 1
    Последнее сообщение: 28.04.2010, 17:34
  3. SysLibCom
    от demon в разделе ПЛК1хх
    Ответов: 1
    Последнее сообщение: 20.03.2009, 13:08
  4. ПЛК 150 и SysLibCom.lib.
    от Анатолий в разделе ПЛК1хх
    Ответов: 2
    Последнее сообщение: 13.12.2008, 13:48
  5. SysLibCom.lib
    от Nekit в разделе ПЛК1хх
    Ответов: 0
    Последнее сообщение: 05.05.2007, 11:14

Ваши права

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