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

STM32 как правильно поклокать i2c

Возникают проблемы с i2c, не может выставиться START. По видимому, это связано с тем, что слейв находится в передаче и держит SDA.

Чтобы слейв отпустил шину, предлагается дать по клоку несколько тактов.

как это правильно сделать?

Выключить i2c, включить ногу клока на выход, подергать, включить снова и2с или есть простой способ этого сделать не изменяя конфигурацию ног?

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


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

Похоже нарушен протокол I2C. Реализация аппаратная? Тогда как вы пытаетесь выставить вручную старт? Если слейв в режиме передачи, то нужно дать ему закончить передачу и не подтвердить последний байт, тем самым сеанс связи закончится и можно начинать новый, выставив старт. Или я что-то я не пойму, код в студию.

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

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


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

Выключить i2c, включить ногу клока на выход, подергать, включить снова и2с или есть простой способ этого сделать не изменяя конфигурацию ног?

Я как-то так и делал.

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


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

Похоже нарушен протокол I2C.

Угу. Например, мастер в лице нашего контроллера решил перезагрузиться в момент передачи от слейва.

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

 

Методика лечения очень простая - 9 раз дёрнуть клок, не выдавая ACK. Но как это сделать, не перенастраивая ноги, я не знаю.

Может, кстати, при ошибках обмена такое же делать?.. А то я сейчас просто стоп-старт шлю, если что-то не так.

 

Так что +1 к вопросу. Только у меня LPC.

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


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

Методика лечения очень простая - 9 раз дёрнуть клок, не выдавая ACK. Но как это сделать, не перенастраивая ноги, я не знаю.

А в чём проблема с перенастройкой ног?

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


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

Некрасиво это. Как-то исторически сложилось, что настройка ног - в одном месте, а дальше её никто не меняет. И портировать драйвер на другие пины не так удобно будет...

Но это единственное препятствие :)

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


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

Некрасиво это.

Ну, если это единственная проблема, то я Вам завидую: у Вас всё очень хорошо :-)

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


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

Угу. Например, мастер в лице нашего контроллера решил перезагрузиться в момент передачи от слейва.

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

Если мастер перезагрузился, то почему бы не выдать девять клоков, а уже потом инициализировать I2C?

 

 

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


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

Если мастер перезагрузился, то почему бы не выдать девять клоков, а уже потом инициализировать I2C?

Перезагрузка мастера - не единственная причина i2c latchup-а. Он может случиться и от сильной помехи.

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


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

У меня ситуация почти постоянно возникает такая, включаем плату, начинается обмен данными с датчиком. Заливаем/запускаем прошивку JTAGом, питание с датчиков не сбрасывается, поэтому их состояние неизвестно, а контроллер с новой прошивкой начинает все сначала.

 

Получилось довольно некрасиво, но работает. Я просто думал может i2c можно аппаратно поклокать, принудительно ченить сделать чтобы байт от слейва дочитать, но пока не нашел способа.

 

  //Ïðîâåðêà ÷òî íèêòî èç ñëåéâîâ íå äåðæèò øèíó
 if( (I2C1->SR2 & I2C_SR2_BUSY) > 0 ){
   GPIO_InitTypeDef  GPIO_InitStructure;

   I2C_DeInit(I2C1);

   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
   GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
   GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_NOPULL;
   GPIO_Init(GPIOB, &GPIO_InitStructure);   

   for( j = 0; j < 10; j++ ){
     GPIOB->BSRRH = GPIO_Pin_8;
     for( i = 0; i < 0x0FFF; i++ );
     GPIOB->BSRRL = GPIO_Pin_8;
     for( i = 0; i < 0x0FFF; i++ );
   }

   API2C_Init();
 }

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


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

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

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

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

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

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

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

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

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

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