Перейти к содержанию
    

Mega16+TWI+Mega16 Проблемы и решение

Atmega_16+TWI+Atmega_16 - Возникшие проблемы и их решение.

Может кому пригодится сэкономить кучу времени.

 

Сначала немного предистории. В начале 2000-х я уже использовал TWI для связи двух Atmega 64. Там была простая передача данных от Мастера к Слэйву. Делал по примерам, Мастер управлялся напрямую, Слэйв по прерываниям. Заработало сразу и я особо не разбирался с этой шиной. Несколько десятков стендов до сих пор работает по стране и претензий к шине не было.

Недавно, для очередного проекта мне не хватало ног и я попробовал использовать Atmega 32 + 5шт расширителей PCF8574, и был неприятно удивлен. При разводке платы я особо не задумывался, на какую из микросхем вешать тот или иной вход или выход. Куда ближе, туда и проводил. И большинство кнопок повесил на расширители. Кнопки опрашивал раз в 10 мс. Так вот, эти расширители стали виснуть за время от нескольких секунд, до часу. Мне показалось, что висли именно те PCF, где был опрос входов. Их оживление - только через сброс питания.

Порезал дорожки на плате, переразвел проводами так, чтобы все кнопки были подключены непосредственно к МК. Частота обмена по шине снизилась до 1 с. (Только индикатор обменивался довольно длинными пачками, но там только выход) Сбои стали крайне редкими, но меня это не устраивало. Устройство (пеллетный котел) должно работать весь сезон без сбоев.

Переделал схему на две Atmega 16 связав их по SPI (и TWI, как вариант Б). Я решил, что проблема именно в PCF8574 и неудачной реализации ее шины, так как, я уже говорил, что связка 2-х Atmega работала нормально (правда там был режим - несколько часов в день, и, возможно, проблема не успевала проявиться).

Вариант по SPI что-то не заладился. Мастер дает пачки, а Слэйв не хочет входить в прерывание, хоть ты тресни. Решил пока применить вариант Б, а то время поджимает, а со SPI разберусь попозже. И вот тут меня ждала засада.

Сначала применил свой старый код. Передача на слэйв идет нормально. А вот прием - никак. Переделал код в соответствии с примерами AVR312/315. Мне показалось, что так легче отлаживать. Только там в примерах постоянно включают/отключают разрешение прерывания TWI. Это лишнее, решил я, можно оставить разрешение постоянно, так как вариант от Atmel исключал возможность смены Мастера и Слэйва местами. И тут же получил по рукам. После передачи появлялось ложное прерывание Слэйва со статусом 0xA0 - РеСтарт. В принципе его можно проигнорировать в обработчике Слэйва, хотя это лишало возможности самому использовать такую возможность обмена. Причем, на осциллографе была видна стабильная иголка на полке СТОП в первой ее трети, там где Слэйв передавливает Мастера (я временно ввел резистор 200 Ом в линию SDA, чтобы видеть, кто именно давит линию).

Вернулся к коду примера. Передача заработала нормально, пропали как ложное прерывание, так и сам пичок. Так что это не просто такой стиль программирования, а необходимость, вызванная особенностью исполнения TWI у Atmega. Но, самый первый запрос на обмен игнорировался. Пришлось вставить в код функции tw_Send() сначала разрешение IRQ, а спустя какое-то время, запуск TWI. Теперь проходят все запросы на передачу.

Далее возникла проблема с приемом. Сам прием проходит нормально, ставится флаг завершения пачки, но (куда же без него), стабильно, примерно через 100 мкс после конца приема, возникает ложное прерывание со статусом 0х00 - "Сбой шины". На осциллографе никакой иголки в этом месте не вижу. (Хотя не факт, что ее там нет. У меня Tektronix TDS 1002, и я уже встречался с ситуацией, когда иголка есть, вызывает прерывание, а цифровой осцилл ее не видит). Как временное решение, ставил ошибку и, в основном цикле, переинициировал TWI. Но ведь это не дело!.

Очень долго искал проблему, пока не вышел на флаг TWSTO. В примере 312, при приеме, он использовался для сообщения Слэйву, что принята вся пачка и пора освободить шину. А при передаче он отсутствовал. Попробовал вставить в конце передачи. Пропало ложное прерывание, зато Слэйв перестал отпускать шину.

Когда искал возможное решение на разных форумах (кстати, почему-то моя проблема нигде не всплывала), мелькнуло сообщение, что какой-то из STM будет нормально работать по TWI только тогда, когда один из его сигналов, после его установки, сбросить вручную через определенное время. Я попробовал вариант, когда при передаче Слэйвом последнего байта ставится бит TWSTO, а спустя 20 мкс снимается. И о чудо, все заработало как надо, но времени убил воз и маленьку тележку.

Странно, что не вижу сообщений о подобной проблеме с приемом по IRQ. Пример 312/315 упоминается часто, связь 2-х mega16 тоже. Или в моем случае так планиды сошлись? Может что-то с конкретной партией МК? Непонятки.

 

Далее приведена нарезка кода для Мастера и Слэйва. Пишу на IAR EW.

Отлаживаю под AVRStudio 4.18 + AVR JTAG USB.

 

Здесь приведена нарезка кода для Мастера.

twi_master.txt

 

Здесь приведена нарезка кода для Слэйва.

twi_slave.txt

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

После передачи появлялось ложное прерывание Слэйва со статусом 0xA0 - РеСтарт.

Странно, что не вижу сообщений о подобной проблеме с приемом по IRQ.

Если еще актуально.

RepStart передается мастером, если пересылка Stop еще не завершена и при этом дана команда на передачу Start. Вот такая фича. Установлено эмпирически ценой мегавремени. Я боролся с помощью отслеживания завершения пересылки Stop (и только после этого давал Start). Все равно 100%-ного избавления не получилось.

Я об этом здесь кому-то уже писал энсколько лет назад.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В данном случае проблема была в другом. Нового старта еще нет.

Иголка, связанная с прерыванием была действительно на полке сигнала СТОП,

но вызвана, на мой взгляд, немного сырой реализацией внутренней логики

интерфейса и проявилась только при коде, слегка отличном от примера,

то есть когда я пытался работать не выключая прерывание (бит TWIE),

и при этом, где-то в таймингах логики образовалась дырка.

 

Мое недоумение как раз вызвано недоделкой интерфейса.

Только вот я не знаю, было ли это изначально и никто не заметил.

Или это выплыло позже, что-то правили и зацепили. Это часто бывает.

Или просто такая партия попалась. (И с этим я тоже сталкивался,

например, была партия с очень большим временем записи EEPROM).

 

Кстати, если кто-то захочет использовать приведенный мной код,

в файле twi_slave.txt строка 18 - while(TWCR & (1<<TWINT));

явно лишняя. Время от времени этот бит не сбрасывается и

код зависает в бесконечном опросе, в тоже время, это никак

не влияет на последующие операции, так что опрос бита лишний.

 

Ну и для тех, кто не в курсе, в примере я использую подробные комментарии

на русском, но, естественно, в реальном коде нельзя использовать

маленькую 'я', ее код 0xFF используется как спец код в каком-то из

инструментов. Чаще всего он никак не влияет на компиляцию.

Но, время от времени нарушает ее ход, и можно долго искать, чего это

отладчик идет по коду не туда, да еще пытается выполнить заремированные

строки.

 

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...