Реализация протокола Modbus

Дипломная работа - Компьютеры, программирование

Другие дипломы по предмету Компьютеры, программирование



?чётчик будет при поступлении новых байт декрементироваться до 0. Также для корректного возврата из прерываний и подпрограмм необходимо инициализировать указатель стека.

В инициализацию UART входят разрешение приёма, передачи и прерывания по приёму, настройка скорости передачи и формата посылки. Для разрешения приёма, передачи и прерывания по приёму необходимо установить в регистре UCSR1B соответствующие биты. В регистре UCSR1C устанавливаются биты, которые отвечают за формат посылки. Для настройки скорости передачи в регистр UBBR1 записывается значение делителя частоты, который высчитывается по следующей формуле:

= XTAL/(16тАвbaudrate)-1;

где bauddivider - значение делителя, XTAL - частота микроконтроллера, baudrate - желаемая скорость передачи. После инициализации UART необходимо глобально разрешить прерывания путём установления бита разрешения прерываний в регистре статуса командой sei. Теперь система находится в состоянии ожидания прерывания, выполняя пустой бесконечный цикл.

3.2 Обработка прерываний

В блоке обработки прерываний считывается пришедшее сообщение путём загрузки содержимого регистра UDR1 в регистр MES, и в зависимости от счётчика BYTENUM выполняется соответствующее действие.

Если BYTENUM=7, значит посылка только началась, необходимо считать S_ID. Для этого содержимое регистра MES помещается в ячейку памяти s_id. Если BYTENUM=6, значит необходимо считать F_ID, переместив содержимое регистра MES в ячейку памяти s_id.

Если BYTENUM больше или равен 2, но меньше 6, значит необходимо считать информацию о данных. В порядке уменьшения регистра BYTENUM будут считываться старшая часть startreg, младшая часть startreg, DATACH и DATACL.

После сохранения в памяти полученного значения вызывается функция getCRC, которая посчитает CRC для каждого нового байта. После подсчёта CRC декрементируется счётчик BYTENUM.

Если BYTENUM равен 1, значит нужно сохранить младшую часть CRC. После сохранения младшей части CRC функция getCRC не вызывается, но счётчик BYTENUM декрементируется.

Если BYTENUM равен 0, значит вся посылка была передана, и после сохранения в памяти старшей части CRC вызывается подпрограмма обработки запроса. После обработки запроса значения BYTENUM, CRCL и CRCH инициализируются для новой посылки.

3.3 Обработка запроса

В первую очередь необходимо проверить, предназначалась ли посылка устройству. Если s_id равен slave_id (slave_id - id данного устройства, объявлено директивой .def), то после обработки запроса отправится ответ. Если s_id равен 0, то устанавливается флаг широковещательной передачи. В другом случае посылка не обрабатывается, так как предназначалась другому устройству.

После проверки s_id сравниваются контрольные суммы, и если они не совпадают, посылка отбрасывается.

Если CRC совпадает, то происходит загрузка функции из памяти. Если необходимо выполнить функцию с кодом более 6ти, отправляется исключение. Если код функции корректный, выполняется действие, соответствующее коду. Проверка осуществляется путём цепочки условных переходов. В R17 загружается 1, в R16 - код функции. Команда cpse сравнивает эти регистры, и в случае равенства переходит по адресу обработчика функции чтения флагов. Если регистры не равны, выполняется следующая инструкция, которая осуществляет безусловный переход на следующий этап. На следующем этапе регистр R17 инкрементируется и происходит то же, что и на предыдущем этапе, только функция на каждом шаге будет своя. Была организована именно такая система переходов, так как безусловные переходы передают управление на большие расстояния. Если ни один из переходов по адресу обработки функции не был совершён, выполняется функция с кодом 7.

3.4 Чтение флагов

В первую очередь функция чтения флагов проверяет, была ли посылка широковещательной, и если была, то функция не выполняется. После этого производится проверка значений startreg и startreg+DATACL. Если одно из этих значений превосходит 8, то отправляется исключение.

Если исключения не произошло, то происходит отправка кода устройства, кода функции и количества запрашиваемых данных. Перед отправкой байта считается его CRC. Количество запрашиваемых данных всегда равно 1, так как для флагов выделен всего один байт.

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

Если происходит запрос на чтение флагов, в регистровую пару Z загружается смещение переменной coils, и содержимое переменной загружается в регистр MES. Если читаются дискретные регистры, вызывается функция get_status_reg, которая поместит содержимое регистра статуса в регистр MES.

После загрузки флагов в регистр MES необходимо логически сдвинуть его вправо на значение startreg-1, так как нумерация адресов в протоколе modbus начинается с одного. В регистр R16 загружен startreg-1, и сдвиг происходит, пока R16 не равен нулю. Если startreg равен единице, сдвига не происходит. После сдвига регистра MES необходимо наложить на него маску, которая бы сбросила все флаги, которые не были запрошены. Число запрашиваемых флагов находится в регистре DATACL, для наложения маски вызывается функция get_mask. После наложения маски на регистр MES выполняется его отправка и расчёт контрольной суммы. После этого отправляется рассчитанное значение CRC.

Функция get_status_reg выполняет восемь проверок флагов микроконтроллера, начиная со старшего. Если бит установлен, то регистр MES сдвигается влево и инкрементируется,