It’s all in the title
I want to be able to change the device's i2c slave address upon reception of a certain i2c command. I'm currently using a nucleo 144 f207gz.
I've been trying to achieve this without success by calling HAL_I2C_Init after changing the OwnAddress1 field of the i2c handle.Init, I tried to call DeInit then Init, but all without success...
So is there a way to achieve this ? If so, how?
It’s all in the title
I want to be able to change the device's i2c slave address upon reception of a certain i2c command. I'm currently using a nucleo 144 f207gz.
I've been trying to achieve this without success by calling HAL_I2C_Init after changing the OwnAddress1 field of the i2c handle.Init, I tried to call DeInit then Init, but all without success...
So is there a way to achieve this ? If so, how?
Share Improve this question asked Feb 5 at 20:47 grybouilligrybouilli 4205 silver badges15 bronze badges1 Answer
Reset to default 0I finally managed to get something working. I was using interrupts and doing it wrong : the DeInit - Init has to be done in the RXCallback function. Here is a minimal working example:
Using interrupts
// [ CubeMX generated code ... ]
uint8_t i2c_slave_address = 0x40;
uint8_t received_data [2]= {0};
HAL_StatusTypeDef Change_I2C_Address(uint8_t new_address)
{
HAL_StatusTypeDef ret;
HAL_I2C_DeInit(m_i2c_handle);
hi2c1.Init.OwnAddress1 = addr << 1;
ret = HAL_I2C_Init(m_i2c_handle);
return ret;
}
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_I2C1_Init();
/* Infinite loop */
/* USER CODE BEGIN WHILE */
HAL_I2C_Slave_Receive_IT(&hi2c1, received_data, 2);
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
}
// [ CubeMX generated code ... ]
void HAL_I2C_SlaveRxCpltCallback(I2C_HandleTypeDef *hi2c) {
if (received_data[0] == 0xA5)
{ // Command to change address
if(Change_I2C_Address(received_data[1]) != HAL_OK)
{
Error_Handler();
}
received_data[0] = 0;
}
else if (received_data[0] == 0x05)
{ // Command to blink
HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, 1);
HAL_Delay(5000);
HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, 0);
received_data[0] = 0;
}
HAL_I2C_Slave_Receive_IT(&hi2c1, received_data, 2);
}
Using blocking mode
The main should look like this:
HAL_StatusTypeDef Change_I2C_Address(uint8_t new_address) {
HAL_StatusTypeDef ret;
HAL_I2C_DeInit(m_i2c_handle);
hi2c1.Init.OwnAddress1 = addr << 1;
ret = HAL_I2C_Init(m_i2c_handle);
return ret;
}
/* Main Function */
int main(void) {
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_I2C1_Init();
while (1) {
if (HAL_I2C_Slave_Receive(&hi2c1, received_data, 2, HAL_MAX_DELAY) == HAL_OK) {
if (received_data[0] == 0xA5) { // Command to change address
if(Change_I2C_Address(received_data[1]) != HAL_OK)
{
Error_Handler();
}
}
}
}
}