UART + ПРЕРЫВАНИЯ
- Войдите на сайт для отправки комментариев
Втр, 29/10/2013 - 13:53
Всем доброго дня!
Вопрос такой:
Есть две ардуины соединенные по UART, одна раз в 5 сек. передает 10 переменных, другая по событию кнопки. У меня это реализовано просто через Serial.print(p1); где р1 переменная (ее значения 1 или 0).
Т.е. отправка выглядит так:
if (событие) {
Serial.print(p1);
Serial.print(p2);
Serial.print(p3);
........................
Serial.print(p9);
Serial.print(p10);
}
Но это не работает потому что через некоторо время получается каша и значения не соответствуют переменным. Передачу нужно делать с помощь прерываний.
Помогите разобраться как работать с прерываниями и стабильно передавать данные по UART пожалуйста.
Передачу нужно делать с помощь прерываний.
То что у вас выше работает, а то что не работает вы не показали. Что вам нужно конкретно вы тоже не написали.
Вставка программного кода в тему/комментарий
Прием переменных выглядит так:
Сейчас ардуина постоянно проверяет буфер UART. А если происходит сбой то значения переменных сдвигаются.
Например, если в буфере по какой то причине остались 2 байта (2 значения) от старой передачи и туда записались 10 новых байт (значений) то мы считаем 2 старых + 8 новых и в итоге вся передача сдвинется на 2 значения.
Как сделать так что бы данные из буфера забирались в тот момент когда они поступили, что бы забирать именно 10 последних записанных байт?
Зачем ждать, пока в буфере накопится 10 байт? Забирайте сразу же, как только они поступили
а если боитесь, что произойдет сбой - заведите специальный 11-тый символ, как конец последовательности. или наоборот, начало.
Ждать для того, что бы получив 10 байт сразу присвоить их 10ти переменным.
Я думал на тему спец символа, но 11 символ не решает проблему потери. Поясню, например, мы передаем ~1234567890 10 переменных где значение соответствует номеру переменной. И вдруг мы потеряли пятый байт, значение которого 5. Теперь на 5ом месте шестой байт значение которого 6, соответственно пятой переменной присвоится значени 6, шестой 7 и т.д.
Получается передавать надо пакетом и если потерян хотя бы 1 байт пакета, то в помойку весь пакет, но в этом случае надо повторно запрашивать потеряный пакет =(
А что если сразу после отправки вызывать внешнее прерывание на получающей ардуне, которое сразу считает данные из буфера? Чем может быть плох такой способ?
А с чего вдруг должен потеряться байт? Я вам могу и за платно написать 100% стабильную передачу данных, но как только вы засуните мой код в свой у вас опять начнутся потери. Так что не надо тут каких то кусков кода с вашими обьяснениями, просто покажите ВЕСЬ под приемника и ВЕСЬ код передатчика.
Байт может потеряться по причине плохого соединения, временного отсутствия питания на одном конце и т.д.
И прерывания не решат эту проблему.
Другое дело, если отправлять структуры вида (номер, данные). В этом случае отсутствие пакета сразу будет заметно.
Вот это ближе к делу, Dimsan прав, ведь даже скачок напряжения может привести к потере байта.
Так из вышенаписанного получается, что невозможно реализовать стабильную передачу отправляя последовательно байты в UART?
Вот ВЕСЬ код как сказали.
Код одной
Код другой
Код одной, с 35 по 44 передача с 46 по 53 прием.
Код другой с 21 по 27 прием с 59 по 63 передача.
В прерываниях всё прекрасно работает, за исключением обрыва линии или
потери питания. МК соединяются по схеме Master-Slave.
Master периодически, по таймеру, передаёт данные и опрашивает
Slave. В конце каждого пакета передаётся контрольная сумма,
если не совпадает то пакет не принимается во внимание и приёмный буфер
очищается. Slave в ответ передаёт либо свой статус, либо данные.
У меня так работают Master и 6 Slave.
В общем так и не ясно сколько же байт вы хотите передать ,толи 10 толи 5, по коду этого определить не получается.
Делаете так и будет вам стабильность
МК соединяются по схеме Master-Slave.
Если не секрет это как?
alex_r61, у вас на аппаратных прерываниях это реализовано?
И видите, в чем дело, я еще не дорос до понимания "контрольная сумма"
Как Master опрашивает Slave?
Каим образом очищается буфер, я такой команды не нашел?
Можно посмотреть ваши коды, мне будет очень полезно!
maksim я выложил коды как вы просили =) что скажете?
Я соединял через RS-485 трансиверы, а два можно напрямую.
Я соединял через RS-485 трансиверы, а два можно напрямую.
maksim я выложил коды как вы просили =) что скажете?
Что вам еще сказать? #10
Понятно, сами не знаете как. Открою вам секрет UART это не есть RS-485. UART не имеет ни мастера ни слейва.
Rs-485 это стандарт физического уровня, т.е. железо. А реализация Master-Slave
это програмный уровень, можете хоть ModBus прилепить. И держите свой секрет в
большом секрете.
А, программно.... Я просто еще разок вас процитирую.
МК соединяются по схеме Master-Slave.
А программно.... Я просто еще разок вас процитирую.
МК соединяются по схеме Master-Slave.
Я имел в виду именно программное подключение.
qwedhinet задайте в поисковике "сrс8 для arduino".
Программное подключение по программной схеме программными проводами.
В общем, ладно, разговор ни о чем. Нет такого подключения.
Контрольную сумму в вашем случае передаете одиннадцатым байтом.
При приеме также ее считаете и сравниваете с тем же 11-м байтом
Что-то вы тут много всего написали, только запутали человека. Он использует UART, нет тут ни master, ни slave.
Я предложил решение. CRC конечно хорошо, не спорю, но что будет если, например, 11-й байт (контрольная сумма) придёт 10-м? Приёмник будет долго ждать последний 11-й байт, по ка не дождётся начала следующих 11 байт.
CRC конечно хорошо, не спорю, но что будет если, например, 11-й байт (контрольная сумма) придёт 10-м? Приёмник будет долго ждать последний 11-й байт, по ка не дождётся начала следующих 11 байт.
Ожидание нужно ограничить. Если, после начала приёма, в течении определённого
времени не получено определённого количества байт выходить по TimeOut с флагом
ошибки.
Правильно.
На этот случай есть функция Serial.readBytes(buffer, length) - http://arduino.cc/en/Serial/ReadBytes. Принимает массив байт с учётом таймаута. Если вдруг что-то потеряется, то можно смело кричать: "Плохи дела, давай ещё раз!"
А что если, а что если....
Вы предложили увеличить размер данных в два раза. А что если под одним и тем же номером прийдут разные значения? Не надо здесь ни конторольной суммы, ни номеров. Есть проблемы с соединением - устраните проблему с соединением. Есть проблемы с питанием устраните проблему с питанием, так как это не шина и не сеть коллизии исключены, а значит данные просто так пропасть не могут.
Не спорю.
А что скажете на счёт 24-го сообщения?
У этой функции (метода) есть один минус - она блокирующая. Если так уж надо то можно обьявить переменную, в которой сохранять значение millis() как только пришел первый байт пакета и сбрасывать ее в 0 когда получили последний байт.
qwedhinet, а что за опасные условия, если не секрет, где работает эта неустойчивая конструкция - то провод оборвут, то питание пропадет, то байт сам по себе испарится? просто интересно.....