RS485
Разберёмся с RS485. Что такое RS485? Это стандарт физического уровня. И в этом месте у многих начинается путаница. А путают RS485 как ни странно с протоколами связи (UART,I2C,SPI). Такая ситуация возникает по очень простой причине. Вам надо взять два устройства и соединить их между собой. Вы берёте UART и смело передаете данные и туда и обратно. И всё работает. Казалось бы, зачем тогда нужен RS485 если всё и так работает. А работает всё только в идеальных лабораторных условиях. Попробуйте соединить два устройства в промышленном цеху в котором моторы, магнитные поля, помехи на расстояние в хотя бы 100 метров. У вас не получиться. А если получиться то работать это всё будет крайне не стабильно. Для этого и нужен протокол физического уровня например RS485. Он работает далеко, надежно, быстро.
Принцип работы и общая схема
RS-485 работает как общая дифференциальная шина. Все узлы подключены последовательно к линиям A и B и используют один и тот же физический канал. Передача ведётся в полудуплексном режиме: в каждый момент времени активен только один передатчик, остальные находятся в режиме приёма.
Контроллер управляет направлением передачи через выводы DE/RE трансивера, включая передатчик только на время отправки данных. После передачи линия освобождается, и другие узлы могут отвечать.
Для сети из контроллера и нескольких узлов каждому устройству требуется RS-485 трансивер, витая пара для линий A/B, общий провод GND, терминаторы 120 Ом на концах линии и корректная шинная топология без звёздных соединений. Скорость передачи выбирается с учётом длины линии, обычно не выше нескольких сотен килобит в секунду.
Общая схема такая ( без повторителей )
MCU → RS485 Transceiver → A/B → линия → A/B → RS485 Transceiver → UART MCU
Топология
Если в сети используется низкая скорость передачи, фронты сигналов достаточно пологие, а кабельные участки короткие, то к топологии можно относиться не слишком строго. Но как только линия становится длинной, скорость растёт или появляются помехи, топология начинает играть ключевую роль. В этом случае надёжно бороться с отражениями сигналов позволяет только одна простая схема, последовательное подключение устройств вдоль линии (daisy chain).
Это не значит, что RS-485 нельзя использовать в звездообразной конфигурации. Однако при «звезде» управление отражениями и помехами превращается скорее в искусство, чем в предсказуемую инженерную задачу. Поэтому на практике для стабильной работы почти всегда выбирают последовательную шинную топологию (daisy-chain).

Основные характеристики RS485
Дальность – до 1200м
Скорость:до 10 Мбит/с на коротких линиях, на длинных может быть и 1 Мбит/с и даже меньше
На одной шине может быть до 32 устройств без повторителей. Но есть возможность использовать специальные трансиверы, что значительно увеличивает количество узлов.
Полудуплекс линии A/B используются и для передачи, и для приёма, но одновременно говорит только один узел. Если хотите полный дуплекс, используйте 4 провода.
Напряжение на входе TTL совместимое ( 3В или 5В ). Дифференциальное напряжение ( между трансиверами ) обычно от 0.2В до 2В.
Заземление и терминирование
Хотя передача данных в RS-485 осуществляется по дифференциальной паре A/B, в реальной системе устройства часто находятся в разных точках и имеют разный потенциал земли. Из-за длины кабелей, наводок, токов утечки и работы мощного оборудования напряжение между «землями» узлов может отличаться на несколько вольт.
Трансиверы RS-485 допускают лишь ограниченный диапазон такого смещения (common-mode). Если разница потенциалов становится слишком большой, приёмник начинает работать нестабильно или может выйти из строя. Поэтому на практике часто прокладывают третий провод — общий GND, чтобы выровнять потенциалы устройств.
В более сложных или промышленно шумных условиях применяют гальваническую развязку RS-485 или экранированный кабель с правильным подключением экрана. Это повышает надежность связи и защищает оборудование от токов по земле и помех.
Линия RS-485 на большой длине перестаёт быть просто «проводом» и начинает вести себя как линия передачи с волновым сопротивлением. Когда передатчик формирует фронт сигнала, по кабелю распространяется электромагнитная волна. Если на конце линии сопротивление не согласовано, часть сигнала отражается обратно.
Эти отражения накладываются на основной сигнал, искажают уровни и фронты, вызывают ложные переходы и ошибки приёма, особенно на высокой скорости и длинных кабелях. В итоге приёмник может увидеть «дополнительные биты», дрожание фронтов или нестабильные уровни.
Терминатор — это резистор (обычно около 120 Ом), подключённый между линиями A и B на концах шины. Он согласует импеданс кабеля с нагрузкой и «гасит» волну, не давая ей отражаться. Благодаря этому сигнал доходит до приёмника в чистом виде, без эха и искажений.
Важно, что терминаторы ставятся только на физических концах линии, а не на каждом узле. Если поставить их везде, линия станет слишком нагруженной, и передатчику будет трудно сформировать нормальный уровень сигнала.
MAX485
В нашей схеме будем использовать трансивер MAX485 поэтому пару слов о нём.
MAX485 это микросхема, которая позволяет двум устройствам обмениваться данными по одной витой паре на большие расстояния. Она умеет передавать и принимать сигналы, но не одновременно (полудуплекс). Когда микроконтроллер хочет отправить данные, MAX485 включает линию передачи, а когда нужно принять — отключает передачу и включает приём. Это делает связь устойчивой к помехам и позволяет использовать всего два провода для обмена.Принцип работы MAX485 основан на дифференциальной передаче сигнала. Вместо того чтобы просто отправлять высокое или низкое напряжение относительно земли, микросхема формирует разность напряжений между двумя линиями A и B. Например, логическая “1” это когда A выше B на несколько вольт, логический “0” когда B выше A. Приёмник считывает разницу между A и B, а не абсолютное значение относительно земли, поэтому сигнал почти не восприимчив к внешним помехам и шумам на длинных проводах. То есть, даже если обе линии немного «шумят», главное разница между ними, и данные принимаются корректно.
Распиновка MAX485

