Сетевой обмен RS–485

Для обмена данными по сети RS-485 используется модуль USART микроконтроллера. Процесс обмена данными обрабатывается на прерываниях.

Сначала, необходимо настроить модуль для работы по протоколу RS-485.

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

Если при приеме данных переданный адрес совпадает с собственным адресом устройства, микроконтроллер выключает режим мультипроцессорного обмена и обрабатывает следующие данные посылки. Если байт адреса не совпадает с адресом устройства, микроконтроллер игнорирует все следующие байты посылки. Поскольку данные могут иметь значение hFF (команда игнорирования записи данных), для определения типа байта используются 9 битные данные. Для большей надежности включается контроль четности данных.

В файле init.inc инициализируем USART:

out16 UBRR,bddr ; определение скорости приема/передачи

sbrp UCSRA,(1<<MPCM) ; включение мультипроцессорного режима

outi UCSRC,(1<<URSEL)|(3<<UCSZ0)|(2<<UPM0) ; включение контроля четности

; формат посылки 9 бит

outi UCSRB,(1<<TXEN)|(1<<UCSZ2) ; включение передатчика

; формат посылки 9 бит

Скорость работы bddr вычисляется в файле define.inc, формат посылки – 9 бит, один стоп бит, включен контроль четности. Обязательно включается режим мультипроцессорного обмена и включается передатчик, но пока не разрешаются прерывания.

Кроме того, необходимо при инициализации портов контроллера ножку 16 (PD2) настроить как выход с высоким уровнем. Эта ножка управляет драйвером RS-485 и переключает его на передачу.

Обратите внимание на то, что регистры UBRRH и UCSRC в выбранном микроконтроллере находятся по одному адресу h20(h40), поэтому, при обращении к регистру UCSRC, необходимо установить бит URSEL в 1.

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

В файле init.inc при инициализации ТС0 выбирается режим работы – сброс при совпадении канала А, в регистр совпадения заносится время одного периода обмена по сети, и разрешается прерывание по совпадению:

; Таймер 0: ожидание приема данных по сети

outi TCCR0,(1<<WGM01) ; режим работы - сброс при совпадении

outi OCR0,Tim_Wait ; заносится время совпадения

sbrp TIMSK,(1<<OCIE0) ; разрешается прерывание по совпадению

Время ожидания вычисляется в файле define.inc из скорости обмена данными по сети.

При обмене данными по сети могут возникать ошибки приема/передачи. Для того чтобы первая же ошибка не стала причиной сбоя в работе алгоритма, при ошибках следует возвращаться в начало цикла и повторять его. Но для того, чтобы не зависнуть в цикле, необходимо ограничить количество повторных возвратов. Для этого в RAM выделяется ячейка – счетчик циклов ошибки (CountErr), и добавляется переменная AmnErr = 3 – количество повторов при ошибках.

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

Передача данных в сеть.

Передача данных происходит по прерыванию опустошения буфера модуля USART – UDRE, при этом вызывается обработчик прерывания UDR_Ok.

В этом прерывании сначала включается светодиод передачи данных по сети, затем по состоянию точки чтения определяется 9 бит данных.

Первым передается адрес устройства, при этом точка чтения буфера = 0. При этом условии 9 бит должен быть установлен (бит TXB8 регистра UCSRB). При передаче следующих байтов, точка чтения будет увеличиваться, и соответственно бит TXB8 должен быть сброшен.

Затем вычисляется адрес ячейки в буфере передачи, данные из которой будут передаваться в сеть. Для этого в адресную пару Y загружается адрес начала буфера, и прибавляется к нему значение точки чтения. Считываются данные из ячейки буфера, и копируются в регистр UDR модуля USART.

Далее увеличивается значение точки чтения и уменьшается счетчик передаваемых байтов. Если счетчик не равен нулю (считаны не все данные из буфера) происходит выход из прерывания.

При чтении последнего байта данных (countbyte = 0) происходит переключение разрешенных прерываний модуля USART, прерывание UDRIE запрещается и разрешается прерывание по окончанию передачи данных – TXCIE.

