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

I2C иногда выдает HAL_BUSY после включения


bobbjenkins

Рекомендуемые сообщения

Привет

Иногда, например сразу после прошивки контроллера (STM32F103), HAL_I2C_Mem_Read/HAL_I2C_Mem_Write возвращают HAL_BUSY. Но, если перезагрузить контроллер - все начинает работать. Иногда после перезагрузки кнопкой на плате i2c с этим i2c устройством не заводится, приходится заводить его как мопед - с нескольких перезагрузок reset'ом. Такое зависание обычно бывает, если зажать кнопку RESET и подержать секунду - сама плата с stm32 стартует нормально, а устройство I2c не работает, хотя зависания i2c случаются и при кратковременном резете.

Приаттачены настройки I2c из куба и отрывок из Datasheet I2C устройства (гироскоп/акселерометр MPU9250). Как думаете, в чем может быть причина? Подтягивающие резисторы (sda-vcc, scl-vcc), разумеется, на самой плате имеются.

Что я пробовал сделать (ничего из этого не помогло): 

1) добавлял HAL_Delay(1000) при старте STM32

2) также при старте добавил  (mpu9250 подключен к i2c1)

__HAL_RCC_I2C1_FORCE_RESET();
HAL_Delay(1000);
__HAL_RCC_I2C1_RELEASE_RESET();

3) менял настройки i2c в кубе: выставил StandardMode/1khz (хотя по спецификации, MPU9250 поддерживает i2c 4кгц).

В самом протоколе I2c, к сожалению, недостаточно хорошо разбираюсь, чтобы понять, что может происходить...

Screen Shot 2017-08-16 at 9.24.37 AM.png

Screen Shot 2017-08-16 at 9.27.57 AM.png

 

Изменено пользователем bobbjenkins
Ссылка на комментарий
Поделиться на другие сайты

  • Ответов 59
  • Создана
  • Последний ответ

Топ авторов темы

для начала посмотрите в каком случае вообще возникает HAL_BUSY. Скорее всего контроллер не получает ACK от устройства в заданный интервал времени. Такое может быть, если "абонент" хочет, чтобы его слегка "дернули", после старта. Достаточно для этого сделать просто пустой WRITE на любой прерываемой функцией HAL_I2C с таймаутом (например миллисекунду). Просто по адресу пулять например чтение статуса или ID устройства, до тех пор пока не ответит, игнорируя ошибки чтения по таймауту.

У этих акселерометров вечно такие проблемы со связью. Контроллер бывает и не виноват вовсе.

Нужно делать то, что нужно. А то, что не нужно, делать не нужно. (С) Винни Пух

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

Спасибо за ответ.

Нашел совет вот здесь: https://community.st.com/thread/15632. Судя по всему - это баг в реализации HAL для F10* контроллеров.

Рекомендуют включать тактирование i2c вручную (в обход куба) перед инициализацией gpio, + установить/сбросить бит RESET у i2c. 

Добавил вот этот код в начало main(), перед инициализацией периферии:

  /* 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 */

Пока что нет (и, надеюсь, не будет) проблем с BUSY, независимо от длительности перезагрузки.

HAL_Delay'и здесь не нужны, верно?

Update: Как оказалось, задержки нужны. Без них, при длительном зажатии кнопки Reset, HAL_BUSY появлялись. Кстати и сейчас изредка появляются, но очень редко и при зажатии ресета на несколько секунд. Но работать можно. Вот такой костыль...

Изменено пользователем bobbjenkins
Ссылка на комментарий
Поделиться на другие сайты

Сравнительное тестирование аккумуляторов EVE Energy и Samsung типоразмера 18650

Инженеры КОМПЭЛ провели сравнительное тестирование аккумуляторов EVE и Samsung популярного для бытовых и индустриальных применений типоразмера 18650. 

Для теста были выбраны аккумуляторы литий-никельмарганцевой системы: по два образца одного наименования каждого производителя – и протестированы на двух значениях тока разряда: 0,5 А и 2,5 А. Испытания проводились в нормальных условиях на электронной нагрузке EBD-USB от ZKEtech, а зарядка осуществлялась от лабораторного источника питания в режиме CC+CV в соответствии с рекомендациями в даташите на определенную модель. Подробнее>>

Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161

думаю нет

можно было попробовать просто инитки местами поменять и все в начале main()

Изменено пользователем mail_robot

Нужно делать то, что нужно. А то, что не нужно, делать не нужно. (С) Винни Пух

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

Новый аккумулятор EVE серии PLM для GSM-трекеров, работающих в жёстких условиях (до -40°С)

Компания EVE выпустила новый аккумулятор серии PLM, сочетающий в себе высокую безопасность, длительный срок службы, широкий температурный диапазон и высокую токоотдачу даже при отрицательной температуре. 

