Работа с RS485 на микросхеме sp3485
- Войдите на сайт для отправки комментариев
Пнд, 25/11/2019 - 20:46
Здравствуйте. Купил модуль sp3485 https://ru.aliexpress.com/item/32681306095.html?spm=a2g0s.9042311.0.0.557e33edUKbEUe, а он странно работает в полудуплексном режиме. Первое сообщение он как положено присылает, а дальше не работает. На осцилографе потом я вижу график разряжающегося конденсатора после конвертации. Попробовал подтянуть 1к резистором к земле и +3,3 в, но не помогло, все тоже самое. Самое интересное что в одну сторону работает всегда, а обратно только 1 раз. Библиотека работы с UART самописная, для 485 добавил только выставление сигнала RTS.
// Формирование и отправка посылки
void UART_Serial::prepareMessage1(uint8_t dev, uint8_t cmd, long data, uint8_t length1)
{
digitalWrite(rts, HIGH);
dtStrOut.dt.dev =dev;
dtStrOut.dt.command = cmd;
dtStrOut.dt.data = data;
dtStrOut.dt.CRC = crc_calc(dtStrOut.b, length1);
MySerial->write(dtStrOut.b, length1 + 1);
delay(1);
digitalWrite(rts, LOW);
}
RS485 соединяет 2 МК STM32. Куда копать в первую очередь?
думаю, что в первую очередь надо проверять свою "самописную библиотеку"
думаю, что в первую очередь надо проверять свою "самописную библиотеку"
И чисто на UART без RS485...
думаю, что в первую очередь надо проверять свою "самописную библиотеку"
Проверять буду потом, когда с железом проблемы решу
думаю, что в первую очередь надо проверять свою "самописную библиотеку"
И чисто на UART без RS485...
На UARTе вообще-то все работает.
железячник? - из тех, кому проще всю плату заново переразвести, чем одну строчку в коде поправить? :)
Откуда такая уверенность, что проблемы именно в железе, а не в коде?
Вот с таким адаптером у меня нет ни каких проблем.
https://ru.aliexpress.com/item/33005036745.html?spm=a2g0o.productlist.0.0.708e7a8dqNOQVB&algo_pvid=edb4ffa4-766d-4830-bee7-c0d1201e983b&algo_expid=edb4ffa4-766d-4830-bee7-c0d1201e983b-0&btsid=2d6e58a5-5591-4197-94c7-a3f2fe0e91c8&ws_ab_test=searchweb0_0,searchweb201602_10,searchweb201603_55
Единственный но жЫрный минус, маркировка микросхем стерта.
Ок, буду иметь ввиду. А до 2 Mbod разгоняется, не пробовали?
железячник? - из тех, кому проще всю плату заново переразвести, чем одну строчку в коде поправить? :)
Откуда такая уверенность, что проблемы именно в железе, а не в коде?
Ну в коде нет утечек памяти, а с юартом тестировал, все работало.
Смотрел вчера на самом дешёвом китайском осциллографе, посылка идёт куда надо в итоге, но ничего не доходит. Как будто порт RX y STM самопроизвольно вчера отключился. Хотя ТХ работает все равно.
На модбас RTU не было надобности...
Чего-то странные вещи какие-то. Снял я эти sp3485 и соеденил по UART Первое сообщение СТМка принимает отлично. А дальше чего хочешь делай ничего не видит, но на осциллографе видно что все приходит. Блин, то ли контроллер погорел, то ли программный косяк. На другом конце хорошо работает, поэтому сомневаюсь что прошивка такая.
Дак напиши простую как барабан отправку ( в которой точно не накосячишь) в твой стм, чтобы рх проверить
В общем я догадался в чем проблема, тему можно закрыть. Походу нехватает копирующего конструктора. Два экземпляра класса типа serial влияют друг на друга.
я ж те говорил, что косячит твоя "самописная библиотека" - а ты не верил
Просто после отправки байтовой строки надо не сразу переключать 485 в режим приема, а подождать пока чип всю эту строку отправит.
Время ожидания: ориентировочно 1200 микросекунд на каждый отправленный байт.
Я это делал вот так:
i = 0; if (Serial.available()) { //если по USB что то пришло digitalWrite(2, HIGH); // включаем передачу 485 pause(5000); //ждем, пока все сообщение загрузится в буфер. while (Serial.available()) { //Пока саообщение не кончилось rec = Serial.read(); Serial1.write(rec); //отправляет на 232 Serial2.write(rec); //отправляет на 485 i++; } pause(i*1200); //пауза для отправки по 485. Чем больше байт ушло, тем больше надо паузу. digitalWrite(2, LOW); // включаем прием 485 }FoxJone, это какая-то несоуразная ж.
У меня на F0 все сделано на DMA, и передача и прием.
Модбас рту...
Модбас - это когда сам и приемник и передачу делаешь. А я в основном цепляюсь к чужим железкам, созданиям сумрачного военного гения. Там никаких модбасов, там в каждом случае свой собственный, специально для этой железки придуманный протокол. Пару раз даже и скорости не стандартные были.
Что не отменяет того факта, что чип 485 не успевает отправить всю посылку, если резко переключить его на прием. Пауза нужна, проверенно экспериментально. Я в первый раз неделю убил на осознание этого факта. Что характерно, нигде в примерах этого нет, но там обычно и посылки в пару байт, максимум "хелло ворлд".
У вас эта пауза есть, но маленькая: delay(1). Как раз несколько байт уходит и чип переключается на прием.
В вашем случае нужен только прием, тобишь сниффер.
Для чего идеально подходит логический анализатор с али.
И специально для вас , у меня нет никаких делаев, это удел нубов. Даже в модбас все это делается аппаратно. И кстати тот адаптер на который я дал ссылку , без управления , думайте...
Так таки ни одного делая? А в строке 9 что?
void UART_Serial::prepareMessage1(uint8_t dev, uint8_t cmd, long data, uint8_t length1) { digitalWrite(rts, HIGH); dtStrOut.dt.dev =dev; dtStrOut.dt.command = cmd; dtStrOut.dt.data = data; dtStrOut.dt.CRC = crc_calc(dtStrOut.b, length1); MySerial->write(dtStrOut.b, length1 + 1); delay(1); digitalWrite(rts, LOW); }Вы меня с ТС не путайте, ок.
Я подобную ересь в проект ну никак не впихну, в моих реалиях аурдунья табу.
Знаете , простой сишечкой живем...
Так таки ни одного делая? А в строке 9 что?
FoxJone - у вас прямо в цитировании написано. что это код Densl А отвечаете вы коиу?
https://habr.com/ru/post/279747/ Здесь описана эта ситуация. Я тоже долго бился с RS485. По 232 работало, по 485 нет. Я поставил задержку на переключение на приём. Задержка равна времени передачи одного символа на скорости 115200. Когда разбирался, оказалась что STMка выставляет флаг буфер пуст после передачи символа в аппаратный буфер передачи, а не после полной отправки, а это единственная возможность аппаратно контролировать окончание процесса отправки буфера модбас.
я подозреваю, что микросземы интерфейса rs485 в модулях у ТС и в модуле, на который ссылается dosikus - разные. На sp3485 полудуплекс и его нужно переключать снаружи. В том что у dosikis вполне может быть аппаратный выбор приема-передачи - какая там микруха ведь неизвестно
nik182 - в вашей ссылке на Хабр тоже не ясно на чем постоен интерфейс. Похоже что-то другое, потому что там скорость 115200, а в даташите sp3485 я что-то выбора скорости не вижу.
С телефона легко ники спутать, ошибся.
Думал с ТС общаюсь. И таки да, обычные мах485 или адм485, которые я в свои платы запаиваю, требуют внешнего управления и пауза после отправки нужна, я настаиваю.
Скорость зависит от того сколько сам поставишь. Это только конвертер. Я когда с модбасом развлекался на максимум STMки разгонял. На коротких расстояниях работало через 485. У меня сейчас 25 метров витой пары на установке стоит. Максимум 115200. Если больше начинает глючить.
Мозгов нет у людей, а виновата, как всегда, ардуина...
nik182, что бы тебе не надумалось вновь какой либо хрени.
Специально для тебя - в F0 аппаратная поддержка модбас рту , в частности контроль окончания транзакции мастера.
Хабр считаю абсолютным г. и не надо ссылаться на него как на аксиому.
тогда какого же хрена вы лезете в дискуссию, где обсуждаются полудуплексные модули, которые требуют ручного переключения между режимами?
Какого фига намеренно дурить ТС голову, что мол "задержка не нужна" ? Похвастать, что используете СТМ с ДМА и покрасоваться перед "лохами"?
А нука голосарь , обьясни мне чем то что я описываю отличается от полудуплексного режима применительно к модбас рту? Где по протоколу определен конец транзакции именно паузой?
Открой мануал на F0 и узрей об аппаратной поддерже модбас рту и ASCII супротив ваших кривых делаев.
Давай ты не будешь додумывать за других? Где я сказал что ссылаюсь как аксиому? Я привел пример, что человеку пришлось ставить задержку, что бы модбас с 485 заработал. Поддержка F0 есть, но только на уровне пакета. И даже это хорошо. Вот только у меня нет ни одного F0.
Переключать на приём надо по окончании физической передачи последовательного канала. А как вы это сделаете - ваша задача. Это делается довольно просто даже под ардуиновский сериалпорт. Без блокировки.
В остальных есть таймеры и IDLE и опять таки каноны протокола а не делаи.
Думай, думай...
пауза нужна не для этого. Обьясняю для "не-ардуинщиков"
Ты положил в буфер Сериал N символов для передачи. Сериал работает не блокирующе, программа пошла дальше. И ты тут же включаешь прием. Но символы то из буфера еще не отправились!
так что пауза - вещь нужная. И длительность ее FoxJone рассчитал весьма похоже для скорости в 9600
"Твой софт дерьмо" (c)...
Даже если у ТС не F0 , это элементарно делается на дма.
Если для аурдуньи это проблема, надо что-то менять в этой консерватории...
Думать как авр, это диагноз...
Коллега, а вы ничего не путаете? Модбас - это всего лишь протокол. Порядок байт в сообщении, грубо говоря.
И пересылаются эти байты по линии связи. По двум проводам, в данном случае. И если эти байты не дошли до приемника (а они не дойдут, если вы это не проконтролируете), то хоть какой у вас распрекрасный код, он это сообщение не прочитает.
И большинство бюджетных чипов 485 требуется контролировать.
b707, точно, подбирал экспериментально как раз на 9600. Подбтрал еще на 115200, но ее не помню на память.
FoxJone, вам прочитать вслух мануал на модбас?
Читаю вслух, дорого.
Намекну, Serial.availableForWrite(), или как-то так. Проверяем на HARDWARE_SERIAL_BUFFER - 1 (или как-то так) и понимаем, что последний байт ушёл в сдвиговый регистр. Далее, ждём длительность байта (с помощью micros()), возможно ещё 3.5 байта, если Modbus, и вуаля, можно переходить на приём.
Перечитай #21. Это проблема UART STM. Нет у него никаких аппаратных признаков окончания передачи. Поэтому нужна задержка. Мы тут на BLUEPILL сидим, а он на 103, аппаратной поддержки модбаса неимеет и модули 485 с внешним управлением используем. Не продвинутые мы.
да понятно, что это можно на ДМА сделать. Асинхронный ДМА с прерыванием по окончанию и в Ардуино можно сделать.
Только ТС спрашивал совсем не об этом
"Я - Д'Артаньян, а остальные..." - основной лозунг местных стм-фанатиков.
Schwarz78, мы же все таки на стм , не так ли?
Со стороны мастера:
Кинули в буфер. Пнули дма , в прерывании по полной транзакции выставили флаг отправки.
Переключились на прием.( С новыми драйверами не надо)
Со стороны слейва.
Не F0 .
Заряжается дма на максимальный размер буфера .
Однако после приема каждого байта запускается таймер на определение конца фрейма.
С F0 также заряжается дма и прерывание по паузе.
Хоть один понял Досика? Принимать можно только окончив передачу. Эта детская ошибка вылезает всегда, вот просто всегда.
b707, вы наконец то стали слушать тс?
Я его раньше услышал. И дал дельный совет
А теперь посмотри кто стал, не слушая ТС гнуть пальцы, уводя разговор в дебри.
Намекну, Serial.availableForWrite(), или как-то так. Проверяем на HARDWARE_SERIAL_BUFFER - 1 (или как-то так) и понимаем, что последний байт ушёл в сдвиговый регистр. Далее, ждём длительность байта (с помощью micros()), возможно ещё 3.5 байта, если Modbus, и вуаля, можно переходить на приём.
Ну так а я про что рассказываю весь топик? Надо ждать! И именно через микрос. Единственный делай (от которого так бомбит у стмщиков) в этом топике у ТС в стартпосте.
Хоть один понял Досика? Принимать можно только окончив передачу. Эта детская ошибка вылезает всегда, вот просто всегда.
Марш читать мануал.
FoxJone, если нужно действительно осознание а не срач, могу помочь.
Да какая разница на чём мы? Физический принцип один. Даже на 1816ВЕ31 приходилось дожидаться конца передачи, хоть тресни.
Хоть один понял Досика? Принимать можно только окончив передачу. Эта детская ошибка вылезает всегда, вот просто всегда.
На микросхему sp3485? Сам иди.
совет взять другой модуль или переписать все на ДМА - уж слишком "дельный", на уровне лечения мигрени гильотиной. Думаю, добавить задержку ТС будет проще.
Согласен, что на ДМА все делается, хотя задержки все равно нужны. Оттого, что задержка отрабатывается асинхронно по прерыванию - суть не меняется
Дожидаться можно по разному.
Или по дебильному ждать окончания делай, либо в конечном автомате проверять флаг.
И здесь заканчиваются страдания обсасывателей миллис и начинается вменяемый кодинг.
Хоть один понял Досика? Принимать можно только окончив передачу. Эта детская ошибка вылезает всегда, вот просто всегда.
На микросхему sp3485? Сам иди.
На протокол модбас.