понеділок, 22 січня 2018 р.

STM32: Сканер пристроїв на I2C шині (оновлено 24.12.2020)

update 24.12.2020: статтю оновлено до сучасних реалій. Додано відео-посібник.

Передмова

Розбирався я з шиною I2C, точніше хотів під'єднати сенсор освітлення TSL2561, який працює по шині I2C. І щоб зрозуміти, як тим сенсором скористуватись, довелось розбиратись з шиною I2C. Поки розбирався, вивчав, як воно все то працює і як наслідок написав невеличку програмку для сканування адрес пристроїв які "висять" на шині I2C. Зручно перевіряти адреси пристроїв, бо не завжди впевнений в правильності адреси, або переконатись чи взагалі, той, чи інший пристрій, відгукується на запит. Бо був випадок. Ніяк не міг запустити на іншому проекті пов'язаному з ESP8266 сенсор si7021. Як виявилось, він взагалі не реагує на запити. Більш за все бракований, або зіпсовався, коли припаював дроти до нього.

Створюємо проект в STM32CubeIDE

Створюємо новий проект в STM32CubeIDE. Обираємо свій MCU. Позначаємо потрібні піни. Я використовую MCU STM32F103C8T6, тож приклад буде для нього, але це не принципово. У вас може бути будь який інший MCU STM32.

Налаштування проекту
  1. Оберемо шину: I2C1 (або I2C2);
  2. Назначимо, що тактуватись будемо від зовнішнього кварцу: Crystal/Ceramic Resonator (не обов'язково, можна залишити як є, тактуватись буде, в цьому випадку, від внутрішнього генератора мікроконтролера);
  3. Оберемо пристрій Debug по якому заливаємо прошивку та налагоджуємо програму: Serial Wire;
  4. Оберемо послідовну шину: USART2 (можна інший, який зручно вам).
З налаштуваннями це все. Можна генерувати проект "Ctrl+S".

Пишемо програму

Відкриваємо в дереві проекту файл "main.c". В визначених, для користувача/розробника, ділянках додаємо такий код.

Додаємо до проекту бібліотеку "stdio.h", вона нам згодиться для друку повідомлень в Serial Monitor за допомоги функції "printf()":
/* USER CODE BEGIN Includes */
#include <stdio.h>
/* USER CODE END Includes */

Робимо редирект потоку до UART за допомоги переназначення системної функції "write":
/* USER CODE BEGIN 0 */
int _write(int file, char *ptr, int len)
{
	HAL_UART_Transmit(&huart2, (uint8_t *) ptr, len, HAL_MAX_DELAY);
	return len;
}
/* USER CODE END 0 */

Тепер сама програма сканеру шини I2C:
/* USER CODE BEGIN WHILE */
  while (1)
  {
	  printf("\r\nStart scanner I2C bus\r\n");

	  for (int i = 0; i < 128; ++i)
	  {
		uint16_t address = i << 1;

		if (HAL_I2C_IsDeviceReady(&hi2c1, address, 1, HAL_MAX_DELAY) == HAL_OK)
		{
			printf("Address: 0x%X\r\n", address >> 1);
		}
	  }

	  printf("End test I2C bus\r\n");
	  HAL_Delay(5000);
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */

Компілюємо, заливаємо. Підключаємо до шини I2C MCU ваші пристрої I2C, та конвертер USART2USB до зазначеного USART по такій схемі (шпильки MCU мають відповідати назначеним шпилькам в STM32CubeIDE):
Схема підключення

В будь якій термінальній програмі слухаємо COM порт до якого підключений USART2USB конвертер.  Подаємо живлення на MCU і в термінальній програмі бачимо результат сканування:

Результат роботи програми

Я використовую вбудований в STM32CubeIDE термінал. "З коробки" Serial Monitor не встановлено, потрібно встановити додатково з репозиторію. Як це зробити, описано в статті.

Відео-посібник



2 коментарі:

  1. Давайте посилання на ріплейсі на свої статті, думаю тамошнім користувачам буде дуже цікаво. Chemist.

    ВідповістиВидалити
  2. Дякую за пропозицію, скористаюсь порадою.

    ВідповістиВидалити