Эти аккумуляторы поддерживают заряд при температуре от -40/-20°С (сниженным значением тока), безопасны (не воспламеняются и не взрываются) при механическом повреждении (протыкание и сдавливание), устойчивы к вибрации. Они могут применяться как для автотранспорта (трекеры, маячки, сигнализация), так и для промышленных устройств мониторинга, IoT-устройств. Подробнее параметры и результаты тестов новой серии PLM по ссылке.

Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161

Оказывается, проблема еще глубже. Если кому-то интересно, в эррата есть подробное описание решения:

"I2C analog filter may provide wrong value, locking BUSY flag and preventing master mode entry" 

 

http://www.st.com/content/ccc/resource/technical/document/errata_sheet/7d/02/75/64/17/fc/4d/fd/CD00190234.pdf/files/CD00190234.pdf/jcr:content/translations/en.CD00190234.pdf#page26

 

Там приводятся 15 шагов по обходу этой проблемы

И еще вот решения:

https://electronics.stackexchange.com/questions/272427/stm32-busy-flag-is-set-after-i2c-initialization

https://electronics.stackexchange.com/questions/267972/i2c-busy-flag-strange-behaviour

Описанный в прошлом посте метод в большинстве случаев работает (иногда все-таки выдает HAL_BUSY, хоть и намного реже), поэтому пока оставлю реализацию этого кода из errata на потом, когда появится свободное время разобраться во всем этом.

Изменено пользователем bobbjenkins
Ссылка на комментарий
Поделиться на другие сайты

  • 9 месяцев спустя...

Литиевые батарейки и аккумуляторы от мирового лидера  EVE в Компэл

Компания Компэл, официальный дистрибьютор EVE Energy, бренда №1 по производству химических источников тока (ХИТ) в мире, предлагает продукцию EVE как со склада, так и под заказ. Компания EVE широко известна в странах Европы, Америки и Юго-Восточной Азии уже более 20 лет. Недавно EVE была объявлена поставщиком новых аккумуляторных элементов круглого формата для электрических моделей «нового класса» компании BMW.

Продукция EVE предназначена для самого широкого спектра применений – от бытового до промышленного. Подробнее>>

Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161

В 16.08.2017 в 16:16, bobbjenkins сказал:

Оказывается, проблема еще глубже. Если кому-то интересно, в эррата есть подробное описание решения:

Привет! У меня тоже с i2c проблема...

Проблема заключается в том , что выдается старт бит и потом через 5мкс. Сразу отпускается шина... Смотрел логическим анализатором сигнал.  Собран проект в кубе , юарт и прочее работает , а и2ц никак..

Пробовал 15 шагов , да что то проблема не решается.

У меня проц stm32f103c8t6

Что может быть лучше в радиоэлектронике, чем программирование микроконтроллеров ?

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

3 минуты назад, mail_robot сказал:

а кто роняет шину то

Стм формирует старт и через 5мкс поднимает шину , и больше ничего не происходит. Я уже чего только не пробовал. Могу показать логи

Функция передачи и приема (HAL_I2C..) постоянно возвращает 0х02.

IMG_20180604_111929.jpg

IMG_20180604_111918.jpg

Что может быть лучше в радиоэлектронике, чем программирование микроконтроллеров ?

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

Блин , пацаны , есть этот кусок кода у кого то?? Чтобы не писать регистры пол дня.

Что может быть лучше в радиоэлектронике, чем программирование микроконтроллеров ?

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

Мля, я не знаю. Ну ни разу небыло проблем с I2C на 103-ем. И на хал и без него. Там в ерате такой лес условий чтобы баг словить, что я прям не знаю как надо извернуться.

Надо поробовать поднять ноги приемника с шины и просто на подвешенных резюках снять лог. Уже сколько раз у народа глюки были на той стороне. 0х02 контроллер шины выдаст только тогда, когда ACK придет не вовремя и единица выставленная контроллером на шине при проверке не совпадет с реальным значением на шине. То есть контроллер отпускает шину открытым стоком, потом сравнивает показания с дата регистром, если не совпали, то ставит ошибку - шина занята. А она и правда с точки зрения контроллера занята, потому как кто-то насильно ее тянет к земле. Обычная мультимастерная коллизия

Кто приемник? Как его зовут?

Изменено пользователем mail_robot

Нужно делать то, что нужно. А то, что не нужно, делать не нужно. (С) Винни Пух

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

1 минуту назад, mail_robot сказал:

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

***** , я вчера это делал , честное слово ! Я думал что это датчик hdc1080 балуется , но с отключенным датчиком точно такая же проблема!

Условие старт формируется и потом сразу отпускает шину ! И потом вообще никаких признаков жизни . Хоть програмный i2c подключай ...

У меня кстати на ф407 все работает ! Только там память 24с32

5 минут назад, mail_robot сказал:

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

Да не занята шина !

Стм32 формирует условие старт и отпускает шину . На ней 3.3в четко стоит . 

Что может быть лучше в радиоэлектронике, чем программирование микроконтроллеров ?

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

ну попробуй регистрами. Для очистки совести. Проинить ноги на AF, затактируй модуль да пульни в регистр данных любое значение. Или второй I2C попробуй на те же дела

