pvvx
Активный участник сообщества
Попробовал нативно работать с аппартным I2C.
Удобный аппаратный контроллер.
На примере с INA219 получилось работать так:
1) Конфигурируем i2c в нужный режим (их там куча )
2) Забиваем в FIFO команды и данные для передачи.
3) Ожидаем готовности или спустя время транзакции, считываем готовые данные от датчика из FIFO.
Никакой тусовки и ногодрыга.
Пример (только кода) прерывания на аппаратном таймере, непрерывно читающем измеренные ток и напряжение на датчике INA219:
Буфера накопления данных к передаче для простоты примера убраны и заменены на вывод в LogUART. Льет примерно такой лог:
Заполненная командами FIFO I2С исполняет такую пачку передач-приема по I2C, каждое прерывание таймера:
Частоты I2C CLK разгоняются любые, до нескольких МГц. Можно указать и работу в режиме HS, тогда контроллер I2C будет автоматом вставлять команду перехода в SMBUS режим для повышения частоты за МГц-ы... На чтение данных, для заполнения буферов с типом пинг-понг (один заливается, второй обрабатывается и передается на внешний сервер), можно включить и DMA... Но тут пока простой пример.
Скорость измерения у INA219 к 600 us на 12 бит замеры, чтение значений тока и напряжения по I2C при CLK I2C ~360 кГц (такой вышел для теста - плата с датчиком на длинных проводах и соплях - сделана для Ардуиншиков и более не тянет - щупы осциллографа уже вносят завалы фронтов своей емкостью...) занимает порядка 300 us. Это и выйдет максимальной частотой для опроса по таймеру, но в UART это уже в текстовом виде не вывести - не хватит скорости UART ...
Инициализацию i2с контроллера тоже написал свою, она очень простая... Выкинул громоздкий SDK-шный Hal... Она оптимизирована под конкретные задачи и использует совсем мало кода и данных. Может позже скину пример в мою сборку SDK.
PS: 4-ре I2С контроллера в RTL871x по регистрам аналогичны Intel D2000 и расписаны в доках от Intel D2000. Код от SDK к Intel D2000 для I2C, после модификации и вставки пару нюансов тоже работает.
Удобный аппаратный контроллер.
На примере с INA219 получилось работать так:
1) Конфигурируем i2c в нужный режим (их там куча )
2) Забиваем в FIFO команды и данные для передачи.
3) Ожидаем готовности или спустя время транзакции, считываем готовые данные от датчика из FIFO.
Никакой тусовки и ногодрыга.
Пример (только кода) прерывания на аппаратном таймере, непрерывно читающем измеренные ток и напряжение на датчике INA219:
Код:
#define i2c_reg(r) *((volatile uint32 *)(pi2c->base_regs + r))
void ina_tick_handler(void *par) {
PINA219DRV p = &ina219drv;
i2c_drv_t *pi2c = &p->i2c;
DiagPrintf("%d,%d\n", p->buf_i2c.us[0], p->buf_i2c.ss[1]);
switch(p->status) {
default:
// Disable controller.
i2c_reg(REG_DW_I2C_IC_ENABLE) = 0;
DiagPrintf(".");
p->status = 1;
break;
case 1:
// Enable controller.
i2c_reg(REG_DW_I2C_IC_ENABLE) = BIT_IC_ENABLE;
DiagPrintf("*");
p->status = 2;
break;
case 3:
if (i2c_reg(REG_DW_I2C_IC_RAW_INTR_STAT) & BIT_IC_RAW_INTR_STAT_TX_ABRT) {
uint32 tmp = i2c_reg(REG_DW_I2C_IC_CLR_INTR);
p->status = 0;
break;
} else {
// Считаем готовые значения тока и напряжения INA219 из FIFO ic I2C
p->buf_i2c.uc[1] = i2c_reg(REG_DW_I2C_IC_DATA_CMD);
p->buf_i2c.uc[0] = i2c_reg(REG_DW_I2C_IC_DATA_CMD);
p->buf_i2c.uc[3] = i2c_reg(REG_DW_I2C_IC_DATA_CMD);
p->buf_i2c.uc[2] = i2c_reg(REG_DW_I2C_IC_DATA_CMD);
}
case 2:
// Заполним FIFO ic I2C командами (адрес устройства и прочее он сделает сам, автоматически, согласно начальной конфигурации контроллера IC)
// Задать номер регистра напряжения для чтения в INA219. Write addr reg + stop.
i2c_reg(REG_DW_I2C_IC_DATA_CMD) = 2 | BIT_IC_DATA_CMD_STOP;
// Задать транзакцию чтения регистра напряжения из INA219. Read command 2 bytes + stop.
i2c_reg(REG_DW_I2C_IC_DATA_CMD) = BIT_IC_DATA_CMD_CMD;
i2c_reg(REG_DW_I2C_IC_DATA_CMD) = BIT_IC_DATA_CMD_CMD | BIT_IC_DATA_CMD_STOP;
// Задать номер регистра тока для чтения из INA219. Write addr reg + stop.
i2c_reg(REG_DW_I2C_IC_DATA_CMD) = 1 | BIT_IC_DATA_CMD_STOP;
// Задать транзакцию чтения регистра тока из INA219. Read command 2 bytes + stop.
i2c_reg(REG_DW_I2C_IC_DATA_CMD) = BIT_IC_DATA_CMD_CMD;
i2c_reg(REG_DW_I2C_IC_DATA_CMD) = BIT_IC_DATA_CMD_CMD | BIT_IC_DATA_CMD_STOP;
p->status = 3;
break;
}
}
Заполненная командами FIFO I2С исполняет такую пачку передач-приема по I2C, каждое прерывание таймера:
Частоты I2C CLK разгоняются любые, до нескольких МГц. Можно указать и работу в режиме HS, тогда контроллер I2C будет автоматом вставлять команду перехода в SMBUS режим для повышения частоты за МГц-ы... На чтение данных, для заполнения буферов с типом пинг-понг (один заливается, второй обрабатывается и передается на внешний сервер), можно включить и DMA... Но тут пока простой пример.
Скорость измерения у INA219 к 600 us на 12 бит замеры, чтение значений тока и напряжения по I2C при CLK I2C ~360 кГц (такой вышел для теста - плата с датчиком на длинных проводах и соплях - сделана для Ардуиншиков и более не тянет - щупы осциллографа уже вносят завалы фронтов своей емкостью...) занимает порядка 300 us. Это и выйдет максимальной частотой для опроса по таймеру, но в UART это уже в текстовом виде не вывести - не хватит скорости UART ...
Инициализацию i2с контроллера тоже написал свою, она очень простая... Выкинул громоздкий SDK-шный Hal... Она оптимизирована под конкретные задачи и использует совсем мало кода и данных. Может позже скину пример в мою сборку SDK.
PS: 4-ре I2С контроллера в RTL871x по регистрам аналогичны Intel D2000 и расписаны в доках от Intel D2000. Код от SDK к Intel D2000 для I2C, после модификации и вставки пару нюансов тоже работает.
Вложения
-
267.3 KB Просмотры: 25
Последнее редактирование: