Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: STM32L151 I2C slave. Не пойму как это работает.
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
Димон Безпарольный
В настройках не нашел:

Код
/* I2C2 init function */
void MX_I2C2_Init(void)
{

  hi2c2.Instance = I2C2;
  hi2c2.Init.ClockSpeed = 100000;
  hi2c2.Init.DutyCycle = I2C_DUTYCYCLE_2;
  hi2c2.Init.OwnAddress1 = 144;
  hi2c2.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
  hi2c2.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
  hi2c2.Init.OwnAddress2 = 0;
  hi2c2.Init.GeneralCallMode = I2C_GENERALCALL_ENABLE;
  hi2c2.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
  HAL_I2C_Init(&hi2c2);

}


Как контроллер понимает что он Slave? Как организовать прерывание при совпадении SlaveAdr? Как организовать передачу с помощью DMA из памяти?
alag57
Цитата(Димон Безпарольный @ Jun 15 2017, 22:07) *
Как контроллер понимает что он Slave?


RM0038
Reference manual:
26.3.1 Mode selection
By default, it operates in slave mode. The interface automatically switches from slave to
master, after it generates a START condition and from master to slave, if an arbitration loss
or a Stop generation occurs, allowing multimaster capability.

Димон Безпарольный
Цитата(alag57 @ Jun 16 2017, 08:02) *
RM0038
Reference manual:

Да, я это уже прочитал. Спасибо. Просто не знаю с чего начать писать код. Примеров в Сети не нашел.

Нужен I2C slave со стратегией:
- ответ на Slave ADR и передача Slave Transmit 16байт.

Куб конечно помогает сконфигурировать интерфейс но кто устанавливает hi2c2.Mode = HAL_I2C_MODE_SLAVE; не пойму.

Может где есть пример?

Попробую начать долбить slave адресом в чип и контролировать установку бита Bit 1 ADDR: Address sent (master mode)/matched (slave mode)
Димон Безпарольный
Сделал машину состояний. Стабильно начало работать только после того, как я обеспечил обработку ошибок.

CODE
void I2C2_EV_IRQHandler(void)
{
/* USER CODE BEGIN I2C2_EV_IRQn 0 */

switch(I2C_GetLastEvent(I2C2))
{
//SLAVE Receive
case I2C_EVENT_SLAVE_RECEIVER_ADDRESS_MATCHED: //EV1 0x00020002
{
I2C_clear_ADDR();
//CntTR = 0;
break;
}
case I2C_EVENT_SLAVE_BYTE_RECEIVED: //EV2 0x00020040
{
//Read it, so no one is waiting, clears BTF if necessary. Read DR
Dum1 = I2C2->DR;
break;
}
case I2C_EVENT_SLAVE_STOP_DETECTED: //End of receive, EV4 0x00000010
{
//if(I2C_GetFlagStatus(I2C_FLAG_ADDR) == SET) {I2C_clear_ADDR();} //----------------
volatile int State; //Clear STOPF
State = I2C2->SR1; //
I2C2->CR1 |= 1; //PE-----------------------
break;
}
//Transmit
case I2C_EVENT_SLAVE_TRANSMITTER_ADDRESS_MATCHED: //EV1 0x00060082
{
I2C_clear_ADDR();
I2C2->DR = Dum1; //Send first byte
break;
}
case I2C_EVENT_SLAVE_BYTE_TRANSMITTED: //EV3 0x00060084
case I2C_EVENT_SLAVE_BYTE_TRANSMITTING: //-----------------------------
{
//Read flag and write next byte to clear BTF if present
I2C_GetFlagStatus(I2C_FLAG_BTF);
I2C2->DR = ++CntTR;
break;
}
//Alternative Cases for address match
case I2C_EVENT_SLAVE_RECEIVER_SECONDADDRESS_MATCHED: {break;}//EV1 0x00820000
case I2C_EVENT_SLAVE_TRANSMITTER_SECONDADDRESS_MATCHED: {break;}//EV1 0x00860080
//How the FUCK did you get here? I should probably raise some error, but fuck it, it's late
default: {break;}
}
/* USER CODE END I2C2_EV_IRQn 0 */
//HAL_I2C_EV_IRQHandler(&hi2c2);
/* USER CODE BEGIN I2C2_EV_IRQn 1 */

/* USER CODE END I2C2_EV_IRQn 1 */
}


Код
void I2C2_ER_IRQHandler(void)
{
  /* USER CODE BEGIN I2C2_ER_IRQn 0 */
    //Dum1 = I2C2->SR1;
  /* USER CODE END I2C2_ER_IRQn 0 */
  //HAL_I2C_ER_IRQHandler(&hi2c2);
  /* USER CODE BEGIN I2C2_ER_IRQn 1 */
    GPIOB->BSRR = 1<<13;
    I2C2->SR1 = ~((1<<10) & ((uint32_t)0x0000FFFF)); //AF Clear    
    //I2C2->CR2 |= I2C_CR2_ITEVTEN;
    //I2C2->CR2 |= I2C_CR2_ITBUFEN;
    //I2C2->CR2 |= I2C_CR2_ITERREN;

  /* USER CODE END I2C2_ER_IRQn 1 */
}


При ошибках загорается светодиод. В цикле 1с он гасится. Так вот. Ошибка возникает только одна - Ack failure. Думаю что она возникает когда мастер выдает NACK на последнем байте. Других мыслей нет.

Пока обработчик принимает один байт и выдает нумерованные байты. На мастере вызывается функция

Код
HAL_I2C_Mem_Read(&hi2c1, 0x33<<1, 0x55, 1, &GAS_Data[0], 20, 200);


Она передает Slave+W, Байт адреса, повторный старт, Slave+R и читает 20байт. Кажется так.

Работает исправно. Но избавится от Ack failure пока не могу.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.