RS485 Потеря информации при переключении прием-передача
- Войдите на сайт для отправки комментариев
Добрый день, коллеги.
Имею вот такую задачу: есть железка, которая шлет информацию по RS485 (115200, 8 битб 1 стоп). Информацию эту она шлет не кому попало, а только пополучении ответа на свой запрос. То есть железка делает запрос, корреспондент должен правильно ответить, и только после этого железка даст инфу.
Подключил я к этому вопросу Мегу и стандартный конвертер 485 на мах485. Все, что получает мега по 485, тут же шлет в байтах в монитор порта. В красивом читабельном виде. Плюс, слежу за линией 485 через терминал (есть у меня сканер 485/232).
На мегу залил вот такой скетч:
int i = 0; int j = 0; int incom = 0; int rec[255]; int Answer[21] = {254, 3, 5, 5, 134, 12, 0, 33, 202, 247, 102, 64, 96, 72, 1, 28, 0, 120, 97, 232, 88}; long del = 0; void setup() { Serial.begin(115200); Serial1.begin(115200); pinMode(DIR, OUTPUT); //пин переключения прием/передача на 485 digitalWrite(DIR, LOW); // включаем прием i = 0; } void loop() { if (Serial1.available() > 0) { incom = Serial1.read(); //читаем байт if (incom == 254) { //начало новой посылки всегда 254 Serial.print(" i="); Serial.println(i, DEC); i = 0; //если начало новой посылки, то выводит количество байт в предыдущей посылке, переводит строку в мониторе и обнуляет счетчик байт в посылке } if (incom < 16) Serial.print("0"); // добавляет в мониторе ноль к мелким байтам.. ну привык я хексы видеть двузначными... Serial.print(incom, HEX); Serial.print(" "); //выводит в монитор полученный байт. Это все отладочный модуль, потом я его уберу. rec[i] = incom; //заносит полученный байт в массив if (i == 8) { //если получено 9 байт с начала посылки, то обрабатывает информацию (9 байт = команда от железяки) if (rec[1] == 3 && rec[2] == 5 && rec[3] == 5 && rec[4] == 134 && rec[5] == 0 && rec[6] == 0 && rec[7] == 0 && rec[8] == 0) { //если первые 9 байт совпали с командой "запрос связи", мега отправляет ответ digitalWrite(DIR, HIGH); // включаем передачу for ( j = 0; j <= 20; j++) { Serial1.write(Answer[j]); //ответ из 21 байта. Железка его точно принимает и по его получении шлет инфу del = millis(); while ((millis() - del) < 2) { } // задержка между отправкой байтов. Без нее железка не читает, видимо слишком быстро шлются. } digitalWrite(DIR, LOW); // включаем прием Serial.print(" i="); Serial.println(i, DEC); Serial.println("sent answer"); } if (rec[1] == 3 && rec[2] == 9 && rec[3] == 45 && rec[4] == 134 && rec[5] == 28 && rec[6] == 0 && rec[7] == 80 && rec[8] == 66) Serial.println("test command"); //тестовая команда, которая ни разу не сработала( } i++; } }
Что имею в итоге: в сканере ясно видно, что железка шлет запрос, мега отвечает, железка ее понимает и шлет команду с инфой (это инфа прямо из линии 485):
Так у вас в 35 строке задержка стоит. Она не только между посылаемыми байтами срабатывает, но и перед переключением на прием. Вот и терчются первые байты.
Задержка нужна, что бы убедиться, что все данные из буферов переданы в линию. Слейв перед отправкой должен иметь некоторую задержку, во вторых мастер должен убедится что все данные ушли и сразу начать слушатт линию. Убедиться можно проверив количество байт в буфере отправки.
Задержка нужна, что бы убедиться, что все данные из буферов переданы в линию. Слейв перед отправкой должен иметь некоторую задержку, во вторых мастер должен убедится что все данные ушли и сразу начать слушатт линию. Убедиться можно проверив количество байт в буфере отправки.
Да, все верно. Проблему решил, уменьшив задержку до 75 микросекунд.