Ошибка по шине i2c

Ошибка по шине i2c

Напряжение питания как к линии SDA , так и к линии SCL подводится через нагрузочные резисторы. Значение этого напряжения обычно составляет от 4,5 В до 5,5 В и должно точно соответствовать приведенному в сервисной документации уровню. Поиск неисправностей, поэтому следует начинать с измерения питающего шину напряжения. К прекращению обмена информацией в шине могут привести также колебания питающего напряжения питания, особенно в тех случаях, когда появляется какая-нибудь нерегулярная неисправность. Пульсации могут составлять всего лишь несколько милливольт, поэтому в сомнительных случаях проверку питающего системную шину напряжения надо проводить с помощью осоцилографа.

Обычно на входах блоков, подключаемых к системной шине, или перед микросхемами в этих блоках располагают еще и развязывающие резисторы. С помощью измерения напряжения на этих резисторах можно установить наличие короткого замыкания в соответствующем блоке. Если такая неисправность присутствует, то измеренное напряжение на выводе резистора, со стороны подключенного блока или микросхемы, имеет существенно более низкое значение, чем на другом выводе резистора. Если же в проверяемых узлах короткое замыкание отсутствует, то падение амплитуды сигнала на соответствующих развязывающих резисторах незначительное из-за достаточно низкого их номинала (от 100 Ом до 1 кОм). Поиск неисправностей усложняется, когда отдельные узлы и схемы подключены к системной шине без развязывающих резисторов, так как в этом случае любой неисправный узел может полностью заблокировать обмен информацией по системной шине. В этом случае придется последовательно отсоединять подключенные к шине отдельные узлы и схемы.

Уже измерение напряжения до и после нагрузочных резисторов может дать указание на вероятную неисправность в одном из устройств, подключенных к системной шине, если падение напряжения на этих резисторах слишком велико.

Необходима также проверка наличия сигналов в линиях SCL и SDA шины. Отсутствие сигнала синхронизации в линии SCL указывает на необходимость проверки работоспособности центрального управляющего устройства, а также внешнего кварцевого резонатора тактового генератора ЦУУ. Неисправности частотозадающих элементов тактового генератора могут быть причиной отличия тактовой частоты от номинальной, что также может привести к нарушению обмена информацией в шине.

Тактовый сигнал может представлять собой синусоидальный сигнал, либо сигнал прямоугольной или трапециевидной формы.

Наличие импульсных сигналов номинальной амплитуды в линии SDA -шины само по себе не дает достоверной информации о правильности обмена данными между узлами ВМ, подключенными к системной шине, но при их наличии можно условно считать, что обмен данными в системе происходит правильно.

Видео:How To Solve I2C HID Device Driver Issues EasilyСкачать

How To Solve I2C HID Device Driver Issues Easily

Обработка ошибок и перезапуск модуля I2C

Сегодня в комментариях меня попросили рассмотреть работу I2C более подробно, обратить внимание на нетривиальные случаи: например, что будет в случае возникновения ошибок на линии, как такие ошибки обрабатывать? Дело в том, что при появлении таких ошибок модуль I2C часто «зависает», и не реагирует на дальнейшие обращения — нужно ловить такую ситуацию и перезапускать модуль.

Стандартная процедура общения с I2C-модулем предусматривает отправку байт и проверку флага — передано или нет. Флаг проверяется в цикле while, и именно этот цикл подвержен зависаниям — если флаг не устанавливается из-за ошибки, из этого цикла мы уже не выйдем никогда.

Я предлагаю простой способ выхода из этой ситуации — вместо простого while нужно сделать «while с условием». К примеру, если цикл опроса флага безрезультатно прокрутился более 200 раз — наверное ситуация уже не изменится, т.к. возникла ошибка. Значит нужно перезагружать модуль I2C.

Сделать это просто: добавим переменную «таймаут» = 200, и в цикле опроса флага будем её декрементировать. Как только она дошла до нуля — сбрасываем текущую передачу и перезапускаем модуль. Очень важно именно отменить передачу, потому что иначе после перезапуска модуля она продолжится с того места, где застряла в прошлый раз — ну и ни к чему хорошему это не приведёт.

