Lcd i2c модуль подключение к arduino. Обмен даными Arduino по протоколу I2C
С номиналами от 10 Ом до 1 МОм);
1 Описание интерфейса I2C
Последовательный протокол обмена данными IIC (также называемый I2C - Inter-Integrated Circuits, межмикросхемное соединение) использует для передачи данных две двунаправленные линии связи, которые называются шина последовательных данных SDA (Serial Data) и шина тактирования SCL (Serial Clock) . Также имеются две линии для питания. Шины SDA и SCL подтягиваются к шине питания через резисторы.
В сети есть хотя бы одно ведущее устройство (Master) , которое инициализирует передачу данных и генерирует сигналы синхронизации. В сети также есть ведомые устройства (Slave) , которые передают данные по запросу ведущего. У каждого ведомого устройства есть уникальный адрес, по которому ведущий и обращается к нему. Адрес устройства указывается в паспорте (datasheet). К одной шине I2C может быть подключено до 127 устройств, в том числе несколько ведущих. К шине можно подключать устройства в процессе работы, т.е. она поддерживает «горячее подключение».
Давайте рассмотрим временную диаграмму обмена по протоколу I2C. Есть несколько различающихся вариантов, рассмотрим один из распространённых. Воспользуемся логическим анализатором, подключённым к шинам SCL и SDA.
Мастер инициирует обмен. Для этого он начинает генерировать тактовые импульсы и посылает их по линии SCL пачкой из 9-ти штук. Одновременно на линии данных SDA он выставляет адрес устройства , с которым необходимо установить связь, которые тактируются первыми 7-ми тактовыми импульсами (отсюда ограничение на диапазон адресов: 2 7 = 128 минус нулевой адрес). Следующий бит посылки - это код операции (чтение или запись) и ещё один бит - бит подтверждения (ACK), что ведомое устройство приняло запрос. Если бит подтверждения не пришёл, на этом обмен заканчивается. Или мастер продолжает посылать повторные запросы.
Это проиллюстрировано на рисунке ниже.. В первом случае, для примера, отключим ведомое устройство от шины. Видно, что мастер пытается установить связь с устройством с адресом 0x27, но не получает подтверждения (NAK). Обмен заканчивается.
![](https://i0.wp.com/soltau.ru/images/ardu-i2c/i2c_timing_wo.png)
Теперь подключим к шине I2C ведомое устройство и повторим операцию. Ситуация изменилась. На первый пакет с адресом пришло подтверждение (ACK) от ведомого. Обмен продолжился. Информация передаётся также 9-битовыми посылками, но теперь 8 битов занимают данные и 1 бит - бит подтверждения получения ведомым каждого байта данных. Если в какой-то момент связь оборвётся и бит подтверждения не придёт, мастер прекратит передачу.
2 Реализация I2C в Arduino
Arduino использует для работы по интерфейсу I2C два порта. Например, в Arduino UNO и Arduino Nano аналоговый порт A4 соответствует SDA, аналоговый порт A5 соответствует SCL.
![](https://i1.wp.com/soltau.ru/images/ardu-i2c/2.png)
Для других моделей плат соответствие выводов такое:
3 Библиотека "Wire" для работы с IIC
Для облегчения обмена данными с устройствами по шине I2C для Arduino написана стандартная библиотека Wire . Она имеет следующие функции:
Функция | Назначение |
---|---|
begin(address) | инициализация библиотеки и подключение к шине I2C; если не указан адрес, то присоединённое устройство считается ведущим; используется 7-битная адресация; |
requestFrom() | используется ведущим устройством для запроса определённого количества байтов от ведомого; |
beginTransmission(address) | начало передачи данных к ведомому устройству по определённому адресу; |
endTransmission() | прекращение передачи данных ведомому; |
write() | запись данных от ведомого в ответ на запрос; |
available() | возвращает количество байт информации, доступных для приёма от ведомого; |
read() | чтение байта, переданного от ведомого ведущему или от ведущего ведомому; |
onReceive() | указывает на функцию, которая должна быть вызвана, когда ведомое устройство получит передачу от ведущего; |
onRequest() | указывает на функцию, которая должна быть вызвана, когда ведущее устройство получит передачу от ведомого. |
4 Подключение I2C устройства к Arduino
Давайте посмотрим, как работать с шиной I2C с помощью Arduino.
Сначала соберём схему, как на рисунке. Будем управлять яркостью светодиода, используя цифровой 64-позиционный потенциометр AD5171 (см. техническое описание), который подключается к шине I2C. Адрес, по которому мы будем обращаться к потенциометру - 0x2c (44 в десятичной системе).
![](https://i2.wp.com/soltau.ru/images/ardu-i2c/4.png)
5 Управление устройством по шине IIC
Рассмотрим диаграммы информационного обмена с цифровым потенциометром AD5171, представленные в техническом описании:
![](https://i2.wp.com/soltau.ru/images/ardu-i2c/diag.png)
Нас тут интересует диаграмма записи данных в регистр RDAC . Этот регистр используется для управления сопротивлением потенциометра.
Откроем из примеров библиотеки "Wire" скетч: Файл Образцы Wire digital_potentiometer . Загрузим его в память Arduino.
#include
После включения вы видите, как яркость светодиода циклически нарастает, а потом гаснет. При этом мы управляем потенциометром с помощью Arduino по шине I2C.
Arduino поддерживает много интерфейсов передачи данных, одним из которых является достаточно популярный на сегодняшний день I2C. Когда-то давно этот протокол связи придумала компания Philips и зарегистрировала под запатентованным названием “I2C”, вы также можете встретить его под названиями TWI, 2 line interface, но все они работают по единому принципу.
Весь смысл I2С шины состоит в том, что на 2 провода можно повесить большое (128) количество различных устройств, от датчиков температуры, до микроконтроллеров.
Но в тоже время по скорости I2C уступает UART и SPI , из-за основных принципов работы, т.к. две линии всегда подтянуты к резисторам(Vcc), а значит на графике мы получаем не прямоугольные импульсы, а трапециевидные, в отличие от вышеупомянутых.
SDA - отвечает за передачу информации(начало передачи, адрес, данные)
SCL - тактирование шины
В I2C устройства могут быть двух типов Master и Slave
Теперь разберём основные принципы программирования с помощью стандартной библиотеки Wire.h:
Wire.begin(uint8_t address) - используется для инициализации устройства, в режиме слейва нужно ввести адрес, в режиме мастера Wire.begin() . Вместо Wire можно использовать любое другое слово.
Wire.requestFrom(uint8_t address, uint8_t quantity) – запрос на получения какого-то количества байт от определенного устройства(7 бит адрес). Возвращает число считанных байт.
Wire.beginTransmission(uint8_t address)- начало передачи
Wire.endTransmission()- конец передачи,возвращает номер ошибки или успех(0)
Wire.write(uint8_t data) –может принимать значение одиночного байта(value), нескольких байт(string), массива, определенной длинны (data, lenght). Располагается между: beginTransmission и endTransmission. Возращает число записанных байт.
Wire.available() – возвращает количество байт доступных для обработки. Вызывается мастером после requestFrom.
Wire.read() – считывает байт от ведомого устройства. Пишется после requestFrom.
Подключение библиотек к Ардуино IDE не представляет сложности, так как поставляется в комплекте со стандартным редактором.
Есть еще несколько функций, но думаю для начала этой основы вполне достаточно, к тому же почти на любую периферию можно найти библиотеку.
Для примера рассмотрим подключение и работу акселерометра и гироскопа Gy-521.
Подключаем согласно схеме (подтягивающие резисторы встроены в модуль):
Модуль может работать как от 3.3 вольт, так и от 5.
#include
Вам понадобится
- - Arduino;
- - цифровой потенциометр AD5171;
- - светодиод;
- - резистор на 220 Ом;
- - 2 резистора на 4,7 кОм;
- - соединительные провода.
Инструкция
Последовательный протокол обмена данными IIC (также называемый I2C - Inter-Integrated Circuits, межмикросхемное соединение) использует для передачи данных две двунаправленные линии связи, которые называются шина последовательных данных SDA
(Serial Data) и шина тактирования SCL
(Serial Clock). Также имеются две линии для питания. Шины SDA и SCL подтягиваются к шине питания через резисторы.
В сети есть хотя бы одно ведущее устройство (Master
), которое инициализирует передачу данных и генерирует сигналы синхронизации. В сети также есть ведомые устройства (Slave
), которые передают данные по запросу ведущего. У каждого ведомого устройства есть уникальный адрес, по которому ведущий и обращается к нему. Адрес устройства указывается в паспорте (datasheet). К одной шине I2C может быть подключено до 127 устройств, в том числе несколько ведущих. К шине можно подключать устройства в процессе работы, т.е. она поддерживает "горячее подключение".
Arduino использует для работы по интерфейсу I2C два порта. Например, в Arduino UNO и Arduino Nano аналоговый порт A4 соответствует SDA, аналоговый порт A5 соответствует SCL.
Для других моделей плат:
Arduino Pro и Pro Mini
- A4 (SDA), A5 (SCL)
Arduino Mega
- 20 (SDA), 21 (SCL)
Arduino Leonardo
- 2 (SDA), 3 (SCL)
Arduino Due
- 20 (SDA), 21 (SCL), SDA1, SCL1
Для облегчения обмена данными с устройствами по шине I2C для Arduino написана стандартная библиотека "Wire". Она имеет следующие функции:
begin(address)
- инициализация библиотеки и подключение к шине I2C; если не указан адрес, то присоединённое устройство считается ведущим; используется 7-битная адресация;
requestFrom()
- используется ведущим устройством для запроса определённого количества байтов от ведомого;
beginTransmission(address)
- начало передачи данных к ведомому устройству по определённому адресу;
endTransmission()
- прекращение передачи данных ведомому;
write()
- запись данных от ведомого в ответ на запрос;
available()
- возвращает количество байт информации, доступных для приёма от ведомого;
read()
- чтение байта, переданного от ведомого ведущему или от ведущего ведомому;
onReceive()
- указывает на функцию, которая должна быть вызвана, когда ведомое устройство получит передачу от ведущего;
onRequest()
- указывает на функцию, которая должна быть вызвана, когда ведущее устройство получит передачу от ведомого.
Давайте посмотрим, как работать с шиной I2C с помощью Arduino.
Сначала соберём схему, как на рисунке. Будем управлять яркостью светодиода, используя цифровой 64-позиционный потенциометр AD5171, который подключается к шине I2C. Адрес, по которому мы будем обращаться к потенциометру - 0x2c (44 в десятичной системе).
Описание библиотеки Wire
Данная библиотека позволяет вам взаимодействовать с I2C / TWI устройствами. На платах Arduino с компоновкой R3 (распиновка 1.0) SDA (линия данных) и SCL (линия тактового сигнала) находятся на выводах около вывода AREF. Arduino Due имеет два I2C / TWI интерфейса: SDA1 и SCL1 находятся около вывода AREF, а дополнительные линии находятся на выводах 20 и 21.
В таблице ниже показано, где расположены TWI выводы на разных платах Arduino.
Начиная с Arduino 1.0, данная библиотека наследует функции Stream , что делает ее совместимой с другими библиотеками чтения/записи. Из-за этого send() и receive() были заменены на read() и write() .
Примечание
Существуют 7- и 8-битные версии адресов I2C. 7 битов идентифицируют устройство, а восьмой бит определяет, идет запись или чтение. Библиотека Wire использует 7 битные адреса. Если у вас есть техническое описание или пример кода, где используется 8-битный адрес, вам нужно откинуть младший бит (т.е. сдвинуть значение на один бит вправо), получив адрес от 0 до 127. Однако адреса от 0 до 7 не используются, так как зарезервированы, поэтому первым адресом, который может быть использован, является 8. Обратите внимание, что при подключении выводов SDA/SCL необходимы подтягивающие резисторы. Для более подробной информации смотрите примеры. На плате MEGA 2560 есть подтягивающие резисторы на выводах 20 и 21.
Описание методов
Wire.begin()
ОписаниеИнициализирует библиотеку Wire и подключается к шине I2C как ведущий (мастер) или ведомый. Как правило, должен вызываться только один раз.
Синтаксис
Wire.begin(address)
Параметры
address: 7-битный адрес ведомого устройства (необязательно); если не задан, плата подключается к шине как мастер.
Возвращаемое значение
Пример
Примеры для ведомого устройства смотрите в примерах к методам onReceive() и onRequest() . Примеры для ведущего устройства смотрите в примерах к остальным методам. .
Wire.requestFrom()
ОписаниеИспользуется мастером для запроса байтов от ведомого устройства. Эти байты могут быть получены с помощью методов available() и read() .
Если этот аргумент равен true , то requestFrom() после запроса посылает сообщение STOP, освобождая шину I2C.
Если этот аргумент равен false , то requestFrom() после запроса посылает сообщение RESTART. Шина не освобождается, что мешает другому устройству-мастеру влезть между сообщениями. Это позволяет одному ведущему устройству посылать несколько запросов, пока оно контролирует шину.
Синтаксис
Wire.requestFrom(address, quantity)
Wire.requestFrom(address, quantity, stop)
Параметры
- address: 7-битный адрес устройства, у которого запрашиваются байты;
- quantity: количество запрашиваемых байтов;
- stop: boolean . true посылает сообщение STOP после запроса. false посылает сообщение RESTART после запроса, сохраняя соединение активным.
byte: количество байтов, возвращенных от ведомого устройства.
Пример
Wire.beginTransmission()
ОписаниеНачинает передачу на ведомое I2C устройство с заданным адресом. После него последовательность байтов для передачи ставится в очередь с помощью функции write() , и их передача с помощью вызова endTransmission() .
Синтаксис
Wire.beginTransmission(address)
Параметры
address: 7-битный адрес устройства, на которое необходимо передать данные.
Возвращаемое значение
Пример
Wire.endTransmission()
ОписаниеЗавершает передачу на ведомое устройство, которая была начата методом beginTransmission() и передает байты, которые были поставлены в очередь методом write() .
Для совместимости с определенными I2C устройствами, начиная с Arduino 1.0.1, requestFrom() принимает аргумент логического типа данных, меняющий его поведение.
Если этот аргумент равен true , то requestFrom() после передачи посылает сообщение STOP, освобождая шину I2C.
Если этот аргумент равен false , то requestFrom() после передачи посылает сообщение RESTART. Шина не освобождается, что мешает другому устройству-мастеру влезть между сообщениями. Это позволяет одному ведущему устройству посылать несколько передач, пока оно контролирует шину.
По умолчанию этот аргумент равен true .
Синтаксис
Wire.endTransmission()
Wire.endTransmission(stop)
Параметры
stop: boolean . true посылает сообщение STOP после передачи. false посылает сообщение RESTART после передачи, сохраняя соединение активным.
Возвращаемое значение
byte , который указывает на состояние передачи:
- 0: успех;
- 1: данные слишком длинны для заполнения буфера передачи;
- 2: принят NACK при передаче адреса;
- 3: принят NACK при передаче данных;
- 4: остальные ошибки.
Смотрите пример к методу write() .
Wire.write()
ОписаниеЗаписывает данные от ведомого устройства в отклик на запрос от ведущего устройства, или ставит в очередь байты для передачи от мастера к ведомому устройству (между вызовами beginTransmission() и endTransmission()).
Синтаксис
Wire.write(value)
Wire.write(string)
Wire.write(data, length)
Параметры
- value: значение для передачи, один байт.
- string: строка для передачи, последовательность байтов.
- data: массив данных для передачи, байты.
- length: количество байтов для передачи.
byte: write() возвращает количество записанных байтов, хотя чтение этого количества не обязательно.
Пример #include
Wire.available()
ОписаниеВозвращает количество байтов, доступных для получения с помощью read() . Этот метод должен вызываться на ведущем устройстве после вызова requestFrom() или на ведомом устройстве внутри обработчика onReceive() .
Синтаксис
Wire.available()
Параметры
Возвращаемое значение
Количество байтов, доступных для чтения.
Пример
Смотрите пример к методу read() .
Wire.read()
ОписаниеСчитывает байт, который был передан от ведомого устройства к ведущему после вызова requestFrom() , или который был передан от ведущего устройства к ведомому.
Синтаксис
Параметры
Возвращаемое значение
byte: очередной принятый байт.
Пример #include
Wire.setClock()
ОписаниеИзменяет тактовую частоту для связи по шине I2C. У ведомых I2C устройств нет минимальной рабочей тактовой частоты, однако обычно используется 100 кГц.
Синтаксис
Wire.setClock(clockFrequency)
Параметры
clockFrequency: значение частоты (в герцах) тактового сигнала. Принимаются значения 100000 (стандартный режим) и 400000 (быстрый режим). Некоторые процессоры также поддерживают 10000 (низкоскоростной режим), 1000000 (быстрый режим плюс) и 3400000 (высокоскоростной режим). Чтобы убедиться, что необходимый режим поддерживается, обращайтесь к технической документации на конкретный процессор.
Возвращаемое значение
Wire.onReceive()
ОписаниеРегистрирует функцию, которая будет вызываться, когда ведомое устройство принимает передачу от мастера.
Синтаксис
Wire.onReceive(handler)
Параметры
handler: функция, которая должна будет вызываться, когда ведомое устройство принимает данные; она должна принимать один параметр int (количество байтов, прочитанных от мастера) и ничего не возвращать, т.е.:
void myHandler(int numBytes)
Возвращаемое значение
Пример
#include
Wire.onRequest()
ОписаниеРегистрирует функцию, которая будет вызываться, когда мастер запрашивает данные от ведомого устройства.
Синтаксис
Wire.onRequest(handler)
Параметры
handler: функция, которая должна будет вызываться, она не принимает параметров и ничего не возвращает, т.е.:
void myHandler()
Возвращаемое значение
Пример
Код для платы Arduino, работающей в качестве ведомого устройства:
#include