реклама на сайте
подробности

 
 
> Организация стабильной работы шины I2C
Arlleex
сообщение Nov 18 2014, 19:41
Сообщение #1


Местный
***

Группа: Участник
Сообщений: 492
Регистрация: 12-11-11
Пользователь №: 68 264



Добрый вечер!
Имеется микроконтроллер, имеется некоторое периферийное устройство, подключенное к первому по шине I2C. Однажды, при отладке их взаимодействия, я столкнулся с особенностью, на первый взгляд интересной, но в то же время привносящей плачевные последствия. Дело в том, что, в отличие от синхронных интерфейсов, имеющих отдельную физическую линию разрешения (CS, EN, и т.д.), например, SPI, шина I2C таковой не является: только две линии - SDA и SCL. Усугубляется это обстоятельство еще и идеологией сигналов: в зависимости от состояний логических уровней на этих линиях различают старт-бит, повторный старт, стоп бит.
При включении питания микроконтроллер начинает инициализировать свою внутреннюю периферию, в том числе линии портов ввода/вывода, к которым подключена шина I2C. И заранее никто не защищен от переходных процессов на шине в этот момент - там может и всплеск быть короткий, и что угодно. Пагубное влияние таких всплесков налицо - они случайно могут служить условиями старта для I2C. Когда-то так получалось и у меня, пока я не посмотрел осциллограммы сигналов на интерфейсных линиях. Действительно, там был кратковременный всплеск, и I2C-ведомые думали, что микроконтроллер сформировал условие старта. А МК, ничего об этом не подозревая, шлет реальный старт-бит, вводя ведомое устройство в ступор (ну железно зашитый в нем конечный автомат, чего поделать). Далее все просто - ведомый не отправляет бит подтверждения, а в некоторых случаях может сам подтянуть линию SCL к низкому логическому уровню. А что в этот момент делает микроконтроллер? Он опрашивает различные флаги (произошло на линии условие старта или нет, передался ли адрес, принялся ли бит подтверждения и т.д.). И, к сожалению, если делать это так:
Цитата
while(!(STATUS_I2C_REG & (1 << 5))); // ожидание установки флага

и в этот момент на шине ничего не произойдет для установки этого флага, микроконтроллер тут и повиснет.
Можно сделать на прерывании, но сути не изменится - аппаратная ошибка на шине, которую можно обнаружить в регистрах I2C-интерфейса микроконтроллера, и соответственно отреагировать, но ведомому-то до этого какое дело? Вот произошла ошибка в момент передачи данных, ведомый притянул линию SCL к земле - вот и ничего не поделаешь уже, МК не сможет даже условие стопа сформировать, чтобы потом снова попытаться обратиться к этому ведомому. Я думаю вы поняли к чему я веду: случайная наводка на интерфейсной шине может сформировать определенный сигнал на шине, причем микроконтроллер еще сможет это обнаружить, но ведомый - нет. Он все так же будет ждать следующим битом, например, стоп-бит, а микроконтроллер еще только отправляет последний бит данных... Тут возникает жестокий ступор, и как вывести ведомого из него - как раз мой вопрос.
Ведь по идее делать так:
Цитата
while(!(STATUS_I2C_REG & (1 << 5))); // ожидание установки флага

нельзя нигде. Мало ли почему флаг не установится, программа зациклится и что-нибудь взорвется laughing.gif
Насколько я знаю, для таких целей предусматривают таймауты, по истечению которых обрабатывается произошедший казус. Но на I2C как обработать ошибку? У меня вариант только один - сделать управляемым питание ведомого устройства. Через полевой транзистор, например. Чуть что - перезапустили и дальше работаем.
Благодарю за внимание!
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
Arlleex
сообщение Nov 19 2014, 09:44
Сообщение #2


Местный
***

Группа: Участник
Сообщений: 492
Регистрация: 12-11-11
Пользователь №: 68 264



Сергей Борщ,
Цитата
На шине I2C пассивное состояние (лог. единица) формируется резисторами подтяжки. И если во время инициализации ваш контроллер каким-то образом умудряется сформировать там случайные нули - исправляйте программу.

Существует и стандартная процедура сброса автомата приема ведомого - нужно подать 9 импульсов SCLK не притягивая SDAT к нулю. После этого ведомое будет ожидать старт-условие.


Инициализация как ни странно - правильная. А артефакты бывают тогда, когда подключаю ведомое двухметровым проводом, но - на минимальной скорости. Про 9 бит надо попробовать, спасибо!

MiklPolikov, благодарю за подсказку!

Сообщение отредактировал Arlleex - Nov 19 2014, 09:45
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Nov 19 2014, 10:22
Сообщение #3


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(Arlleex @ Nov 19 2014, 11:44) *
когда подключаю ведомое двухметровым проводом
Тут каждый сам себе злобный Буратина. В стандарте довольно четко оговорен и кабель (если он превышает 10 см в длину) и порядок проводов в кабеле и сопротивление резисторов подтяжек. Если вы не выполнили эти требования - скорее всего проблема аппаратная и решать ее надо на аппаратном уровне. Каким кабелем вы подключаете, резисторы подтяжек какого номинала используете?

Само название шины - Inter-IC bus как бы намекает, что она задумана для связи между микросхемами, а не между устройствами.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post



Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 30th July 2025 - 22:14
Рейтинг@Mail.ru


Страница сгенерированна за 0.01387 секунд с 7
ELECTRONIX ©2004-2016