Функции этого раздела предназначены для обмена данными с периферийными устройствами по двухпроводному интерфейсу 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;
}