При окончании передачи последнего байта данных будет вызван обработчик прерывания по метке TX_Ok.

В этом прерывании модуль USART переключается на прием данных (выключается передатчик, запрещается прерывание TXCIE, драйвер RS-485 переключается на прием, включается приемник, разрешается прерывание RXCIE). Сбрасывается точка чтения и точка записи буферов.

Для того, чтобы программа не зависла в цикле ожидания (если устройства с переданным адресом нет в сети, то и ответ от него не придет) используется таймер 0. Сбрасывается значение счетного регистра и запускается таймер с предделителем 1024.

После этого выключается светодиод передачи данных и происходит выход из прерывания.

Прием данных.

Прием данных происходит по прерыванию RXCIE модуля USART, при этом вызывается обработчик прерывания RХ_Ok.

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

Затем проверяются ошибки на уровне интерфейса RS-485 (ошибка кадрирования, ошибка переполнения, ошибка контроля четности). Для этого считываются данные регистра UCSRA и проверяются флаги ошибок FE, DOR, UPE. Если хотя бы один из флагов установлен программа переходит по метке Error_RX, , где происходит обработка ошибок.

Если ошибок нет, программа определяет тип полученного байта. Считывается регистр UCSRB и проверяется 9 байт полученных данных – бит RXB8, если 9 бит = 1, получен адрес, иначе – получены данные.

При получении байта адреса считываются данные из регистра UDR и сравниваются с собственным адресом устройства. Если адреса не совпадают, программа контроллера переходит по метке On_MPC. Прием следующих байтов игнорируется до прихода байта адреса.

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

Контрольная сумма вычисляется по алгоритму CRC8 в подпрограмме Calc_CRC8. Для выключения режима мультипроцессорного обмена сбрасывается бит MPCM в регистре UCSRA.

Если при проверке бита RXB8, 9 байт данных = 0 (получены данные), программа переходит по метке RX_Data. При этом, на всякий случай, необходимо проверить, что режим мультипроцессорного обмена выключен, для этого считывается регистр UCSRA и проверяется состояние бита MPCM. Если бит установлен – происходит выход из обработчика.

Затем считываются полученные данные из регистра UDR и вычисляется контрольная сумма. Относительно точки записи вычисляется адрес ячейки в буфере приема, в которую переписываются данные.

Далее увеличивается значение точки записи и уменьшается счетчик принимаемых байтов. При этом производится еще две проверки:

· если счетчик байтов = 1 (получен байт ASK), проверяется значение этого байта, если получено значение h21 – программа выходит из обработчика прерывания, иначе происходит переход по метке Error_RX, где обрабатывается ошибка.

· если счетчик байтов = 0 (приняты все данные посылки и получен байт контрольной суммы), программа переходит по метке Check_CRC, где модуль USART и драйвер шины переключается на передачу, останавливается таймер 0 и проверяется целостность всей посылки данных, при этом после вычисления контрольной суммы регистр crc8 должен быть = 0!

Если данные были приняты с ошибками, программа обрабатывает их по метке Error_RX. Здесь сбрасывается флаг приема данных (считываются данные из регистра UDR, сбрасывается флаг RXC), устанавливается флаг ошибки (флаг ErrF в регистре flag_reg), включается светодиод ошибки.

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

Если устройство не отвечает.

Если устройство не отвечает на запрос ведущего в течении длительного времени, сработает прерывание по совпадению таймера счетчика 0. При этом вызывается обработчик прерывания Wait_Full. Поскольку срабатывание прерывания вызвано ошибкой обмена по сети, прежде всего, устанавливается флаг ошибки ErrF и включается светодиод ошибки. Модуль USART переключается на передачу (в том числе переключается в порт PD2, управляющий драйвером RS-485). Выключается светодиод приема данных, останавливается таймер счетчик 0, и включается режим мультипроцессорного обмена, после чего происходит выход из обработчика прерывания.