I2C

I2C

Модуль I2C определяет числовую константу для каждого доступного I2C-устройства. Например, на ESP32 I2C0 определен константой i2c.I2C0. Пожалуйста, обратитесь к документации вашей платформы или платы, чтобы узнать, какие I2C-устройства доступны. Если вы обращаетесь к несуществующему I2C, возвращается значение nil.

Модуль I2C может работать в режиме мастера или ведомого, каждый из которых идентифицируется константами i2c.MASTER и i2c.SLAVE. На данный момент разрешен только i2c.MASTER.

I2C (Inter-Integrated Circuit) — это многомастерная, многоведомая, пакетно-переключаемая, однопроводная, последовательная компьютерная шина, изобретенная фирмой Philips Semiconductor (теперь NXP Semiconductors). Обычно она используется для подключения периферийных интегральных схем с низкой скоростью к процессорам и микроконтроллерам для общения на короткие расстояния внутри платы.

I2C использует только две двунаправленные линии с открытым стоком: линию передачи данных (SDA) и линию тактового сигнала (SCL), подтянутые резисторами.

I2C имеет 7-битное или 10-битное (в зависимости от используемого устройства) адресное пространство. Общие скорости шины I2C — стандартный режим 100 кбит/с и низкоскоростной режим 10 кбит/с, но также допускаются произвольно низкие частоты тактового сигнала. Недавние версии I2C могут поддерживать больше узлов и работать на более высоких скоростях (400 кбит/с в режиме Fast, 1 Мбит/с в режиме Fast mode plus или Fm+ и 3,4 Мбит/с в режиме High Speed).

Следует отметить, что указанные скорости передачи данных применяются для транзакций между мастером и ведомым без учета растяжения тактового сигнала или других аппаратных накладных расходов. К протокольным накладным расходам относятся адрес ведомого устройства и, возможно, адрес регистра внутри ведомого устройства, а также биты подтверждения/не подтверждения для каждого байта. Таким образом, фактическая скорость передачи данных пользователя ниже, чем эти максимальные битовые скорости.

Максимальное количество узлов ограничено адресным пространством и общей емкостью шины 400 пФ, что ограничивает практические расстояния коммуникации до нескольких метров.

instance = i2c.attach(id, mode, [speed])

Подключить устройство I2C.

Аргументы:

  • id: идентификатор устройства I2C. Используйте i2c.I2Cx, определенный для этой цели.
  • mode: может быть либо i2c.MASTER, либо i2c.SLAVE. На данный момент поддерживается только i2c.MASTER.
  • speed (необязательно): скорость шины I2C, выраженная в герцах. Этот аргумент необязателен, и если он не предоставлен, применяется стандартная скорость 40000 (400 килогерц).

Возвращает: экземпляр устройства i2c или исключение. Этот экземпляр необходимо сохранить в переменной для дальнейших операций с ним.

instance:detach()

Отсоединить экземпляр устройства i2c от шины I2C и освободить все используемые ресурсы.

Аргументы: нет.

Возвращает: ничего или исключение.

instance:setspeed(speed)

Установить скорость шины I2C для конкретного экземпляра I2C.

Аргументы:

  • speed (скорость): скорость шины I2C, выраженная в герцах.

Возвращает: ничего или исключение.

instance:start()

Начать транзакцию I2C.

Аргументы: нет

Возвращает: ничего или исключение.

instance:address(address, read)

Отправить адрес на шину I2C для чтения или записи, если экземпляр I2C настроен в режиме мастера.

Аргументы:

  • address (адрес): целочисленное значение с адресом I2C для отправки.
  • read (чтение): логическое значение, которое указывает, используется ли адрес для чтения или записи в шину I2C или из нее. Если true, адрес используется для чтения, если false - для записи.

Возвращает: ничего или исключение.

readed data = instance:read()

Прочитать один байт с шины I2C. Перед использованием этой функции необходимо отправить адрес I2C для чтения.

Аргументы: нет

Возвращает: прочитанные данные или исключение.

instance:write(byte0, [byte1, …, byten])

Записать один или несколько байтов на шину I2C. Перед использованием этой функции необходимо отправить адрес I2C для записи.

Аргументы:

  • byte0, …., byten: байты для записи.

Возвращает: ничего или исключение.

instance:write(string)

Записать строку на шину I2C. Перед использованием этой функции необходимо отправить адрес I2C для записи.

Аргументы:

  • string: строка для записи.

Возвращает: ничего или исключение.

instance:stop()

Остановить транзакцию I2C.

Аргументы: нет

Возвращает: ничего или исключение.

Пример

Этот пример демонстрирует, как общаться с устройствами I2C. В примере выполняется запись значений в EEPROM (4c256d), затем происходит чтение из EEPROM и проверка того, что значения совпадают.

-- Attach the eeprom to the i2c bus
function eeprom_attach()
  eeprom = i2c.attach(i2c.I2C0, i2c.MASTER, 400000)
end

-- Once the internally-timed write cycle has started and the EEPROM
-- inputs are disabled, acknowledge polling can be initiated.
-- This involves sending a start condition followed by the device address word.
-- If this fails (timeout, or ack not received) we can't write.
function eeprom_poll(devAddress) 
  local done = false
  
  while not done do
    try(
      function() 
        eeprom:start()
      eeprom:address(devAddress, false)
        eeprom:stop()
      done = true
      end
    )
  end
end

-- Write to eeprom (byte)
function eeprom_write(devAddress, address, value)
  eeprom:start()
  eeprom:address(devAddress, false)
  eeprom:write(0x00, address, value)
  eeprom:stop()

  eeprom_poll(devAddress)
end

-- Read from eeprom (byte)
function eeprom_read(devAddress, address)
  local read

  eeprom:start()
  eeprom:address(devAddress, false)
  eeprom:write(0x00, address)
  eeprom:start()
  eeprom:address(devAddress, true)

  read = eeprom:read()
  
  eeprom:stop()

  return read
end

-- Attach eeprom
eeprom_attach()

-- Write test bytes
for i=0,100 do
  eeprom_write(0x51, i, i)
end

-- Check bytes
for i=0,100 do
  if (eeprom_read(0x51, i) ~= i) then
    error("Readed "..read..", expected "..i)
  end
end