Работа ModBus в проектах FLProg
Добавлено: 28 ноя 2019, 12:40
Как часто замечаю, иногда пользователи не до конца понимают как устроена работа обмена по модбас, и, соответственно, требуют не реализуемые задачи.
Слэйв модбас rtu. Slave ModBus RTU.
При создании кода для IDE FLProg перед первой платой вставляет дополнительные, необходимые для работы, переменные, функции.
Одной из них является функция, отвечающая за обмен по модбас. Выполняется она, как Вы догадались, один раз в цикле.
Сама по себе состоит из других, вложенных функций, отвечающих за разные задачи.
В примере - минимальный вариант - значение из регистра на выход ШИМ. Время цикла - минимальное.
Итак, вначале проверяется, есть ли что либо, а именно байты, в буфере serial( или Softserial - не принципиально).
1-й цикл. Если ответ пусто, 0, функция прерывается, программа выполняется дальше.
2-й цикл. Если есть, запоминается текущее количество доступных для считывания байт( в _modbusSlaveLastRec),
запоминается текущее время( в _modbusSlaveTime), функция прерывается, программа выполняется дальше.
3-й цикл. Если значение количества последних и сейчас доступных для считывания байт не совпадает, значит данные всё еще поступают в буфер serial.
Запоминается текущее количество доступных для считывания байт(_modbusSlaveLastRec),
запоминается текущее время(_modbusSlaveTime), функция прерывается, программа выполняется дальше.
N-й цикл. Значение количества доступных для считывания из буфера serial байт и старое значение одинаковы, то проверяем, сколько прошло времени,
между последним изменением, вдруг байт где-то заплутал. Если время ожидания получения байта ещё не вышло - прерываем функцию.
N+n цикл. Время вышло, больше байтов нет, начинаем обрабатывать полученное.
Замечу - время ожидания приёма байта зависит от скорости(раньше), у Автора сейчас составляем 5 мс....
обнуляем _modbusSlaveLastRec.
Загружаем все данные из буфера serial в буфер программы, попутно подсчитывая количество байт и следя за переполнением.
/*
Здесь у Автора нет защиты от переполнения буфера и получения нежданчиков:
если в моей библиотеке serial размер буфера больше стандартного, буфер модбаса переполнится,
выставится только флаг - bBuffOverflow, но данные продолжат записываться в ячейки, которые буферу не принадлежат...
Я в таких случаях просто вызываю read(), опустошая буфер serial. Легко чинится в коде перестановкой строк....
*/
Если количество полученных байт >= минимальной посылки, проверяем, нам ли она адресована. Если нет - функция прерывается, программа выполняется дальше.
Проверяем контрольную сумму, если не правильная - функция прерывается, программа выполняется дальше.
Далее, исходя из номера функции, делаем необходимые действия - записываем данные при необходимости и готовим ответ.
Передаём ответ мастеру.
Функция закончена, обмен проведён, программа выполняется дальше.
Как видно из моей мисанины, выполнения кода модбас при малом времени цикла занимает несколько циклов,
а при программе, напичканой выводами на дисплей по I2C и другими тяжело-временными блоками, минимум два.
И для общего понимания. Не спеша.ilusha писал(а): 24 ноя 2019, 01:04 Почему работает Очень медленно modbus?
Очень медленно.
Это так медленно, если я делаю
не правильно..
Синхронизация включена на 1 миллисекунду
Слэйв модбас rtu. Slave ModBus RTU.
При создании кода для IDE FLProg перед первой платой вставляет дополнительные, необходимые для работы, переменные, функции.
Одной из них является функция, отвечающая за обмен по модбас. Выполняется она, как Вы догадались, один раз в цикле.
Сама по себе состоит из других, вложенных функций, отвечающих за разные задачи.
В примере - минимальный вариант - значение из регистра на выход ШИМ. Время цикла - минимальное.
Итак, вначале проверяется, есть ли что либо, а именно байты, в буфере serial( или Softserial - не принципиально).
1-й цикл. Если ответ пусто, 0, функция прерывается, программа выполняется дальше.
2-й цикл. Если есть, запоминается текущее количество доступных для считывания байт( в _modbusSlaveLastRec),
запоминается текущее время( в _modbusSlaveTime), функция прерывается, программа выполняется дальше.
3-й цикл. Если значение количества последних и сейчас доступных для считывания байт не совпадает, значит данные всё еще поступают в буфер serial.
Запоминается текущее количество доступных для считывания байт(_modbusSlaveLastRec),
запоминается текущее время(_modbusSlaveTime), функция прерывается, программа выполняется дальше.
N-й цикл. Значение количества доступных для считывания из буфера serial байт и старое значение одинаковы, то проверяем, сколько прошло времени,
между последним изменением, вдруг байт где-то заплутал. Если время ожидания получения байта ещё не вышло - прерываем функцию.
N+n цикл. Время вышло, больше байтов нет, начинаем обрабатывать полученное.
Замечу - время ожидания приёма байта зависит от скорости(раньше), у Автора сейчас составляем 5 мс....
обнуляем _modbusSlaveLastRec.
Загружаем все данные из буфера serial в буфер программы, попутно подсчитывая количество байт и следя за переполнением.
/*
Здесь у Автора нет защиты от переполнения буфера и получения нежданчиков:
если в моей библиотеке serial размер буфера больше стандартного, буфер модбаса переполнится,
выставится только флаг - bBuffOverflow, но данные продолжат записываться в ячейки, которые буферу не принадлежат...
Я в таких случаях просто вызываю read(), опустошая буфер serial. Легко чинится в коде перестановкой строк....
*/
Если количество полученных байт >= минимальной посылки, проверяем, нам ли она адресована. Если нет - функция прерывается, программа выполняется дальше.
Проверяем контрольную сумму, если не правильная - функция прерывается, программа выполняется дальше.
Далее, исходя из номера функции, делаем необходимые действия - записываем данные при необходимости и готовим ответ.
Передаём ответ мастеру.
Функция закончена, обмен проведён, программа выполняется дальше.
Как видно из моей мисанины, выполнения кода модбас при малом времени цикла занимает несколько циклов,
а при программе, напичканой выводами на дисплей по I2C и другими тяжело-временными блоками, минимум два.