Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: I2C STM32F103
Форум разработчиков электроники ELECTRONIX.ru > Интерфейсы > Форумы по интерфейсам
MiklPolikov
Интерфейс I2C МК STM32F103.
Пытаюсь подружить с пирометром MLX90614

Ни как не могу понять: После передачи адрес(W) + команда , нужно делать Stop Condition ? Или сразу ещё один Start Condition и дальше опять адрес( R ) ?
ViKo
Сразу старт и адрес. На картинке же показано. Всяко бывает.
gerber
Stop не нужен, это так называемый Repeated Start Condition, часто используется для продолжения обмена без освобождения шины.
Сергей Борщ
В однозадачной системе с одним ведущим (master) на шине - без разницы. Можно передавать stop, можно не передавать. Единственный случай, когда обязательно нужно передать stop - это при записи в память (там stop запускает процесс записи). Во всех остальных случаях вместо stop-start можно передавать start, это будет т.н. repeated start. В многозадачной системе или при наличии нескольких независимых ведущих в данном случае нужно обязательно передавать repeated start, который гарантирует, что между записью адреса и чтением никто не влезет на шину и не перепишет установленный адрес.
MiklPolikov
Цитата(Сергей Борщ @ Mar 17 2018, 12:12) *
нужно обязательно передавать repeated start, который гарантирует, что между записью адреса и чтением никто не влезет на шину и не перепишет установленный адрес.

Полагаю, это мой случай. Т.к. передача команды это адрес в MLX90614 , а следующее за ним чтение - это чтение по этому адресу.
Так вот: если делать старт-стоп, то MLX90614 не работает.
А если пытаться передавать повторный старт из STM32F103 , то не работает он , а именно при последующей передаче адреса не выставляет бит "адрес передан". Да и в документации на МК написано, что "старт нужно передавать при сброшенном бите BUSY" , а когда обмен идёт, этот бит уже стоит. Хотя в STM32F429 этот же код работал, и там такой же I2C !

Может такое быть, что I2C в МК не умет передавать повторный старт ?
Сергей Борщ
QUOTE (MiklPolikov @ Mar 17 2018, 13:58) *
Может такое быть, что I2C в МК не умет передавать повторный старт ?
Нет, не может. Для него что повторный, что обычный старт - без разницы.
QUOTE (MiklPolikov @ Mar 17 2018, 13:58) *
Хотя в STM32F429 этот же код работал, и там такой же I2C !
Буквально позавчера столкнулся с такой же фигней - код, работавший на 407, отказался работать на 107. Код на прерываниях, естественно, никакого ожидания сброса BUSY в цикле в нем нет. Посмотрел лог. анализатором - увидел посылки по 14 бит (?) с совершенно не теми данными, которые я запихивал в регистр, плюнул, написал за час I2C ногодрыгом (благо мне при старте программы надо один раз считать MAC из внешней памяти). Тратить время на поиски блох в данном проекте посчитал непродуктивным.
gerber
Цитата(MiklPolikov @ Mar 17 2018, 14:58) *
А если пытаться передавать повторный старт из STM32F103 , то не работает он , а именно при последующей передаче адреса не выставляет бит "адрес передан". Да и в документации на МК написано, что "старт нужно передавать при сброшенном бите BUSY" , а когда обмен идёт, этот бит уже стоит.

В 103 довольно капризный I2C, требующий точного соблюдения всей циклограммы, расписанной в даташите событийно (EV5-EV9), и правильной очистки статусных бит, как написано. Вот псевдо-код (псевдо - потому, что на бесконечных циклах ожидания), работающий на 103 в режиме мастера, с repeated start, без прерываний (чтение из регистра устройства с I2C адресом 0):

Код
void CI2C1::ReadByte(u8 nOffset, u8* pData)
{
  u8 data;
  u16 sr1, sr2;

  I2C1->CR1 |= I2C_CR1_START;
  while (!(I2C1->SR1 & I2C_SR1_SB));

  I2C1->DR = 0x00;
  while (!(I2C1->SR1 & I2C_SR1_ADDR));
  sr1 = I2C1->SR1;
  sr1 = sr1; // prevent warning
  sr2 = I2C1->SR2;
  sr2 = sr2; // prevent warning
  
  I2C1->DR = nOffset;
  while (!(I2C1->SR1 & I2C_SR1_BTF));

  I2C1->CR1 |= I2C_CR1_START; // repeated start
  while (!(I2C1->SR1 & I2C_SR1_SB));

  I2C1->DR = 0x01;
  while (!(I2C1->SR1 & I2C_SR1_ADDR));
  sr1 = I2C1->SR1;
  sr2 = I2C1->SR2;

  while (!(I2C1->SR1 & I2C_SR1_RXNE));
  data = I2C1->DR;  
  I2C1->CR1 |= I2C_CR1_STOP;
  *pData = data;
}
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2024 Invision Power Services, Inc.