RO (Receiver Output) – выход данных при приёме
RE(Receiver Enable) – включение/выключение приёма
DE (Driver Enable) – включение/выключение передачи
DI(Driver Input) – вход данных для передачи
VCC – питание +5V
A,B – дифференциальные линии
GND – земля
Сам модуль выглядит так.

Практическая реализация
Теория это хорошо, но давайте на практике пощупаем этот интерфейс. Для этого передадим данные из STM32F4 Discovery на Arduino UNO по UART используя интерфейс RS485.Расстояние будет всего пару метров, но для учебных целей этого достаточно. Для этого нам понадобятся платы STM32F4 Discovery , Arduino UNO, модуль MAX485, провод витая пара. Обязательно нужно помнить про резисторы на концах схемы, в нашем случае они есть на модуле MAX485.
Логика работы будет следующая.
STM32
– Инициализация UART
– Подготовка к передаче:
- DE = 1 (Driver Enable → включаем драйвер для передачи)
- RE = 1 (Receiver Enable → выключаем приём, так как RE активен низким уровнем)
– Передача строки по UART
– Возврат в режим приёма
Схема подключения
В модуле MAX485 есть линии данных(входы RO DI) и линии управления(входы DE RE). Мы данные передаём , в нашем случае схема будет следующая.
STM – MAX485
PA2(UART TX) – DI
PA3(UART RX) – RO
PA4(output) – DE
PA5(output) – RE
Arduino – max485
RO – D0(RX)
DI – D1(TX)
2 – DE
3 – RE
VCC – в Datasheet указано от 3 до 5В. Мы будем использовать 5В. Земля общая.
Выглядит это следующим образом.

Программный код
Начнём с STM32F407VGT6.
Так как я использую cubeIDE то настройки будем делать в нём. Проинициализируем UART выставив следующие настройки.

Самое важное здесь скорость. Скорость устройств должна совпадать.
Теперь поставим пины PA4 PA5 на выход. Получиться следующая картина.

Ещё я выставил PD12 на выход. Это светодиод на плате Discovery. Это нужно для наглядности, чтобы видеть когда ушёл пакет данных.
Нажимаем кнопку Build в нашем cubeIDE. Теперь добавим строку которую хотим передавать.
/* USER CODE BEGIN PV / uint8_t tx_msg[] = "Hello RS485\r\n"; / USER CODE END PV */
Затем выставим пин PA4 на выход.Это нужно для перевода трансивера в режим передачи. После чего передадим нашу строку и для наглядности поменяем состояние светодиода. Затем задержка 1 секунда.
/* USER CODE BEGIN WHILE */
while (1)
{
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);
HAL_UART_Transmit(huart2, (uint8_t)tx_msg, strlen(tx_msg), HAL_MAX_DELAY);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);
HAL_GPIO_TogglePin(GPIOD, GPIO_PIN_12);
HAL_Delay(1000);
/ USER CODE END WHILE /
/ USER CODE BEGIN 3 */
}
Теперь код ардуино. Опубликую его полность., т.к. он очень простой.
void setup() {
#define DE_PIN 2 // Driver Enable (разрешение передачи)
#define RE_PIN 3 // Receiver Enable (разрешение приема)
// Инициализация последовательного порта на скорости 9600 бод
Serial.begin(9600);
// Настраиваем пины управления как выходы
pinMode(DE_PIN, OUTPUT);
pinMode(RE_PIN, OUTPUT);
// Ждем инициализации порта (необязательно для Uno, но полезно для Leonardo/Micro)
while (!Serial) {
; // ждем подключения последовательного порта
}
Serial.println("Готов к приему данных...");
}
void loop() {
// Проверяем, есть ли данные для чтения
if (Serial.available() > 0) {
// Читаем строку до символа новой строки или таймаута
String receivedString = Serial.readStringUntil('\n');
// Убираем лишние пробелы и символы возврата каретки
receivedString.trim();
// Выводим полученную строку
Serial.print("Received: ");
Serial.println(receivedString);
}
}
После прошивки STM32 и Arduino включаем питание всей схемы и соединяем линию RS485 через MAX485. STM32 начинает передавать данные по UART, MAX485 переводит их в дифференциальный сигнал, и Arduino через свой MAX485 принимает эти байты. В Serial Monitor Arduino ты должен увидеть приходящие строки от STM32.

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