У меня как то был косяк с камнем, когда нога не хотела вести себя так, как я ей скажу. Просто все что писал туда превращалось в рандомные значения. Китайский камень, хз что с ним там натворили при производстве. Нога была PC0. Камень новый, только из коробки

Изменено пользователем mail_robot

Нужно делать то, что нужно. А то, что не нужно, делать не нужно. (С) Винни Пух

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

Заработал i2c дурацкий. Теперь датчик четко темп и влажность измеряет!

Что может быть лучше в радиоэлектронике, чем программирование микроконтроллеров ?

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

  • 2 года спустя...

Может я не в тему обращаюсь, но у меня есть проблемы по I2C библиотеки HAL. Не могу прочитать регистр акселерометра.

Но насколько я понял у меня HAL_OK  дает ошибку. Есть библиотечная функция     pData = HAL_I2C_Mem_Read(&hi2c2, 0xFA, 0x00, I2C_MEMADD_SIZE_8BIT, &pData, 1, 0x10000); делаю например так. Правильно ли это? Захожу в библиотеку и смотрю что она возвращает, вижу, что только HAL_OK. Как вытащить из нее данные?  Такой код 

uint8_t ReadData(uint16_t DevAddress, uint8_t RegAddress)

     {

        HAL_StatusTypeDef status = HAL_OK;

             uint8_t pData = 0;
    

             status = HAL_I2C_Mem_Read(&hi2c2, DevAddress, RegAddress, I2C_MEMADD_SIZE_8BIT, &pData, 1, 0x10000);

             if(status != HAL_OK)
             {
                 Led_on;
             }
            else
             {
         Led_off;
         }

           return pData;

     }
Правильно ли вытаскивать данные так?

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

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

@Uhbif , я с этой библиотекой не работал, поэтому ткнуть в нужное место не могу, но любая библиотека - это всего лишь кусок кода, который кто-то написал. Вот вы правильно делаете:

6 часов назад, Uhbif сказал:

Захожу в библиотеку и смотрю что она возвращает

и видите, что что-то не то. Возьмите да поправьте, как вам надо. И не обязательно библиотеку. Можно просто по образу и подобию свою функцию в своём коде написать. Тем более, что чтение акселерометра элементарно делается глядя в его даташит.

Кстати, когда начнёте получать значения из регистров акселерометра, не забудьте, что значения с MEMS-датчиков сильно шумят. Нужно применять фильтрацию (в простейшем случае - усреднение).

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

@Uhbif а разве трудно посмотреть что вернула функция? Ну пусть не ОК, но что тогда? Занято, таймаут, ошибка?

Ну и второй вопрос - мемрид удобнее что ли использовать?

Нужно делать то, что нужно. А то, что не нужно, делать не нужно. (С) Винни Пух

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

Мемрид для меня удобнее, я новичок, по крайней мере я понимаю, что читаю конкретный регистр. Это проще для меня.

ПО вопросу что она возвращает, значение 1, а это HAL_ERROR.

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

BMX055, если я правильно разобрался в даташите то 0xFA, также в даташите указан адрес шины 0х18 или 0х19, все эти значения попробовал результат такой же. А еще скажите, надо его после включения как то инициализировать? Я ничего не делаю, но я хочу просто прочитать нулевой регистр например и получить дефолтное значение 0хFA.

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

21 minutes ago, Uhbif said:

адрес шины 0х18 или 0х19

Надо использовать одно из этих значений. При вызове функции HAL_I2C_Mem_Read() адрес надо сдвинуть влево на 1 позицию, то есть (0x18 << 1) или (0x19 << 1). Поэтому присваиваем DevAddress = 0x30 или DevAddress = 0x32 и пользуем.

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

попробовал, но значения либо 0 при 0х30 либо 1 при 0х32. Хотя светодиод у меня гаснет, то есть можно сделать вывод что HAL_OK = Ok. Читал регистры 0х00 и 0х0F, значения по умолчанию должны быть 0xFA и 0х03 соответственно. Может еще что то надо.

uint8_t ReadData(uint16_t DevAddress, uint8_t RegAddress)

     {

        HAL_StatusTypeDef status = HAL_OK;

             uint8_t pData = 0;
                 status = HAL_I2C_Mem_Read(&hi2c2, DevAddress, RegAddress, I2C_MEMADD_SIZE_8BIT, &pData, 1, 0x10000)

  if(status != HAL_OK)
             {
                 Led_on;
             }
            else
             {
         Led_off;
         }

           return pData;

     }

 

while(1)

{

ID_Acc=ReadData(0x30,0x00);

дальше вывод в программу терминал виртуального ком-порта.

}

}

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

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

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

Гость
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Ответить в этой теме...

×   Вставлено с форматированием.   Восстановить форматирование

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

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

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

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

Загрузка...
  • Последние посетители   0 пользователей онлайн

    • Ни одного зарегистрированного пользователя не просматривает данную страницу

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