Максимальное количество записей Arduino I2C на передачу

i2c

Существует ли ограничение на количество команд Wire.write(), последовательно выполняемых между командой Wire.beginTransmission() и командой Wire.endTransmission( ) для библиотеки Arduino Wire?

, 👍3

Обсуждение

@pascalm Не волнуйтесь, ответы тоже будут перенесены., @Roger Rowland


3 ответа


1

Быстрый взгляд на исходный код показывает, что имеется буфер фиксированной длины в 32 байта:

Из заголовочного файла wire.h:

#define BUFFER_LENGTH 32

И из реализации функции write:

size_t TwoWire::write(uint8_t data)
{
  if(transmitting){
  // в режиме ведущего передатчика
    // не беспокойтесь, если буфер заполнен
    if(txBufferLength >= BUFFER_LENGTH){
      setWriteError();
      return 0;
    }
    // поместить байт в буфер tx
    txBuffer[txBufferIndex] = data;
    ++txBufferIndex;
    // обновляем количество в буфере
    txBufferLength = txBufferIndex;
  }else{
  // в ведомом режиме отправки
    // ответ мастеру
    twi_transmit(&data, 1);
  }
  return 1;
}
,

Я почти уверен, что буфер расходуется через прерывание во время передачи, поэтому вы можете передать более 32 байтов, если перед записью убедитесь, что буфер не заполнен., @Nick Johnson

@NickJohnson Может быть, я не видел весь код, но, согласно документации, передача не начинается, пока вы не вызовете endTransmission, поэтому я предполагаю, что несколько записей до этого могут переполниться. В любом случае следует проверить код возврата функции., @Roger Rowland

хорошо, спасибо, это точно соответствует тому, что я испытываю, можно отправить максимум 32 байта. Это аппаратное ограничение или просто буфер, установленный в оперативной памяти, другими словами, могу ли я просто увеличить его? например #define BUFFER_LENGTH 64?, @pascalm

@Roger Вы правы, передача не начнется, пока вы не вызовете endTransmission. Ура, новая тупость библиотеки Arduino!, @Nick Johnson

@pascalm Это определенно не аппаратная проблема. Было бы сложно увеличить размер буфера без изменения библиотек Arduino, но вместо этого вы могли бы вызывать вызовы низкоуровневых функций endTransmission с помощью собственного буфера: https://github.com/arduino/Arduino/blob/db8cbf24c99dc930b9ccff1a43d018c81f178535/hardware /arduino/avr/libraries/Wire/utility/twi.c#L177, @Nick Johnson

хорошо, спасибо, тогда я немного углублюсь в этот код :), @pascalm


6

В библиотеках TWI и Wire используется пять буферов. Они определены как 32 байта.

В wire.h:

#define BUFFER_LENGTH 32

В Wire.cpp:

uint8_t TwoWire::rxBuffer[BUFFER_LENGTH];
...
uint8_t TwoWire::txBuffer[BUFFER_LENGTH];

В twi.h:

  #define TWI_BUFFER_LENGTH 32

В twi.c:

static uint8_t twi_masterBuffer[TWI_BUFFER_LENGTH];
...
static uint8_t twi_txBuffer[TWI_BUFFER_LENGTH];
...
static uint8_t twi_rxBuffer[TWI_BUFFER_LENGTH];

Итак, вы сразу используете 5 x 32 байта (160 байт).


Вы можете увеличить это значение, скажем, до 64 байт, учитывая, что ваши 160 байт теперь составляют 320 байт, а оперативной памяти у вас немного.

Комментарии к endTransmission() верны. После вызова Wire.beginTransmission() фактически ничего не передается до вызова endTransmission(). Это позволяет вам заполнить буфер на досуге, а затем позволить библиотеке выполнять запись в зависимости от времени.


Ссылка

  • I2C
  • Проводная библиотека
,

-1

Размер буфера можно увеличить.

Следует перейти к файлу twi.h, файлу Wire.h и установить нужную длину переменной: BUFFER_LENGTH

,