Ладно пора спать. Я наверно фигова объясняю
Вид для печати
Ладно пора спать. Я наверно фигова объясняю
Я в разных циклах в один буфер читаю куски большого блока последовательно укладывая их, ничего оттуда не беру до признака окончания. И ничего не теряюЦитата:
И это будет работать, потому что из буфера "заберут" все содержимое.
По протоколу ответ не может превышать 256 байт.
А если из буфера порта забрать меньше его содержимого, то происходит ПОТЕРЯ ДАННЫХ.
В modbus.lib сделано практически тоже самое.
У Вас теряется - см пост.19 ответ 1 (часть б)
Можно пример
См. исходник modbus.lib
Вдумайтесь
Я всегда недоедаю котлету. Я требую объяснить почему я голодный ?Цитата:
А если из буфера порта забрать меньше его содержимого, то происходит ПОТЕРЯ ДАННЫХ.
Валенок, пожалуйста приведи фрагмент кода чтения ответа, только с определениями переменных. Дался тебе ентот modbus.lib. Ты свой рабочий код покажи.
P.S. Вы в Овене работаете?
Просто я говорю " глючит " и выкладываю пример. Вы говорите все работает и примера не даете. А modbus.lib не в счет.
На форуме есть уже несколько тем с очень похожим содержанием, без ответа почему теряются байты.
Исходник не дам. Разве только пример с закрытой б-кой. Хотя примеры-выкладывал. В Овене не работаю - можете справится у них.
А что вы так против модбаса.либа - я вот его по косточкам разобрал, википедию почитал - и свой мастер сделал.
Я не против modbus.lib, прото мне сейчас не нужен. В проекте нужно сделать обмен с устройством по нестандартному протоколу. Modbus rtu использовал просто для примера. Если я сказал, что глючит обмен между ПЛК63 и шнайдеровским счетчиком, меня в техподдержке с ходу в сад послали. А так обмен между двумя овеновскими плк по modbus. Типа не отвертятся. Но ошибался. Кто-то заболел, контроллеров у них нет и т.д.
Очень кратко - тот протокол как выглядит ?
Какой протокол?
Я посылал запросы и ожидал ответов в формате modbus rtu
REQUEST : ARRAY [ 1..REQUEST_SIZE ] OF BYTE := 16#10, 16#04, 16#00, 16#00, 16#00, 16#04, 16#F2, 16#88;
16- адрес устройства
04 - код функции
00, 00 - адрес первого регистра
00,04 - кол-во регистров
crc - 88F2
Если под рукой нет программы для подсчета crc,
http://www.lammertbies.nl/comm/info/...lculation.html
счетчик я обсуждать не буду
1.Отправили, взвели таймер
2.Читаем.Что-то есть - перевзводим таймер. время вышло - выходим на проверку данных
PS
А счетчик есть и в modbus.lib
И я про тот, другой, протокол спрашивал
Паузы - в сад
шнайдеровский счетчик в сад. Здесь я его обсуждать не хочу. Не та тема.
Пойми из буфера порта читаю небольшими порциями. Да можно при чтении запросить макс. возможное для данного протокола количество байт из буфера. И проблема пропадет. НО почему теряются байты при чтении ответа из буфера частями. На ПЛК100 работает на ПЛК63 - глючит. А на еще каком-нибуть ПЛКxxx, будет другой глюк.
Меня не интересует, как можно сделать по другому. Я знаю как сделать. Меня интересует имено ентот глюк.
Вы попробуйте, если не влом конечно, и есть возможность заменить
Size := DWORD_TO_WORD(SysComRead(ComHandle, ADR(rBuf), SIZEOF(rBuf), 0));
на
Size := DWORD_TO_WORD(SysComRead(ComHandle, ADR(rBuf), SIZEOF(rBuf), 0));
if ( size > 0 ) then
size := size + DWORD_TO_WORD(SysComRead(ComHandle, ADR(rBuf[ 1 ]), SIZEOF(rBuf) - 1, 0));
end_if
когда читаете - знаете сколько прочитали. Ну за каким читать меньше или больше ?
PS
Все. Спокойной ночи.
Допустим в буфере появился "мусор" ( каким образом, даже думать не хочу ). Читаем 100 байт, первые 10 "мусор", а дальше идет верный ответ от устройства. Т.е. надо дочитать ответ. Читаем недостающие байты. И тут облом. Теряются байты.
Вот зачем
в место единицы видимо Size должны были написать
Блин, уже жалею, что ПЛК63 на объекте, и раньше, чем через пару недель туда не доберусь. Очень интересно было бы проверить теорию "шестого байта"...
А нет ограничений на то, что в одном цикле должна быть только одна команда SysComRead? Или это требование относилось к тому, что в одном цикле или SysComRead, или SysComWrite... Или я что-то путаю, и такого совсем нет...
Жалко, нет функции, которая сказала бы количество байт, доступных для чтения... Хотя всё равно не спасло бы - где гарантия, что между ней и чтением не изменится кол-во данных...
Разве SysComRead не возвращает количество доступных байтЦитата:
Жалко, нет функции, которая сказала бы количество байт, доступных для чтения... Хотя всё равно не спасло бы - где гарантия, что между ней и чтением не изменится кол-во данных...
В одном цикле SysComWrite и SysComRead теоретически можно. Но если посылается запрос устройству, который требует ответа, то ведь устройство должно принять запрос, обработать, послать ответ. Слишком длинный рабочий цикл получиться.
Я читать ответ частями и в одном цикле, и разносить по циклам. Результат тотже
Может кто-нибудь посмотрел примеры?
Обсуждение свелось к предложениям - "нафига ... ", " зачем ..."
Еще раз. Эти примеры не имеют ничего общего с моими проектами. Я их специально написал, чтобы показать проблему.
А нужно это затем, что если есть такой глюк, то его надо учитывать в алгоритме программ, чтобы потом "блох" не вылавливать.
смысл от этой строки, если до этого каждый цикл, переменной size будет присваиваться 0 либо 1. Друго дело если Вы накапливаете size, то и вычитать тогда нужно не 1 а size-прочитанных байт.Цитата:
size := size + DWORD_TO_WORD(SysComRead(ComHandle, ADR(rBuf[ 1 ]), SIZEOF(rBuf) - 1, 0));
Хотели услышать ответ, честно говорю не смотрел Ваш проект, вернусь домой попытаюсь открыть
Size := DWORD_TO_WORD(SysComRead(ComHandle, ADR(rBuf), 1, 0)); (* запрос на чтение одного байта *)
if ( size > 0 ) then (* если прочитали один байт, пробуем прочитать остальное *)
(* здесь size равно 1 *)
size := size + DWORD_TO_WORD(SysComRead(ComHandle, ADR(rBuf[ 1 ]), SIZEOF(rBuf) - 1, 0));
end_if
size - кол-во байт прочитанных из буфера порта
Это
заменить на этоКод:Size := DWORD_TO_WORD(SysComRead(ComHandle, ADR(rBuf), SIZEOF(rBuf), 0));
Код:Size := DWORD_TO_WORD(SysComRead(ComHandle, ADR(rBuf), SIZEOF(rBuf), 0));
if ( size > 0 ) then
size := size + DWORD_TO_WORD(SysComRead(ComHandle, ADR(rBuf[ 1 ]), SIZEOF(rBuf) - 1, 0));
end_if
опять ошибся
заменить на этоКод:Size := DWORD_TO_WORD(SysComRead(ComHandle, ADR(rBuf), SIZEOF(rBuf), 0));
Код:Size := DWORD_TO_WORD(SysComRead(ComHandle, ADR(rBuf), 1, 0));
if ( size > 0 ) then
size := size + DWORD_TO_WORD(SysComRead(ComHandle, ADR(rBuf[ 1 ]), SIZEOF(rBuf) - 1, 0));
end_if
По результатам выполнения оба куска кода равнозначны.
Это не для того, чтобы "лучше работало", а как " эксперимент ", раз уж мои примеры не смотрят
я понимаю, что Вы делите чтение на два этапа,сперва первый байт, затем пытаетесь записать оставшийся приемный буффер в массив rBuf начиная с индекс 1. У Вас после этого кода видимо Size еще где то используется для сравнения, сколько Вы всего приняли байт за два этапа? Для чего Вы накопление делаете. Судя по Вашим ответам разговор шел, что читать буффер Вы пытаетесь за несколько циклов, тогда суммирование уже смысла не имеет, так как с каждым новым циклом значение Size будет максимум равно 1
В чем суть эксперимента? Наверное когдана первом этапе пытаетесь прочитать 10 байт, а приходит 6, то у Вас не клеится второй этап или как?Цитата:
Size := DWORD_TO_WORD(SysComRead(ComHandle, ADR(rBuf), 10, 0));
if ( size > 0 ) then
size := size + DWORD_TO_WORD(SysComRead(ComHandle, ADR(rBuf[ 1 ]), SIZEOF(rBuf) - 1, 0));
end_if