Код примера, демонстрирующего эту «безопасную передачу», таков:

И в заключение пару слов, почему я сделал именно так, ведь более логичным было бы добавление прерываний на ошибки и обработка этих прерываний. Я просто хотел как можно меньше менять исходный код, сделать это проще всего оказалось именно расширив стандартный while до такого «while с таймаутом». Более того, так можно обойтись без глобальных переменных, а это всегда очень хорошо.

Читайте также: Вулканизация шин по протектору

Введение обработчиков прерываний ошибок раздуло бы код и спрятало бы основную логику. Мне это неудобно. Кстати, подобная проблема встречалась у меня при работе микроконтроллера LM3S с RFID-ридером, я думаю такой подход решил бы её.

Видео:Введение в шину I2CСкачать

Введение в шину I2C

Многобукфф

Видео:I2c шина в iPhone, способы диагностики, причины циклического перезапуска.Скачать

I2c шина в iPhone, способы диагностики, причины циклического перезапуска.

Vladislav’s personal blog site

Видео:Шина I2C.Скачать

Шина I2C.

Нестабильная работа с I2C под STM32

Волею судеб мне пришлось разрабатывать прошивку для одного устройства на основе микроконтроллера STM32F103. Функций у устройства много, в том числе и общение с EEPROM подключенным посредством протокола I 2 C. Кто не знает, микроконтроллеры STM32 во многих своих версиях поддерживают работу по данному протоколу на аппаратном уровне. Это значит, что у микросхемы микроконтроллера присутствуют специальные выводы, которые можно использовать в том числе и для работы по протоколу I 2 C, а все издержки по этому протоколу выполняются «железом» микроконтроллера.

Ошибка по шине i2c

Вообще, I 2 C — штука популярная. Реализуется не так сложно, для его работы требуется всего два сигнальных провода. По одному подаются тактовые импульсы, по второму происходит передача данных, привязанная к тактам первого провода. К шире или выводам I 2 C можно подключить несколько устройств, они не будут мешать друг-другу, т.к. при обращении к конкретному устройству указывается его уникальный адрес.

Шина I 2 C не высокоскоростная и предназначена в первую очередь для обмена данными с различными датчиками, модулями и внешними системами. Через шину прокачать много информации не выйдет, но этого и не требуется. Главное, что она проста, дешева и универсальна. Ну много ли данных передает в секунду датчик температуры или давления? Сущие байты. Этого вполне достаточно.

Как правило в шине I 2 C применяется система с одним ведущим устройством и подключаемыми к нему ведомыми. В качестве ведущего устройства, разумеется, используется микроконтроллер. И он опрашивает подключенные устройства, в надежде получить с них данные. Каким же образом передаются данные по-фактически одному проводу? Конечно, передача данных по одному проводу в I 2 C не является полнодуплексной. Нет возможности в стандарте по одному проводу передавать и принимать данные одновременно. Поэтому, команды на передачу дает ведущее устройство, а все остальные слушают и отвечают, когда это им позволяется.

Простота протокола I 2 C иногда оборачивается и обратной стороной. Отлаживать проблемы, возникающие в коммуникации с внешними устройствами зачастую очень не просто. Ведь в цифровом мире либо устройство работает, либо нет. А еще больше усложняет проблему случай, когда вроде бы работает, а потом, по какой-то причине не совсем работает. Вот именно такая петрушка и произошла в моем случае.

Для реализации микропрограммы был выбран фреймворк STM32Arduino, так как требовалось использовать некоторые библиотеки, которые легче взять готовые, нежели разрабатывать их заново. К чипу же STM32 подключена обычная микросхема EEPROM на несколько килобит. EEPROM используется для частых записей, для чего не предназначена Flash-память на чипе STM32. Все аппаратные подключения проведены в строгом соответствии с документацией как производителя микроконтроллера, так и микросхемы EEPROM. И именно проверка того, как сделаны аппаратные подключения, надежно ли питание, есть ли все необходимые подтяжки и прочее, должна происходить в самую первую очередь, если возникла проблема. Иначе можно потратить годы на то, чтобы найти программную причину ошибки, особенно там, где ее нет.

