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

STM32L151 I2C slave. Не пойму как это работает.

В настройках не нашел:

 

/* 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 из памяти?

Изменено пользователем Димон Безпарольный

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


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

Как контроллер понимает что он 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.

 

 

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


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

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)

Изменено пользователем Димон Безпарольный

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


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

Сделал машину состояний. Стабильно начало работать только после того, как я обеспечил обработку ошибок.

 

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 пока не могу.

Изменено пользователем IgorKossak
[codebox] для длинного кода. [code]-для короткого!!!

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


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

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

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

Гость
Ответить в этой теме...

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

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

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

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

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

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