最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

Can you change the slave i2c address during execution on a stm32 board? - Stack Overflow

programmeradmin0浏览0评论

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 badges
Add a comment  | 

1 Answer 1

Reset to default 0

I 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();
                }
            }
        }
    }
}
发布评论

评论列表(0)

  1. 暂无评论