В моем случае проблема заключалась в выдаче недостоверных результатов с EEPROM и невозможность записи. Точнее запись проходила, но на конечный осмысленный результат они никак не влияла. Причем неполадка появлялась только после аппаратного перезапуска устройства и примерно один раз из десяти. Присутствие какой-либо адекватной реакции от всех программах слоев, на которые опирается STM32Duino ожидать не стоит. I 2 C протокол простой и он либо работает, либо нет. И он работал, выдавал данные, причем даже если данные с EEPROM приходили откровенно левые, то никакие ошибки обращения с библиотекой Wire не возникало. Пришлось начать копать интернет в поисках похожих ошибок и методов их решения.

Читайте также: Какое давление в шинах беларус

Как оказалось, проблема при работе с I 2 C на чипах STM32, особенно семейства F103, возникает чуть ли не у каждого второго пользователя чипов. Причем независимо от того, на чем он пишет свой код: HAL, Arduino, Mbed или еще чего. Проблем возникает много, у кого-то ничего не работает сразу, что несколько легче, так как искать ошибку проще, а у других все работает из коробки, но не постоянно. Основные проблемы, на которые натыкаются пользователи кроются в некоторых, назовем их так, особенностях структуры чипов STM32F10x, да ошибках, которые присутствуют в HAL.

Приведу основные причины возникновения неполадок с I 2 C, полученные после изучения «всего интернета»:

  • Ненадежное аппаратное подключение, ненадежное неверное питание, несоблюдение рекомендаций по подключению.
  • Блокировка шины на стороне микроконтроллера со статусом Busy.
  • Перепутанные выходы, перепутанная инициализация при добавлении второго канала I 2 C на многоканальных чипах. Ошибка из серии «Я скопировал оттуда, где работало, а тут не работает».

Кстати, последняя ошибка встречается не столько при простом копировании кода, завязанного на работу через I 2 C, а сколько на его инициализацию. STM32 штука сложная и если невнимательно работать с Cube или писать инициализацию своими руками, то наверняка куда-то может затесаться мизерная ошибочка, которую замыленный глаз уже не в состоянии разглядеть. Вторая же ошибка по большей части связана с неверной (а зачастую с бездумной) инициализацией микроконтроллера, но присутствуют и особенности реализации (читай ошибки) в самом чипе. С ними (обнаруженными и признанными) и объясняется что делать в замечательном документе Errata sheet (ссылка внизу статьи).

В общем наилучшее, что мог создать коллективный разум, это код принудительной переинициализации функции I 2 C через HAL с дополнительными задержками:

/* USER CODE BEGIN SysInit */
HAL_RCC_I2C1_CLK_ENABLE();
HAL_Delay(100); HAL_RCC_I2C1_FORCE_RESET();
HAL_Delay(100);
__HAL_RCC_I2C1_RELEASE_RESET();
HAL_Delay(100);
/* USER CODE END SysInit */

В Arduino на STM32 данный блок так же можно применить, но он не помогает, по крайней мере, в моем случае. Пришлось еще немного пораскинуть мозгами и попытаться докопаться до причины проблемы, а потом попытаться ее решить. В моем случае обмен данными с EEPROM по I 2 C идет без каких-либо проблем. Данные читаются, записываются, никаких ошибок не возникает. Только вот в одном разе из 10 после аппаратной перезагрузки всей системы, EEPROM начинает выдавать совершенно левые данные, при этом никаких ошибок не возникает. С записью тоже в такие моменты не все гладко, проверить-то никак.

Как известно, чипы STM32 многофункциональны и многие из выводов микросхем могут быть использованы под различные функции. У многих микроконтроллеров, не только у STM32, после перезагрузки, некоторые выводы могут переключиться в так называемые неинициализированные состояния. Обычный софтверный разработчик, как правило не задумывается над тем, какой у него уровень на выводах микроконтроллера после его перезагрузки. Высокий? Низкий? Серединный? При использовании фирменного конфигуратора STM32Cube есть возможность настроить инициализацию выводов и некоторых других функций микроконтроллера путем относительно простого конфигурирования. Но данная процедура может быть опущена, а инициализацию можно провести позже, например, при процедуре вызова той или иной функции. Именно последним путем и пошли разработчики STM32Duino. При загрузке микроконтроллера происходит так называемая базовая инициализация функций микроконтроллера, ножки выводов принимают значения по умолчанию. А вот если с данной конкретной ножки требуется другая функция, то ее инициализация происходит при первом вызове соответствующей функции.

