Как понять, что устройство с определенным адресом есть на шине i2c? Конечно же по биту подтверждения ACK (Acknowledge). Этот бит выставляет не мастер, а ведомое устройство. И, если ведомое устройство получило свой адрес, то оно выставит бит подтверждения (прижмет линию к земле). На отличной картинке от DI HALT это наглядно продемонстрировано.

В HAL-библиотеке есть специальная функция для проверки доступности устройства:
HAL_StatusTypeDef HAL_I2C_IsDeviceReady (I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint32_t Trials, uint32_t Timeout);
Что у нас тут есть:
- *hi2c – собственно, указатель на объект того i2c, который будет подопытным
- DevAddress – адрес устройства
- Trials – количество попыток установить соединение и получить желаемый ACK
- Timeout – и так понятно
Для полноценного сканирования всего адресного пространства на линии i2c1 достаточно написать следующий код:
HAL_StatusTypeDef ret; for(int i = 1; i < 128; i++) { ret = HAL_I2C_IsDeviceReady(&hi2c1, (uint16_t)(i << 1), 4, 100); if (ret != HAL_OK) { printf("dev_addr: 0x%02X ", i); } else if(ret == HAL_OK) { printf("-- "); } }
Мы не обращаемся по адресу 0, т.к. он может, внезапно, и ответить (гуглить: general call address in i2c).
Вывод данной программы будет достаточно простым. Не забываем сделать ретаргет для printf
Список годной литературы по i2c, расположился ниже
Статья об i2c на easyelectronics
https://www.circuitbasics.com/basics-of-the-i2c-communication-protocol/
Пошагово и с картиночками – как я люблю
Один из “алмазов” интернета снова в деле
Comment