AVR Раздел по микроконтроллерам компании Atmel - AVR / ATtiny / ATmega / ATMega128 / ATxmega, вопросы по программированию в AVR studio и все, относящееся к AVR... |
12.09.2019, 13:36
|
|
Частый гость
Регистрация: 19.05.2010
Сообщений: 27
Сказал спасибо: 76
Сказали Спасибо 8 раз(а) в 2 сообщении(ях)
|
Re: Странный баг управления драйвером RS-485
Еще раз спасибо
Вариант от mimuh64 тоже работает, пошел их распихивать по установкам.
А сам хочу доделать вариант на прерываниях от UDRE и TXC, если другие дела опять не отвлекут.
Будет новости, сообщу
|
|
|
|
12.09.2019, 14:44
|
|
Почётный гражданин KAZUS.RU
Регистрация: 08.10.2007
Сообщений: 2,760
Сказал спасибо: 1,106
Сказали Спасибо 1,037 раз(а) в 569 сообщении(ях)
|
Re: Странный баг управления драйвером RS-485
Сообщение от akegor
|
такого программера надо лупить розгами до просветления и осознания.
|
Неистово плюсую.
За ожидание флажков надо наказывать.
(Видел ещё delayms(200) для дребезга. Этих сжигать на медленном огне.)
Порадовали перлы программазма:
"вдруг кто-то портит порт в прерываниях"
"Проверил поисковиком редактора "
Последовательный порт делается на прерываниях и ОДНОМ на всю программу буфере. Записал в буфер, вызвал подпрограмму, которая запихивает 1-й байт в UDR и всё, работай другое! Дальше UDREI подпихивает байты, сколько надо, а как передаст последний, TXCI переключает лапку направления передачи и конфигурирует USART на приём.
|
|
|
|
12.09.2019, 16:03
|
|
Прописка
Регистрация: 29.10.2008
Сообщений: 272
Сказал спасибо: 0
Сказали Спасибо 102 раз(а) в 95 сообщении(ях)
|
Re: Странный баг управления драйвером RS-485
Сообщение от bdn62
|
хочу доделать вариант на прерываниях от UDRE и TXC
|
Ну, это как два пальца об асфальт....
Основные настройки USART у тебя уже выполнены, передатчик и приемник USART включены,
глобальное прерывание включено...
Осталось, например, добавить описание векторов прерывания и активировать передачу...
PHP код:
|
//Handler code for [UDR] ISR(USART0_UDRE_vect) // USART vector { FCM_TX_UDR(); // call selected macro }
//Handler code for [TX] ISR(USART0_TX_vect) // USART vector { FCM_TX(); // call selected macro }
void FCM_TX_UDR() { UDR0 = buff[CNT++]; if (CNT == len) { UCSR0B |= (1‹‹TXCIE0); // включили прерывание по завершению передачи UCSR0B &= ~(1‹‹UDRIE0); // отключили прерывание по UDR0 CNT = 0; // обнулили счетчик } }
void FCM_TX() { UCSR0B &= ~(1‹‹TXCIE0); // отключили прерывание по TX PORTB &= ~(1 ‹‹ PB4); // переключили RS485 на прием... }
|
Макросы FCM_TX_UDR() и FCM_TX() можно описать в самих векторах прерываний...
Для активации работы двух этих процедур в теле программы (там где хотим начать передачу)
пишем следующие строчки
PHP код:
|
... PORTB |= (1 ‹‹ PB4); // переключили RS485 на передачу UCSR0B |= (1‹‹UDRIE0); // активировали запуск прерывания по UDR0 ...
|
Буфер передачи должен быть заполнен до активации.
Последний раз редактировалось mimuh64; 12.09.2019 в 16:10.
|
|
|
Сказали "Спасибо" mimuh64
|
|
|
12.09.2019, 17:49
|
|
Гуру портала
Регистрация: 17.07.2010
Адрес: мурмурляндия
Сообщений: 10,375
Сказал спасибо: 176
Сказали Спасибо 3,128 раз(а) в 2,017 сообщении(ях)
|
Re: Странный баг управления драйвером RS-485
прекращайте хреновней заниматься.
ставьте драйвер от каншины. там нет направлений. просто слушаешь что сам послал и все. сразу же и проверяешь кстати - то на шине шлется что записал или уже не то.
mcp2551
__________________
кагмаподэ магмаподэ
|
|
|
|
12.09.2019, 18:42
|
|
Частый гость
Регистрация: 19.05.2010
Сообщений: 27
Сказал спасибо: 76
Сказали Спасибо 8 раз(а) в 2 сообщении(ях)
|
Re: Странный баг управления драйвером RS-485
mimuh64, спасибо, чуть подсказали, заработало.
Завтра буду проверять на двух независимых каналах.
|
|
|
|
12.09.2019, 19:03
|
|
Гуру портала
Регистрация: 06.05.2005
Адрес: Краснодар, возле укротворного моря.
Сообщений: 18,841
Сказал спасибо: 2,531
Сказали Спасибо 11,764 раз(а) в 5,895 сообщении(ях)
|
Re: Странный баг управления драйвером RS-485
Сообщение от индюк
|
прекращайте хреновней заниматься.
ставьте драйвер от каншины.
|
А километр потянет?
Люблю подобные советы...
__________________
Не бейте больно, ежели чо, ну не удержался... А вааще,
"Мы за все хорошее, против всей х..., По лугам некошеным чтобы шли ступни,
Чтобы миром правила правда, а не ложь, Мы за все хорошее, нас не на...!
..." (Ленинград)
Я не несу ответственности за свои действия в Вашей голове.
|
|
|
|
12.09.2019, 20:06
|
|
Гуру портала
Регистрация: 17.07.2010
Адрес: мурмурляндия
Сообщений: 10,375
Сказал спасибо: 176
Сказали Спасибо 3,128 раз(а) в 2,017 сообщении(ях)
|
Re: Странный баг управления драйвером RS-485
А тут речь о километре чтоль? Сотни метров раблтают
__________________
кагмаподэ магмаподэ
|
|
|
|
12.09.2019, 21:01
|
|
Гуру портала
Регистрация: 06.05.2005
Адрес: Краснодар, возле укротворного моря.
Сообщений: 18,841
Сказал спасибо: 2,531
Сказали Спасибо 11,764 раз(а) в 5,895 сообщении(ях)
|
Re: Странный баг управления драйвером RS-485
Сообщение от индюк
|
А тут речь о километре чтоль?
|
Тут речь о сферическом коне в вакууме. Человек спрашивает "как", а не "что". А вот с чего Вам приванговалось, что Вы лучше знаете, ЧТО ему надо?
__________________
Не бейте больно, ежели чо, ну не удержался... А вааще,
"Мы за все хорошее, против всей х..., По лугам некошеным чтобы шли ступни,
Чтобы миром правила правда, а не ложь, Мы за все хорошее, нас не на...!
..." (Ленинград)
Я не несу ответственности за свои действия в Вашей голове.
|
|
|
|
14.09.2019, 01:57
|
|
Почётный гражданин KAZUS.RU
Регистрация: 13.03.2010
Сообщений: 2,901
Сказал спасибо: 499
Сказали Спасибо 3,061 раз(а) в 1,425 сообщении(ях)
|
Re: Странный баг управления драйвером RS-485
Ну так-то и с RS-485 можно взять, например, MAX13487E с автодирекшном, и не париться с управлением DE/RE.
Но в данном случае это было бы лечением симптомов, конечно.
|
|
|
|
17.09.2019, 16:01
|
|
Гражданин KAZUS.RU
Регистрация: 16.06.2005
Сообщений: 943
Сказал спасибо: 25
Сказали Спасибо 174 раз(а) в 123 сообщении(ях)
|
Re: Странный баг управления драйвером RS-485
Сообщение от bdn62
|
Устройство работает не первый год
|
Глядя на код верится с трудом. Хотя, пожалуй, что долго работает, поверить можно, глядя как для индекса в массиве объявляется 16-битная переменная int cnt, хотя максимальное число передаваемых байт - 8 бит unsigned char len. Ну да ладно, пошутили и хватит.
Сообщение от bdn62
|
но переключение из режима передачи в режим приема выполняет до передачи последних двух байт
|
Ровно как и запрограммировано. Что написано, то контроллер и делает. У него нет собственного разума, желаний и критических дней, хотя циклы присутствуют.
Начинаем передачу. Рассмотрим цикл. Ждём, пока буфер передачи не будет пуст (а он пуст, бо ещё не писали в него). Запихиваем в буфер первый байт (который сразу идёт в регистр передачи, бо он пуст, и передача первого байта начинается), индекс увеличиваем. Проверяем условие выполнение цикла, оно соблюдается. Ждём, пока буфер передачи не будет пуст (а он пуст, бо первый байт уже ушел в регистр передачи). Запихиваем в буфер второй байт (передача первого байта только началась так что байт остаётся в буфере), индекс увеличиваем. Проверяем условие выполнение цикла, оно соблюдается. Ждём, пока буфер передачи не будет пуст (уже реально ждём, бо пуст он станет только тогда когда завершится передача первого байта и байт из буфера (2й) пойдёт в регистр передачи). При этом флаг завершения передачи не будет установлен, бо ставится он, когда данные из регистра передачи ушли, а буфер пуст. Т.е. всё как бы логично и правильно. Вот только аппаратная (внутренностями контроллера) проверка флага пустоты буфера и установка флага завершения передачи в случае, если буфер пуст, занимает такт-два процессора, а программная поверка
while(!( UCSR0A & (1 ‹‹ UDRE0)))
занимает несколько команд по 2-3 такта. И рано или поздно, но передача байта завершится, когда буфер будет ещё пуст (т.е. только прошла проверка флага пустоты буфера, но ещё не выполнен переход к очередной проверке, и тут прерывание нибудь сработает, а судя по стилю написания - передавать в процедуру УКАЗАТЕЛЬ и 8-битную длину кадра, а потом использовать МАССИВ с 16-битным индексом... Думаю не сильно ошибусь, предположив что прерывания долго и тяжело выполняются) и флаг завершения передачи TXC0 будет установлен. Да, должно совпасть несколько факторов, и потому этот сбой происходит не постоянно. Но продолжим. Установившийся флаг TXC0 в теле цикла не сбрасывается - нет прерывания, после выполнения которого он очистится автоматически, нет его ручного сброса. Далее цикл крутится, байты идут и доходят до момента, когда остаётся передать последние 2 байта. Рассмотрим с этого момента подробней:
Ждём пока из буфера уйдёт пред-предпоследний байт.
Пихаем в буфер предпоследний байт, индекс увеличиваем, и он теперь указывает на последний байт.
Ждём пока из буфера уйдёт предпоследний байт (он запишется в сдвиговый регистр и НАЧНЁТСЯ ЕГО ПЕРЕДАЧА).
Пихаем в буфер последний байт (помним, ПЕРЕДАЧА ПРЕДПОСЛЕДНЕГО БАЙТА ТОЛЬКО-ТОЛЬКО НАЧАЛАСЬ), увеличиваем индекс, и СРАЗУ (ну не совсем сразу, 2-3 команды, проверка и переход, но относительно времени передачи таки мгновенно) выходим из цикла, потому что условие продолжения цикла cnt ‹ len нарушено.
Сразу после цикла строка
while ( ! ( UCSR0A & ( 1 ‹‹ TXC0 ) ) )
должная задержать дальнейший ход программы, пока не завершится передача, НО к ней приходим в момент, когда передача ПРЕДПОСЛЕДНЕГО байта только началась, т.е. начал формироваться старт (в лучшем случае), а в буфере лежит ПОСЛЕДНИЙ байт, который даже и не начинал передаваться, и при этом УСТАНОВЛЕН флаг TXC0. Соответственно, никакого ожидания не получается, и через насколько тактов процессора (проверка условия и переход мимо цикла и сброс флага TXC0) наступает... Тадаам! Отключение передатчика RS485 ( PORTB &= ~(1 ‹‹ PB4) ) , и именно в тот момент, когда передаётся старт-бит (ну максимум, первый-второй бит) ПРЕДПОСЛЕДНЕГО байта. Естественно передача прекращается. И два последних байта не передаются.
|
|
|
Эти 3 пользователя(ей) сказали Спасибо Someone за это сообщение:
|
|
|
Ваши права в разделе
|
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения
HTML код Выкл.
|
|
|
Часовой пояс GMT +4, время: 18:54.
|
|