Сделал машину состояний. Стабильно начало работать только после того, как я обеспечил обработку ошибок.
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 пока не могу.