Функции этого раздела предназначены для обмена данными с периферийными устройствами по двухпроводному интерфейсу 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 |
Доступность I2C-шин на Repka Pi 5
Константа | Интерфейс | Пин SDA | Пин SCL | Доступен в вариантах распиновки |
|---|---|---|---|---|
| I2C2 | GPIO1_B6_d (пин 27) | GPIO1_B7_u (пин 28) | 4,8 |
| I2C4 | GPIO0_C4_d (пин 10) | GPIO0_C5_u (пин 8) | 8 |
| I2C5 | GPIO3_D0_u (пин 40) | GPIO3_C7_u (пин 38) | 8 |
| I2C7 | GPIO4_B3_u (пин 15) | GPIO4_B2_u (пин 13) | 8 |
| I2C8 | GPIO1_D7_u (пин 3) | GPIO1_D6_u (пин 5) | 2,3,4,7,8 |
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).
-
I2C4_BUS - порт I2C3 (I2CS на Repka Pi 5).
-
I2C5_BUS - порт I2C3 (I2CS на Repka Pi 5).
-
I2C7_BUS - порт I2C3 (I2CS на Repka Pi 5).
-
I2C8_BUS - порт I2C3 (I2CS на Repka Pi 5).
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: Подключение датчика температуры BMP280 #
Этот пример демонстрирует, как использовать функции i2cSetup, i2cRead и i2cRelease для настройки и получения данных от устройства по шине I2C.
Что делает этот пример:
- Он последовательно подключиться по порту i2c.
- Загрузит преднастройки для работы с датчиком.
- В режиме реального времени будет опрашивать датчик и выдавать значение температуры окружающей среды.
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <stdint.h>
#include "wiringRP.h"
#include "wire.h"
/*
Пример предназначен для иллюстрации возможности подключения устройств
по протоколу I2C.
В данном примере подключается датчик температуры BMP280
и идет его опрос с интервалом в 1 секунду
*/
// Глобальные переменные и константы BMP280
int i2c1_fd;
const int PORT_I2C = I2C1_BUS;
const uint8_t BMP280_ADR = 0x76;
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;
static int T2;
static int T3;
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("Регистр не доступен порт:%d регистр:%x\n", PORT_I2C, Ind);
return false;
}
}
return true;
}
void setup() {
// Инициализация библиотек wiringRP
if (setupWiringRP(WRP_MODE_SUNXI) < 0)
goto error;
// Инициализация пользовательских объектов
i2c1_fd = i2cSetup(PORT_I2C, BMP280_ADR);
if (i2c1_fd < 0) {
goto error;
}
//Считываем регистры предустановки BME280
if(!loadReg(REG_CALIB_START, REG_CALIB_END)) 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)) return;
// расчет по предустановленным значениям
//согласно 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("текущая темпиратура: %d\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"
/*
Пример предназначен для иллюстрации возможности подключения устройств
по протоколу I2C.
В данном примере подключается датчик температуры BMP280
и идет его опрос с интервалом в 1 секунду
*/
// Глобальные переменные и константы BMP280
int i2c1_fd;
const int PORT_I2C = I2C1_BUS;
const uint8_t BMP280_ADR = 0x76;
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;
static int T2;
static int T3;
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("Регистр не доступен порт:%d регистр:%x\n", PORT_I2C, Ind);
return false;
}
}
return true;
}
void setup() {
// Инициализация библиотек wiringRP
if (setupWiringRP(WRP_MODE_SUNXI) < 0)
goto error;
// Инициализация пользовательских объектов
i2c1_fd = i2cSetup(PORT_I2C, BMP280_ADR);
if (i2c1_fd < 0) {
goto error;
}
//Считываем регистры предустановки BME280
if(!loadReg(REG_CALIB_START, REG_CALIB_END)) 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)) return;
// расчет по предустановленным значениям
//согласно 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("текущая темпиратура: %d\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"
/*
Пример предназначен для иллюстрации возможности подключения устройств
по протоколу I2C.
В данном примере подключается датчик температуры BMP280
и идет его опрос с интервалом в 1 секунду
*/
// Глобальные переменные и константы BMP280
int i2c1_fd;
const int PORT_I2C = I2C8_BUS;
const uint8_t BMP280_ADR = 0x76;
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;
static int T2;
static int T3;
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("Регистр не доступен порт:%d регистр:%x\n", PORT_I2C, Ind);
return false;
}
}
return true;
}
void setup() {
// Инициализация библиотек wiringRP
if (setupWiringRP(WRP_MODE_SUNXI) < 0)
goto error;
// Инициализация пользовательских объектов
i2c1_fd = i2cSetup(PORT_I2C, BMP280_ADR);
if (i2c1_fd < 0) {
goto error;
}
//Считываем регистры предустановки BME280
if(!loadReg(REG_CALIB_START, REG_CALIB_END)) 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)) return;
// расчет по предустановленным значениям
//согласно 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("текущая темпиратура: %d\n", temperature);
delay(1000);
}
ONDESTROY() {
// Завершение работы библиотек
i2cRelease(i2c1_fd);
releaseWiringRP();
exit(0); // выход из программы
}
MAIN_WIRINGRP();