Работа с шиной I2C (TWI)

Функции этого раздела предназначены для обмена данными с периферийными устройствами по двухпроводному интерфейсу I2C (Inter-Integrated Circuit), также известному как TWI (Two-Wire Interface).

К СВЕДЕНИЮ

Доступность I2C-шин на Repka Pi 3 (SoC Allwinner H5):

Константа Интерфейс Пин SDA Пин SCL Доступен в вариантах распиновки
I2C1_BUS I2C1 PA12 (пин 3) PA11 (пин 5) 2-9
I2C2_BUS I2C2 PA19 (пин 27) PA18 (пин 28) 4

Доступность I2C-шин на Repka Pi 4 (SoC Allwinner H6):

Константа Интерфейс Пин SDA Пин SCL Доступен в вариантах распиновки
I2C1_BUS I2C1 PD26 (пин 3) PD25 (пин 5) 2-9
I2C2_BUS I2C2 PD24 (пин 27) PD23 (пин 28) 4
I2C3_BUS I2C3 PH6 (пин 21) PH5 (пин 19) 11

i2cSetup() #

Инициализирует функцию передачи данных с использованием I2C интерфейса.

Синтаксис #

int i2cSetup(const int i2cBus, const int devId)

Параметры #

i2cBus - дескриптор порта I2C, доступные значения:

  • I2C1_BUS - порт I2C1.

  • I2C2_BUS - порт I2C2.

  • I2C3_BUS - порт I2C3 (I2CS на Repka Pi 4).

devId - Адрес slave-устройства на шине I2C.

Возврат #

Файловый дескриптор порта I2C.

i2cRelease() #

Высвобождает ресурсы задействованные функцией передачи данных с использованием I2C интерфейса.

Синтаксис #

int i2cRelease(int fd)

Параметры #

fd - Файловый дескриптор порта I2C.

Возврат #

Ничего.

i2cRead() #

Получает данные с устройства напрямую (без выполнения транзакции с регистрами).

Синтаксис #

int i2cRead(int fd)

Параметры #

fd - Файловый дескриптор порта I2C.

Возврат #

Данные полученные от устройства.

i2cReadReg8() #

Получает данные из 8-ми битного регистра устройства

Синтаксис #

int i2cReadReg8(int fd, int reg)

Параметры #

fd - Файловый дескриптор порта I2C.

reg - адрес 8-ми битного регистра.

Возврат #

Данные полученные из регистра устройства.

i2cReadReg16() #

Получает данные из 16-ти битного регистра устройства

Синтаксис #

int i2cReadReg16(int fd, int reg)

Параметры #

fd - Файловый дескриптор порта I2C.

reg - адрес 16-ти битного регистра.

Возврат #

Данные полученные из регистра устройства.

i2cWrite() #

Записывает данные в устройство напрямую (без выполнения транзакции с регистрами).

Синтаксис #

int i2cWrite(int fd, int data)

Параметры #

fd - Файловый дескриптор порта I2C.

data - данные передаваемые устройству.

Возврат #

0 при успешном выполнении, или отрицательное значение в случае ошибки.

i2cWriteReg8() #

Записывает данные в 8-ми битный регистр устройства.

Синтаксис #

int i2cWriteReg8(int fd, int reg, int data)

Параметры #

fd - Файловый дескриптор порта I2C.

reg - адрес 8-ми битного регистра.

data - данные передаваемые устройству.

Возврат #

0 при успешном выполнении, или отрицательное значение в случае ошибки.

i2cWriteReg16() #

Записывает данные в 16-ти битный регистр устройства.

Синтаксис #

int i2cWriteReg16(int fd, int reg, int data)

Параметры #

fd - Файловый дескриптор порта I2C.

reg - адрес 16-ти битного регистра.

data - данные передаваемые устройству.

Возврат #

0 при успешном выполнении, или отрицательное значение в случае ошибки.

Пример использования функций I2C: Универсальный сканер шин #

Этот пример демонстрирует, как использовать функции i2cSetup, i2cRead и i2cRelease для обнаружения устройств на всех доступных шинах I2C.

Что делает этот пример:

  • Он последовательно пытается просканировать шины I2C1_BUS, I2C2_BUS и I2C3_BUS.
  • Если какая-либо шина недоступна в текущем варианте распиновки (или отключена в системе), программа сообщит об этом и корректно перейдет к следующей.
  • Если вы подключите к любой из шин датчик или другой I2C-модуль, сканер обнаружит его и покажет его адрес в шестнадцатеричном формате.
  • Это надежный способ проверить, "видит" ли система ваше I2C-устройство.

Код (i2c_scanner.c)

#include <stdio.h>
#include <stdlib.h>
#include "wiringRP.h"
#include "wire.h"

/**
 * @brief Сканирует одну указанную шину I2C на наличие устройств.
 * @param bus_id Номер шины для сканирования (I2C1_BUS, I2C2_BUS, etc.)
 */
void scan_i2c_bus(int bus_id) {
    char bus_name[16];
    sprintf(bus_name, "I2C%d_BUS", bus_id + 1);

    printf("\n--- Сканирование шины %s ---\n", bus_name);

    // Предварительная проверка доступности шины
    int test_fd = i2cSetup(bus_id, 0x08); // Пробуем открыть с любым адресом
    if (test_fd < 0) {
        printf("Результат: Шина недоступна в текущей конфигурации.\n");
        return;
    }
    i2cRelease(test_fd);

    int devices_found = 0;
    printf("Поиск устройств...\n");
    for (int addr = 0x03; addr < 0x78; addr++) {
        int fd = i2cSetup(bus_id, addr);
        if (fd < 0) continue;

        // Используем i2cRead для реальной проверки ответа от устройства.
        // Функция вернет -1, если устройство не ответило (NACK).
        if (i2cRead(fd) != -1) {
            printf("  - Найдено устройство по адресу: 0x%02X\n", addr);
            devices_found++;
        }
        i2cRelease(fd);
    }

    if (devices_found == 0) {
        printf("Устройства не найдены.\n");
    } else {
        printf("Сканирование завершено. Найдено %d устройств(о).\n", devices_found);
    }
}

int main() {
    if(setupWiringRP(WRP_MODE_SUNXI) < 0) {
        fprintf(stderr, "Критическая ошибка: не удалось инициализировать библиотеку wiringRP!\n");
        exit(EXIT_FAILURE);
    }

    printf("--- Универсальный сканер шин I2C для Repka Pi ---\n");

    // Последовательно сканируем все три шины
    scan_i2c_bus(I2C1_BUS);
    scan_i2c_bus(I2C2_BUS);
    scan_i2c_bus(I2C3_BUS);

    releaseWiringRP();
    return 0;
}

1454 просмотров0 комментариев

Комментарии (0)

Для участия в обсуждении Вы должны быть авторизованным пользователем
Разделы

Навигация

ВойтиРегистрация