В чипах STM32 инициализация происходит очень быстро, ну сами чипы скоростные, это, во-первых, а во-вторых, загрузчик не тормозит загрузку пользовательского кода, так как вызывается при соответствующей аппаратной комбинации. Значит, проблема неинициализированных «ног», когда на них болтается неизвестно что, встает не в полный рост. А вот на других чипах микроконтроллеров, где загрузчик некоторое время ожидает подачу ему сигнала и только потом переходит на пользовательский код, проблема может существенно попортить жизнь. Представьте, что на такой «ноге», которая еще не определилась с уровнем своего сигнала, «висит» управляющий контакт реле. И вот на реле идет жуткая последовательность непонятных сигналов. Что ему делать? Дергаться туда-сюда, пока микроконтроллер не определиться со своим выводом?

Читайте также: Ремонт шин в таганроге

Опытный читатель или электронщик, уже догадался, в чем изюминка порылась. Микросхема EEPROM возвращает неверные данные, а библиотека, работающая с I 2 C, говорит, что все нормально, ошибок нет. Суть нестабильного поведения кроется в следующем. На универсальных чипах STM32F103 многие из выводов многофункциональны. При неверной инициализации или отсутствии инициализации, на «ногах», подключенных к микросхеме EEPROM, может появиться произвольный сигнал, который «сведет с ума» саму микросхему EEPROM (команды на обмен данными с EEPROM та еще китайская азбука, куча условностей, задержек и прочего). Да, она будет как-то реагировать на команды, но вот выдавать данные может совсем не те, что должна. Повторная инициализация I 2 C в микроконтроллере ничего не даст, так как ведомое устройство уже не в себе и вывести его из себя можно только аппаратной перезагрузкой микросхемы EEPROM (перезагрузка микроконтроллера тут не помогает, по той же причине, что и переинициализация через HAL).

Именно такая ситуация возникла в моем случае. Проблема возникала случайным образом, но статистически она присутствовала. Если код инициализации Wire поместить ближе к началу программного кода, то вероятность возникновения ошибки уменьшается, если отодвинуть его куда-то подальше, то ошибка будет возникать чаще. И спастись от проблемы можно только аппаратным сбросом всего оборудования (передергиванием питания).

Так как же можно избавиться от проблемы «сумасшествия» ведомой микросхемы EEPROM? Очевидно, что нужно максимально быстро проинициализировать соответствующие терминалы ввода-вывода, дабы успеть в тот момент времени, пока EEPROM не начнет жить по своим собственным законам, повинуясь непонятным сигналам с микроконтроллера. Другими словами, подвинуть код инициализации Wire в самое начало программы. Но… Данный трюк не решает полностью описанное поведение EEPROM. Все еще остается вероятность отказа EEPROM (и опыты это подтверждают). Почему? Потому, что выполнение кода инициализации Wire занимает какое-то время, бесценные микросекунды, которых хватает на то, чтоб EEPROM удалились в мир грез и фантазий. Что в этом случае можно сделать?

pinMode(I2C_SCL, OUTPUT);
pinMode(I2C_SDA, OUTPUT);

Оказалось, что достаточно только проинициализировать порты микроконтроллера, ответственные за I 2 C как выходные цифровые выводы, как можно быстрее. В этом случае цифровое, а скорее аналоговое, шатание отменяется и невменяемость EEPROM тоже. В STM32Duino при инициализации пина как выходящего, он автоматически включается на низкий уровень. Если этого не происходит, например, поменялась идеология разработчиков фреймворка или вышла новая плата, на которой все не так, то дополнительно можно принудительно установить низкий уровень, что должно обеспечить нормальную работоспособность всей связки.

