ПРЕДУПРЕЖДЕНИЕ
Для работы с функциями библиотеки подключите ее в Вашу программу с помощью инструкции #include <wire.h>
Подробнее о подключении библиотеки в пользовательскую программу →
Библиотека WiringRP позволяет обмениваться данными с периферийными устройствами по двухпроводному интерфейсу I2C (Inter-Integrated Circuit), также известному как TWI (Two-Wire Interface).
Список I2C-интерфейсов для Repka Pi 3 #
Идентификатор | Интерфейс | SDA | SCL | Вариант распиновки |
|---|---|---|---|---|
| I2C1 |
|
| 2 - 8 |
| I2C2 |
|
| 4 |
Список I2C-интерфейсов для Repka Pi 4 #
Идентификатор | Интерфейс | SDA | SCL | Вариант распиновки |
|---|---|---|---|---|
| I2C1 |
|
| 2 - 4 и 7 - 9 |
| I2C2 |
|
| 4 |
| I2C3 |
|
| 11 |
Список I2C-интерфейсов для Repka Pi 5 #
Идентификатор | Интерфейс | SDA | SCL | Вариант распиновки |
|---|---|---|---|---|
| I2C2 |
|
| 4 и 8 |
| I2C4 |
|
| 8 |
| I2C5 |
|
| 8 |
| I2C7 |
|
| 8 |
| I2C8 |
|
| 2, 3, 4, 7 и 8 |
i2cSetup() #
Инициализирует указанный I2C-интерфейс и подключенное к нему ведомое устройство.
Синтаксис #
int i2cSetup(const int i2cBus, const int devId)
Параметры #
i2cBus - идентификатор I2C-интерфейса.
Доступные значения для каждой версии Repka Pi отображены в таблицах (столбец “идентификатор”).
devId - адрес ведомого устройства.
Возвращаемое значение #
Файловый дескриптор I2C-интерфейса или отрицательное значение в случае ошибки.
i2cRelease() #
Освобождает ресурсы задействованные при работе с I2C-интерфейсом.
Синтаксис #
int i2cRelease(int fd)
Параметры #
fd - файловый дескриптор I2C-интерфейса.
Возвращаемое значение #
Ничего.
i2cRead() #
Возвращает байт данных, полученный от ведомого устройства из I2C-интерфейса.
Синтаксис #
int i2cRead(int fd)
Параметры #
fd - файловый дескриптор I2C-интерфейса.
Возвращаемое значение #
Байт данных, полученный от ведомого устройства.
i2cReadReg8() #
Возвращает значение 8-битного регистра ведомого устройства.
Синтаксис #
int i2cReadReg8(int fd, int reg)
Параметры #
fd - файловый дескриптор I2C-интерфейса.
reg - адрес 8-битного регистра ведомого устройства.
Возвращаемое значение #
Значение 8-битного регистра ведомого устройства.
i2cReadReg16() #
Возвращает значение 16-битного регистра ведомого устройства.
Синтаксис #
int i2cReadReg16(int fd, int reg)
Параметры #
fd - файловый дескриптор I2C-интерфейса.
reg - адрес 16-битного регистра ведомого устройства.
Возвращаемое значение #
Значение 16-битного регистра ведомого устройства.
i2cWrite() #
Выполняет передачу данных на ведомое устройство с помощью I2C-интерфейса.
Синтаксис #
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 при успешном выполнении или отрицательное значение в случае ошибки.
Пример использования: Подключение датчика давления и температуры BME280 #
Этот пример демонстрирует, как использовать функции библиотеки для настройки и получения данных от датчика давления и температуры BME280 по интерфейсу I2C.
Что выполняет этот пример:
- Подключение к ведомому устройству по указанному I2C-интерфейсу.
- Чтение калибровочных коэффициентов для преобразования значения температуры.
- Отображение текущей температуры окружающей среды в режиме реального времени.
Схема подключения (на примере Repka Pi 5):
![]() |
ПРЕДУПРЕЖДЕНИЕ
Данный пример может быть запущен ТОЛЬКО на определенных вариантах распиновки GPIO-разъема. Подробнее - в таблицах.
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <stdint.h>
#include "wiringRP.h"
#include "wire.h"
/*
* Пример предназначен для иллюстрации возможности подключения устройств по интерфейсу I2C1 на Repka Pi 3.
* В данном примере подключается датчик давления и температуры BME280.
* Опрос датчика происходит с интервалом в 1 секунду.
*/
// Глобальные переменные и константы
int i2c1_fd; // Файловый дескриптор интерфейса I2C1
// Глобальные переменные и константы BME280
const int PORT_I2C = I2C1_BUS;
const uint8_t BME280_ADR = 0x76;
const uint8_t BME280_CHIP_ID = 0x60;
const uint8_t REG_CHIP_ID = 0xD0;
const uint8_t REG_CTRL_MEAS = 0xF4;
const uint8_t REG_CONFIG = 0xF5;
const uint8_t REG_DATA_START = 0xF7;
const uint8_t REG_CALIB_START = 0x88;
const uint8_t REG_CALIB_END = 0xA1;
static uint8_t raw_data[32];
static uint8_t status;
static int T1, T2, T3;
// Чтение диапазона регистров датчика BMP280
static bool loadReg(uint8_t firstReg, uint8_t lastReg) {
for (uint8_t ind = firstReg; ind <= lastReg; ind++) {
raw_data[ind - firstReg] = i2cReadReg8(i2c1_fd, ind);
if (raw_data[ind - firstReg] < 0) {
printf("Регистр 0x%02X не доступен! Идентификатор интерфейса I2C: %d.\n", ind, PORT_I2C);
return false;
}
}
return true;
}
void setup() {
// Инициализация библиотеки WiringRP
// Используется режим нумерации SUNXI
if (setupWiringRP(WRP_MODE_SUNXI) < 0) {
goto error;
}
// Инициализация пользовательских объектов
i2c1_fd = i2cSetup(PORT_I2C, BME280_ADR);
if (i2c1_fd < 0) {
goto error;
}
delay(100);
// Чтение идентификатор датчика
unsigned int chipId = i2cReadReg8(i2c1_fd, REG_CHIP_ID);
if (chipId != BME280_CHIP_ID) {
printf("Не удалось получить правильный идентификатор датчика! Ожидалось значение 0x%02X, а получено 0x%02X.\n", BME280_CHIP_ID, chipId);
goto error;
}
// Чтение регистров калибровочных коэффициентов
if (!loadReg(REG_CALIB_START, REG_CALIB_END)) {
printf("Не удалось прочитать калибровочные коэффициенты.\n");
goto error;
}
// Формирование калибровочных коэффициентов, согласно datasheet BMP280
T1 = raw_data[0] + (raw_data[1] << 8);
T2 = raw_data[2] + (raw_data[3] << 8);
T3 = raw_data[4] + (raw_data[5] << 8);
/* Запись конфигурации в управляющие регистры датчика.
* Конфигурация устанавливает режим работы, частоту и точность измерений.
* Регистр CTRL_MEAS (0xF4):
* - osrs_t = x1 (0b001),
* - osrs_p = x1 (0b001),
* - mode = normal (0b11).
* Итоговая команда: 0b00100111 = 0x27
*/
i2cWriteReg8(i2c1_fd, REG_CTRL_MEAS, 0x27);
/* Регистр CONFIG (0xF5):
* - t_sb = 1000ms (0b101),
* - filter = off (0b000).
* Итоговая команда: 0b10100000 = 0xA0
*/
i2cWriteReg8(i2c1_fd, REG_CONFIG, 0xA0);
return;
error:
onClose(2);
}
void loop() {
// Основной цикл программы
// Чтение регистров текущего значения температуры
if (!loadReg(REG_DATA_START, REG_DATA_START + 5)) {
printf("Не удалось прочитать значение температуры. Повтор попытки через 1 секунду...\n");
} else {
// Расчет по предустановленным значениям, согласно datasheet BMP280
int adc_P = (raw_data[0] << 12) | (raw_data[1] << 4) | (raw_data[2] >> 4);
int adc_T = (raw_data[3] << 12) | (raw_data[4] << 4) | (raw_data[5] >> 4);
int var1_t = (adc_T / 16384.0 - T1 / 1024.0) * T2;
int var2_t = ((adc_T / 131072.0 - T1 / 8192.0) * (adc_T / 131072.0 - T1 / 8192.0)) * T3;
int t_fine = var1_t + var2_t;
int temperature = t_fine / 5120.0;
printf("[BME280] Температура: %d °C\n", temperature);
}
delay(1000);
}
ONDESTROY() {
i2cRelease(i2c1_fd);
// Завершение работы библиотеки
releaseWiringRP();
// Выход из программы
exit(0);
}
MAIN_WIRINGRP();
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <stdint.h>
#include "wiringRP.h"
#include "wire.h"
/*
* Пример предназначен для иллюстрации возможности подключения устройств по интерфейсу I2C1 на Repka Pi 4.
* В данном примере подключается датчик давления и температуры BME280.
* Опрос датчика происходит с интервалом в 1 секунду.
*/
// Глобальные переменные и константы
int i2c1_fd; // Файловый дескриптор интерфейса I2C1
// Глобальные переменные и константы BME280
const int PORT_I2C = I2C1_BUS;
const uint8_t BME280_ADR = 0x76;
const uint8_t BME280_CHIP_ID = 0x60;
const uint8_t REG_CHIP_ID = 0xD0;
const uint8_t REG_CTRL_MEAS = 0xF4;
const uint8_t REG_CONFIG = 0xF5;
const uint8_t REG_DATA_START = 0xF7;
const uint8_t REG_CALIB_START = 0x88;
const uint8_t REG_CALIB_END = 0xA1;
static uint8_t raw_data[32];
static uint8_t status;
static int T1, T2, T3;
// Чтение диапазона регистров датчика BMP280
static bool loadReg(uint8_t firstReg, uint8_t lastReg) {
for (uint8_t ind = firstReg; ind <= lastReg; ind++) {
raw_data[ind - firstReg] = i2cReadReg8(i2c1_fd, ind);
if (raw_data[ind - firstReg] < 0) {
printf("Регистр 0x%02X не доступен! Идентификатор интерфейса I2C: %d.\n", ind, PORT_I2C);
return false;
}
}
return true;
}
void setup() {
// Инициализация библиотеки WiringRP
// Используется режим нумерации SUNXI
if (setupWiringRP(WRP_MODE_SUNXI) < 0) {
goto error;
}
// Инициализация пользовательских объектов
i2c1_fd = i2cSetup(PORT_I2C, BME280_ADR);
if (i2c1_fd < 0) {
goto error;
}
delay(100);
// Чтение идентификатор датчика
unsigned int chipId = i2cReadReg8(i2c1_fd, REG_CHIP_ID);
if (chipId != BME280_CHIP_ID) {
printf("Не удалось получить правильный идентификатор датчика! Ожидалось значение 0x%02X, а получено 0x%02X.\n", BME280_CHIP_ID, chipId);
goto error;
}
// Чтение регистров калибровочных коэффициентов
if (!loadReg(REG_CALIB_START, REG_CALIB_END)) {
printf("Не удалось прочитать калибровочные коэффициенты.\n");
goto error;
}
// Формирование калибровочных коэффициентов, согласно datasheet BMP280
T1 = raw_data[0] + (raw_data[1] << 8);
T2 = raw_data[2] + (raw_data[3] << 8);
T3 = raw_data[4] + (raw_data[5] << 8);
/* Запись конфигурации в управляющие регистры датчика.
* Конфигурация устанавливает режим работы, частоту и точность измерений.
* Регистр CTRL_MEAS (0xF4):
* - osrs_t = x1 (0b001),
* - osrs_p = x1 (0b001),
* - mode = normal (0b11).
* Итоговая команда: 0b00100111 = 0x27
*/
i2cWriteReg8(i2c1_fd, REG_CTRL_MEAS, 0x27);
/* Регистр CONFIG (0xF5):
* - t_sb = 1000ms (0b101),
* - filter = off (0b000).
* Итоговая команда: 0b10100000 = 0xA0
*/
i2cWriteReg8(i2c1_fd, REG_CONFIG, 0xA0);
return;
error:
onClose(2);
}
void loop() {
// Основной цикл программы
// Чтение регистров текущего значения температуры
if (!loadReg(REG_DATA_START, REG_DATA_START + 5)) {
printf("Не удалось прочитать значение температуры. Повтор попытки через 1 секунду...\n");
} else {
// Расчет по предустановленным значениям, согласно datasheet BMP280
int adc_P = (raw_data[0] << 12) | (raw_data[1] << 4) | (raw_data[2] >> 4);
int adc_T = (raw_data[3] << 12) | (raw_data[4] << 4) | (raw_data[5] >> 4);
int var1_t = (adc_T / 16384.0 - T1 / 1024.0) * T2;
int var2_t = ((adc_T / 131072.0 - T1 / 8192.0) * (adc_T / 131072.0 - T1 / 8192.0)) * T3;
int t_fine = var1_t + var2_t;
int temperature = t_fine / 5120.0;
printf("[BME280] Температура: %d °C\n", temperature);
}
delay(1000);
}
ONDESTROY() {
i2cRelease(i2c1_fd);
// Завершение работы библиотеки
releaseWiringRP();
// Выход из программы
exit(0);
}
MAIN_WIRINGRP();
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <stdint.h>
#include "wiringRP.h"
#include "wire.h"
/*
* Пример предназначен для иллюстрации возможности подключения устройств по интерфейсу I2C8 на Repka Pi 5.
* В данном примере подключается датчик давления и температуры BME280.
* Опрос датчика происходит с интервалом в 1 секунду.
*/
// Глобальные переменные и константы
int i2c8_fd; // Файловый дескриптор интерфейса I2C8
// Глобальные переменные и константы BME280
const int PORT_I2C = I2C8_BUS;
const uint8_t BME280_ADR = 0x76;
const uint8_t BME280_CHIP_ID = 0x60;
const uint8_t REG_CHIP_ID = 0xD0;
const uint8_t REG_CTRL_MEAS = 0xF4;
const uint8_t REG_CONFIG = 0xF5;
const uint8_t REG_DATA_START = 0xF7;
const uint8_t REG_CALIB_START = 0x88;
const uint8_t REG_CALIB_END = 0xA1;
static uint8_t raw_data[32];
static uint8_t status;
static int T1, T2, T3;
// Чтение диапазона регистров датчика BMP280
static bool loadReg(uint8_t firstReg, uint8_t lastReg) {
for (uint8_t ind = firstReg; ind <= lastReg; ind++) {
raw_data[ind - firstReg] = i2cReadReg8(i2c8_fd, ind);
if (raw_data[ind - firstReg] < 0) {
printf("Регистр 0x%02X не доступен! Идентификатор интерфейса I2C: %d.\n", ind, PORT_I2C);
return false;
}
}
return true;
}
void setup() {
// Инициализация библиотеки WiringRP
// Используется режим нумерации SUNXI
if (setupWiringRP(WRP_MODE_SUNXI) < 0) {
goto error;
}
// Инициализация пользовательских объектов
i2c8_fd = i2cSetup(PORT_I2C, BME280_ADR);
if (i2c8_fd < 0) {
goto error;
}
delay(100);
// Чтение идентификатор датчика
unsigned int chipId = i2cReadReg8(i2c8_fd, REG_CHIP_ID);
if (chipId != BME280_CHIP_ID) {
printf("Не удалось получить правильный идентификатор датчика! Ожидалось значение 0x%02X, а получено 0x%02X.\n", BME280_CHIP_ID, chipId);
goto error;
}
// Чтение регистров калибровочных коэффициентов
if (!loadReg(REG_CALIB_START, REG_CALIB_END)) {
printf("Не удалось прочитать калибровочные коэффициенты.\n");
goto error;
}
// Формирование калибровочных коэффициентов, согласно datasheet BMP280
T1 = raw_data[0] + (raw_data[1] << 8);
T2 = raw_data[2] + (raw_data[3] << 8);
T3 = raw_data[4] + (raw_data[5] << 8);
/* Запись конфигурации в управляющие регистры датчика.
* Конфигурация устанавливает режим работы, частоту и точность измерений.
* Регистр CTRL_MEAS (0xF4):
* - osrs_t = x1 (0b001),
* - osrs_p = x1 (0b001),
* - mode = normal (0b11).
* Итоговая команда: 0b00100111 = 0x27
*/
i2cWriteReg8(i2c8_fd, REG_CTRL_MEAS, 0x27);
/* Регистр CONFIG (0xF5):
* - t_sb = 1000ms (0b101),
* - filter = off (0b000).
* Итоговая команда: 0b10100000 = 0xA0
*/
i2cWriteReg8(i2c8_fd, REG_CONFIG, 0xA0);
return;
error:
onClose(2);
}
void loop() {
// Основной цикл программы
// Чтение регистров текущего значения температуры
if (!loadReg(REG_DATA_START, REG_DATA_START + 5)) {
printf("Не удалось прочитать значение температуры. Повтор попытки через 1 секунду...\n");
} else {
// Расчет по предустановленным значениям, согласно datasheet BMP280
int adc_P = (raw_data[0] << 12) | (raw_data[1] << 4) | (raw_data[2] >> 4);
int adc_T = (raw_data[3] << 12) | (raw_data[4] << 4) | (raw_data[5] >> 4);
int var1_t = (adc_T / 16384.0 - T1 / 1024.0) * T2;
int var2_t = ((adc_T / 131072.0 - T1 / 8192.0) * (adc_T / 131072.0 - T1 / 8192.0)) * T3;
int t_fine = var1_t + var2_t;
int temperature = t_fine / 5120.0;
printf("[BME280] Температура: %d °C\n", temperature);
}
delay(1000);
}
ONDESTROY() {
i2cRelease(i2c8_fd);
// Завершение работы библиотеки
releaseWiringRP();
// Выход из программы
exit(0);
}
MAIN_WIRINGRP();