А что же до любителей HAL и особенно STM32Cube? Если работать только на HAL и не прибегать к Cube, как к средству конфигурирования, то проблема будет ровно такой же. Если не применить четкую инициализацию «ног» I 2 C как можно быстрее, то нормально с EEPROM не поработаешь. Впрочем, с Cube тоже не все так гладко как хотелось бы. Да, утилита помогает провести инициализацию микроконтроллера, которая сама по себе не отличается простотой. Но и тут могут быть нюансы. Во-первых, код инициализации I 2 C из Cube может быть выполнен в самую последнюю очередь, когда уже поздно, во-вторых, могут наступить и прочие конфликты, связанные с неверной инициализацией (Cube только выглядит просто, на самом деле без понимания туда лезть не стоит). Более подробно о потенциальных проблемах можно почитать в ссылках ниже.

  1. STM32 WRITE AND READ EEPROM OVER I2C BUS — статья детально разжевывающая методы обращения с EEPROM подключенным посредством I 2 C.
  2. STM32F10xx8 STM32F10xxB Errata sheet (medium-density device limitations) — бюллетень от STMicroelectronics описывающий возможные затруднения и способы борьбы с ними по различным блокам своих микроконтроллеров. Проблем работы с I 2 C в документе указано аж 7.
  3. STM32 — I2C — HAL_BUSY — статья что делать, если возникает Busy.

Опубликовано 12.09.2020 автором kvv в следующих категориях:
DIYSoftстатья

  • Свежие записи
    • Нужно ли менять пружины при замене амортизаторов
    • Скрипят амортизаторы на машине что делать
    • Из чего состоит стойка амортизатора передняя
    • Чем стянуть пружину амортизатора без стяжек
    • Для чего нужны амортизаторы в автомобиле


    📽️ Видео

    Подключение нескольких устройств, датчиков по I2C (АйТуСи) шинеСкачать

    Подключение нескольких устройств, датчиков по I2C (АйТуСи) шине

    Урок 24. Узнаём адреса устройств на шине I2CСкачать

    Урок 24. Узнаём адреса устройств на шине I2C

    Урок 26.3 Соединяем две arduino по шине I2C #iarduinoСкачать

    Урок 26.3 Соединяем две arduino по шине I2C #iarduino

    Лекция 308. Шина I2CСкачать

    Лекция 308.  Шина I2C

    Логический анализатор шины i2cСкачать

    Логический анализатор шины i2c

    Урок 9. Адреса модулей на шине I2C. Arduino (что такое I2C, адресация, как изменить адрес модуля)Скачать

    Урок 9. Адреса модулей на шине I2C. Arduino (что такое I2C, адресация, как изменить адрес модуля)

    Обработка ошибок I2C на микроконтроллере STM32Скачать

    Обработка ошибок I2C на микроконтроллере STM32

    Подключение нескольких устройств по шине i2cСкачать

    Подключение нескольких устройств по шине i2c

    I2C. Краткая теория с примером. STM32 CubeIDE.Скачать

    I2C. Краткая теория с примером. STM32 CubeIDE.

    I2C LCD not showing Text | I2C LCD Errors Fixing || 16x2 LCD not displaying Text || 1602 LCD ErrorСкачать

    I2C LCD not showing Text | I2C LCD Errors Fixing || 16x2 LCD not displaying Text || 1602 LCD Error

    Проверка работоспособности шины I2CСкачать

    Проверка работоспособности шины I2C

    I2C HID Device Error (TUF Gaming FX505GM)Скачать

    I2C HID Device Error (TUF Gaming FX505GM)

    Шина данных i2c - декодируем/синхронизируем с помощью осциллографа Lecroy!Скачать

    Шина данных i2c - декодируем/синхронизируем   с помощью осциллографа Lecroy!

    Установщик адресов Flash-i2cСкачать

    Установщик адресов Flash-i2c

    LCD I2C common problemСкачать

    LCD I2C common problem

    Код 10 Запуск этого устройства невозможен — как исправить?Скачать

    Код 10 Запуск этого устройства невозможен — как исправить?
Поделиться или сохранить к себе:
Технарь знаток