Модуль - Клавиатура, I2C-flash.
Техническое описание: Данная страница содержит подробное техническое описание модуля - клавиатура, I2C-flash и раскрывает работу с модулем через его регистры.
Ознакомиться с пользовательским описанием модуля и примерами работы с библиотекой iarduino_I2C_Keyboard можно на странице Wiki - Клавиатуры, I2C-flash.
Назначение:
Модуль - Клавиатура, I2C-flash - является устройством ввода данных с подключением по шине I2С.
К одной шине I2C можно подключить более 100 модулей. Адрес модуля на шине I2C (по умолчанию 0x09) назначается программно и хранится в его энергонезависимой памяти.
Описание:
Модуль построен на базе микроконтроллера STM32F030F4 и снабжен собственным стабилизатором напряжения. Модуль самостоятельно считывает состояния кнопок и сохраняет данные о их состоянии в свои регистры. Доступ к регистрам модуля осуществляется по шине I2C.
С помощью регистров модуля можно выполнять следующие действия:
- Изменить адрес данного модуля на шине I2C. При изменении адреса, можно указать, что новый адрес должен сохраниться в flash память модуля, а значит адрес сохранится и после отключения питания.
- Включить / отключить внутреннюю подтяжку линий шины I2C (по умолчанию включена). Состояние подтяжки линий шины I2C автоматически сохраняется в flash память модуля, а значит состояние линий сохранится после отключения и включения питания.
- Узнать версию прошивки модуля.
- Узнать текущее состояние кнопок клавиатуры (нажата / отпущена / удерживается).
- Узнать наличие событий кнопок клавиатуры (нажималась / отпускалась).
- Узнать время удержания или простоя кнопок клавиатуры (в десятых долях секунд).
- Прочитать бит-триггер который меняет свое состояние с каждым новым нажатием на кнопку.
- Управлять светодиодами кнопок (включить / выключить).
- Задать яркость свечения светодиодов кнопок (яркость сохраниться в flash память модуля).
- Задать режим светодиодной анимации, при которой светодиоды будут самостоятельно реагировать на события или изменение состояний кнопок (доступно несколько режимов).
- Узнать историю нажатий кнопок прочитав последовательности их нажатий из буфера FIFO.
- Узнать количество байт в буфере FIFO или очистить буфер.
- Задать время по истечении которого нажатая кнопка будет считаться удерживаемой и в буфер FIFO начнут поступать байты номера кнопки (время сохраняется в flash памяти модуля).
- Задать период повторений записи номера удерживаемой кнопки в буфер FIFO (время периода повторений номера удерживаемой кнопки сохраняется в flash памяти модуля).
Выводы модуля:
По бокам платы расположены разъемы для подключения клавиатуры к шине I2C. Шина подключается к любому разъему I2C, а второй разъем можно использовать для подключения следующей клавиатуры, или других устройств.
- SCL - вход/выход линии тактирования шины I2C.
- SDA - вход/выход линии данных шины I2C.
- Vcc - вход питания 3,3 или 5 В.
- GND - общий вывод питания.
Характеристики:
- Напряжение питания: 3,3 В или 5 В (постоянного тока), поддерживаются оба напряжения.
- Потребляемый ток: до 10 мА (при включении всех светодиодов).
- Интерфейс: I2C.
- Скорость шины I2C: 100 кбит/с.
- Адрес на шине I2C: устанавливается программно (по умолчанию 0x09).
- Уровень логической 1 на линиях шины I2C: 3,3 В (толерантны к 5 В).
- Количество кнопок со светодиодами: 10.
- Количество уровней яркости светодиодов: 7.
- Рабочая температура: от -20 до +70 °С.
- Габариты: 78,74 х 39,37 мм.
- Вес: 26 г.
Установка адреса:
Модуль - Клавиатура, I2C-flash относится к серии «Flash» модулей. Все модули данной серии позволяют назначать себе адрес для шины I2C, как временно (новый адрес действует пока есть питание), так и постоянно (новый адрес сохраняется в энергонезависимую память и действует даже после отключения питания). По умолчанию все модули серии «Flash» поставляются с адресом 0x09.
Допускается указывать адреса в диапазоне: 7 < адрес < 127.
Установка адреса (без сохранения):
Если в регистр 0x06 «ADDRESS» записать значение из 7 бит адреса и младшим битом «SAVE_FLASH» равным 0, то указанный адрес станет адресом модуля на шине I2C, но он не сохранится во FLASH памяти, а значит после отключения питания, установится прежний адрес модуля.
Установка адреса (с сохранением):
Для установки адреса с его сохранением в FLASH память модуля необходимо выполнить два действия:
- Установить бит «SAVE_ADR_EN» в регистре 0x01 «BITS_0» (при этом адрес модуля останется прежним).
- Записать в регистр 0x06 «ADDRESS» значение из 7 бит адреса и младшим битом «SAVE_FLASH» равным 1.
- Если не выполнить первое действие (не установить бит «SAVE_ADR_EN»), то новый адрес будет проигнорирован и у модуля останется старый адрес.
- ВАЖНО: запись адреса занимает не менее 30 мс. После сохранения адреса бит «SAVE_ADR_EN» в регистре 0x01 «BITS_0» самостоятельно сбросится в 0.
Регистры:
Карта регистров модуля:
Регистры с адресами 0x02, 0x03, 0x08 - 0x0F зарезервированы, их биты сброшены в 0. Попытка записи данных в эти регистры будет проигнорирована модулем.
Регистры модуля адаптированы к клавиатурам с разным количеством кнопок (от 1 до 10). Каждая кнопка клавиатуры имеет свой номер (нумерация начинается с 0).
Для клавиатуры 4x2, кнопки верхнего ряда пронумерованы от 0 (левая) до 3 (правая), кнопки нижнего ряда пронумерованы от 4 (левая) до 7 (правая).
Для клавиатуры 5x2, кнопки верхнего ряда пронумерованы от 0 (левая) до 4 (правая), кнопки нижнего ряда пронумерованы от 5 (левая) до 9 (правая).
Регистры 0x10 - 0x19 содержат флаги событий и состояний кнопок 0 - 9 соответственно.
Регистры 0x20 - 0x29 содержат время удержания / простоя кнопок 0 - 9 соответственно.
Регистр 0x00 «FLAGS_0» - содержит флаги чтения состояния модуля:
Регистр только для чтения.
- FLG_RESET - Флаг указывает на факт выполнения успешной перезагрузки модуля. Флаг самостоятельно сбрасывается после чтения регистра 0x00 «FLAGS_0».
- FLG_SELF_TEST - Флаг указывает на результат выполнения самотестирования модуля (0-провал, 1-успех). Не поддерживается данным модулем.
- FLG_GET_NAME - Если флаг установлен, значит модуль поддерживает вывод своего названия установкой бита «SET_GET_NAME» в регистре 0x01 «BITS_0».
- RAND_ADR - Если флаг установлен, значит модуль поддерживает генерацию случайного адреса для шины I2C регистрами 0x64 «RANDOM_NUM», «RANDOM_ADR», «BUN_ADR».
- FLG_I2C_UP - Если флаг установлен, значит модуль позволяет управлять подтяжкой линий шины I2C при помощи бита «SET_I2C_UP» регистра 0x01 «BITS_0».
Регистр 0x01 «BITS_0» - содержит биты установки состояния модуля:
Регистр для записи и чтения.
- SET_RESET - Бит запускает программную перезагрузку модуля. О завершении перезагрузки свидетельствует установка флага «FLG_RESET» регистра 0x00 «FLAGS_0».
- SET_SELF_TEST - Бит запускает самотестирование модуля. При успешном завершении самотестирования устанавливается флаг «FLG_SELF_TEST » регистра 0x00 «FLAGS_0». Не поддерживается данным модулем.
- SET_GET_NAME - Бит указывает использовать регистр 0x04 «MODEL» для посимвольного вывода названия модуля. Бит сбрасывается автоматически через 300 мс после его установки. Если флаг «FLG_GET_NAME» регистра 0x00 «FLAGS_0» сброшен, значит модуль не поддерживает посимвольный вывод своего названия.
- BLOCK_ADR - Бит блокирует смену и сохранение адреса для шины I2C. Бит устанавливается автоматически при попытке записи данных в регистры предназначенные только для чтения. Это защищает чип от ненамеренной смены адреса шумами на шине I2C, бит используется в модулях версии 5 и выше. Версия модуля хранится в регистре 0x05 «VERSION».
- SET_I2C_UP - Бит управляет внутрисхемной подтяжкой линий шины I2C. Значение бита сохраняется в FLASH память модуля. Установка бита в «1» приведёт к подтяжке линий SDA и SCL до уровня 3,3 В. На линии I2C допускается устанавливать внешние подтягивающие резисторы и иные модули с подтяжкой до уровня 3,3 В или 5 В, вне зависимости от состояния текущего бита. Если флаг «FLG_I2C_UP» регистра 0x00 «FLAGS_0» сброшен, значит управление подтяжкой не поддерживается модулем.
- SAVE_ADR_EN - Бит разрешает записать новый адрес модуля для шины I2C в FLASH память. Бит самостоятельно сбрасывается после сохранения адреса во FLASH память. Запись адреса выполняется следующим образом: нужно установить бит «SAVE_ADR_EN», после чего записать новый адрес в регистр 0x06 «ADDRESS» с установленным битом «SAVE_FLASH».
Регистр 0x04 «MODEL» - содержит идентификатор типа модуля:
Регистр только для чтения.
- MODEL[7-0] - Для модуля - Клавиатура, I2C-flash - идентификатор равен 0x13.
- Если установлен флаг «FLG_GET_NAME» регистра 0x00 «FLAGS_0» значит модуль поддерживает посимвольный вывод своего названия.
- Установка бита «SET_GET_NAME» регистра 0x01 «BITS_0» включает режим посимвольного вывода названия модуля. При этом в регистре 0x04 «MODEL» появится первый символ названия модуля. В процессе чтения регистра 0x04 «MODEL» он будет возвращать очередной символ названия, вплоть до символа конца строки имеющего код 0x00. Далее цикл повторится.
- Сброс бита «SET_GET_NAME» регистра 0x01 «BITS_0» отключает режим посимвольного вывода названия модуля. Регистр 0x04 «MODEL» вновь будет содержать идентификатор.
Регистр 0x05 «VERSION» - содержит версию прошивки модуля:
Регистр только для чтения.
- VERSION[7-0] - Версия прошивки (от 0x01 до 0xFF).
Регистр 0x06 «ADDRESS» - отвечает за чтение/установку адреса модуля на шине I2C:
Регистр для чтения и записи.
- ADDRESS[6-0] - 7 бит адреса модуля на шине I2C. При чтении возвращается текущий адрес модуля, при записи устанавливается указанный адрес модулю. Допускается указывать адреса в диапазоне: 7 < адрес < 127.
- SAVE_FLASH - Флаг записи адреса в FLASH память модуля.
Флаг имеет значение только при записи данных в регистр.
Если флаг сброшен, то адрес в битах ADDRESS[6-0] будет установлен временно (до отключения питания, или сброса/записи нового адреса). Если флаг установлен, то адрес в битах ADDRESS[6-0] будет сохранён в FLASH память модуля (останется и после отключения питания), но только если в бите «SAVE_ADR_EN» регистра 0x01 «BITS_0» установлена логическая 1. Если флаг «SAVE_FLASH» установлен, а бит «SAVE_ADR_EN» сброшен, то адрес в битах ADDRESS[6-0] не будет установлен ни временно, ни постоянно.
Регистр 0x07 «CHIP_ID» - содержит идентификатор общий для всех модулей серии «Flash»:
Регистр только для чтения.
У всех модулей серии «Flash» в регистре «CHIP_ID» содержится значение 0x3C. Если требуется отличить модули серии «Flash» на шине I2C от сторонних модулей, то достаточно прочитать значение регистров 0x06 «ADDRESS» и 0x07 «CHIP_ID» всех модулей на шине I2C. Если 7 старших битов регистра 0x06 «ADDRESS» хранят адрес совпадающий с адресом модуля, а в регистре 0x07 «CHIP_ID» хранится значение 0x3C, то можно с большой долей вероятности утверждать, что данный модуль является модулем серии «Flash».
Регистр 0x10 «KEY_0» - содержит флаги состояний и событий кнопки 0:
Регистр 0x11 «KEY_1» - содержит флаги состояний и событий кнопки 1:
Регистр 0x12 «KEY_2» - содержит флаги состояний и событий кнопки 2:
Регистр 0x13 «KEY_3» - содержит флаги состояний и событий кнопки 3:
Регистр 0x14 «KEY_4» - содержит флаги состояний и событий кнопки 4:
Регистр 0x15 «KEY_5» - содержит флаги состояний и событий кнопки 5:
Регистр 0x16 «KEY_6» - содержит флаги состояний и событий кнопки 6:
Регистр 0x17 «KEY_7» - содержит флаги состояний и событий кнопки 7:
Регистр 0x18 «KEY_8» - содержит флаги состояний и событий кнопки 8:
Регистр 0x19 «KEY_9» - содержит флаги состояний и событий кнопки 9:
Регистры только для чтения.
- FLG_PUSHED - Флаг нажатия на кнопку. Устанавливается в момент нажатия на кнопку и остаётся установленным пока не будет прочитан. Флаг сбрасывается самостоятельно после чтения данного регистра.
- FLG_RELEASED - Флаг отпускания кнопки. Устанавливается в момент отпускания кнопки и остаётся установленным пока не будет прочитан. Флаг сбрасывается самостоятельно после чтения данного регистра.
- FLG_CHANGED - Флаг смены состояния кнопки. Устанавливается в момент нажатия или отпускания кнопки и остаётся установленным пока не будет прочитан. Флаг сбрасывается самостоятельно после чтения данного регистра. ( CHANGED = PUSHED | RELEASED ).
- FLG_STATE - Флаг состояния кнопки. Установлен пока кнопка нажата и сброшен если она отпущена.
- FLG_TRIGGER - Флаг триггер. Меняет своё состояние с каждым новым нажатием на кнопку (нажали - установился, нажали - сбросился, нажали - установился, ...).
- TIM_HOLD_05[2-0] - Биты хранят значение от 0 до 7 информирующее о времени удержания кнопки. Время удержания кнопки = значение битов «TIM_HOLD_05[2-0]» * 0,5 сек.
Регистр 0x1A «LED_L» - отвечает за управление светодиодами верхнего ряда:
Регистр 0x1B «LED_H» - отвечает за управление светодиодами нижнего ряда:
Регистры для чтения и записи.
- BIT_LED_PWM[2-0] - Биты хранят значение от 0 до 7 определяющее яркость свечения светодиодов своего ряда.
- BIT_LED[4-0] - Биты управления светодиодами своего ряда. Установка бита в «1» приводит к включению соответствующего светодиода, а сброс в «0», к выключению светодиода. «BIT_LED[0]» - управляет крайним левым светодиодом, а «BIT_LED[4]» - крайним правым.
Регистр 0x1C «FIFO_HOLD» - хранит время требуемое для фиксации удержания:
Регистр для чтения и записи.
- FIFO_HOLD[7-0] - Время требуемое для фиксации удержания кнопки (в десятых долях секунд), значение от 0 (0 сек.) до 255 (25,5 сек).
Если нажать любую кнопку клавиатуры, то номер нажатой кнопки сразу попадёт в буфер FIFO содержащий историю нажатых кнопок. Если нажатую кнопку не отпускать, то по истечении времени «FIFO_HOLD[7-0]», кнопка будет считаться удерживаемой и буфер FIFO станет заполняться номером удерживаемой кнопки. - Пример: Откройте на компьютере текстовый редактор, нажмите и не отпускайте любую символьную клавишу Вашей компьютерной клавиатуры. Вы увидите как символ нажатой кнопки, сначала однократно появился в окне, а через несколько долей секунд начал повторно появляться заполняя окно текстового редактора. Время от появления первого символа, до его повторного появления и есть время требуемое для фиксации удержания кнопки.
- Примечание: Содержимое регистра сохраняется в FLASH память модуля клавиатуры.
Регистр 0x1D «FIFO_REPLAY» - время повтора номеров удерживаемой кнопки:
Регистр для чтения и записи.
- FIFO_REPLAY[7-0] - Время между повторными записями номера удерживаемой кнопки в буфер FIFO (в сотых долях секунд), значение от 0 (0 сек.) до 255 (2,55 сек).
Если удерживать нажатой кнопку клавиатуры, то буфер FIFO (содержащий историю нажатых кнопок) будет заполняться номером удерживаемой кнопки каждые «FIFO_REPLAY[7-0]» сек. - Пример: Откройте на компьютере текстовый редактор, нажмите и не отпускайте любую символьную клавишу Вашей компьютерной клавиатуры. Вы увидите как символ нажатой кнопки начал появляться заполняя окно текстового редактора. Время между появлениями символов заполняющих окно текстового редактора и есть время повтора номеров удерживаемой кнопки.
- Примечание: Содержимое регистра сохраняется в FLASH память модуля клавиатуры.
Регистр 0x1E «FIFO_COUNTER» - счётчик буфера FIFO:
Регистр для чтения и записи.
- FIFO_COUNTER[7-0] - Содержит количество номеров кнопок находящихся в буфере FIFO.
- Запись любого значения в регистр 0x1E «FIFO_COUNTER» приведёт к обнулению счетчика FIFO (сбросу значения регистра) и очистке буфера FIFO.
- Чтение из регистра 0x1E «FIFO_COUNTER» не приводит к увеличению адреса регистра, это значит что попытка чтения N байт начиная с регистра 0x1E «FIFO_COUNTER» приведёт к получению N байт из регистра 0x1E «FIFO_COUNTER».
Регистр 0x1F «FIFO» - получение данных из буфера FIFO:
Регистр только для чтения.
- FIFO[7-0] - Служит для побайтового получения данных из буфера FIFO содержащего историю нажатия клавиш (номера нажатых клавиш).
- Если буфер FIFO пуст, то ответом на чтение регистра 0x1F «FIFO» будет значение 0xFF.
- Чтение из регистра 0x1F «FIFO» не приводит к увеличению адреса регистра, это значит что попытка чтения N байт начиная с регистра 0x1F «FIFO» приведёт к получению N байт из регистра 0x1F «FIFO».
- При каждом чтении регистра 0x1F «FIFO», прочитанный байт исчезает из буфера FIFO, а счётчик буфера FIFO, значение которого находится в регистре 0x1E «FIFO_COUNTER», уменьшается на 1.
- При каждом нажатии на клавишу, её номер добавляется в конец буфера FIFO, а счётчик буфера FIFO, значение которого находится в регистре 0x1E «FIFO_COUNTER», увеличивается на 1.
- Пример: Предположим что буфер FIFO пуст (счетчик буфера FIFO равен 0). На клавиатуре были поочерёдно нажаты клавиши с номерами 0,1,2, значит эти номера попали в буфер FIFO (счетчик буфера FIFO равен 3). Далее было прочитано 2 байта из регистра 0x1F «FIFO» (теперь счетчик буфера FIFO равен 1, так как в буфере FIFO остался один байт с номером последней нажатой клавиши - 2), а прочитанными байтами являются номера 0 и 1. Потом были поочерёдно нажаты клавиши 3 и 4, и прочитано 3 байта из регистра 0x1F «FIFO» (теперь счетчик буфера FIFO равен 0, так как в буфере FIFO нет данных), а прочитанными байтами являются номера 2, 3 и 4.
Из примера видно, что в какой очерёдности были нажаты клавиши, в такой очерёдности их номера и были прочитаны из буфера FIFO. - Буфер FIFO ограничен размером в 255 байт, это значит что если не читать данные из буфера FIFO, то он заполнится и каждое новое добавление номера нажатой клавиши в буфер FIFO, будет приводить к исчезновению самого раннего номера хранящегося в буфере (как при чтении одного байта из регистра 0x1F «FIFO» в никуда).
Регистр 0x20 «TIME_KEY_0» - время удержания или простоя кнопки 0:
Регистр 0x21 «TIME_KEY_1» - время удержания или простоя кнопки 1:
Регистр 0x22 «TIME_KEY_2» - время удержания или простоя кнопки 2:
Регистр 0x23 «TIME_KEY_3» - время удержания или простоя кнопки 3:
Регистр 0x24 «TIME_KEY_4» - время удержания или простоя кнопки 4:
Регистр 0x25 «TIME_KEY_5» - время удержания или простоя кнопки 5:
Регистр 0x26 «TIME_KEY_6» - время удержания или простоя кнопки 6:
Регистр 0x27 «TIME_KEY_7» - время удержания или простоя кнопки 7:
Регистр 0x28 «TIME_KEY_8» - время удержания или простоя кнопки 8:
Регистр 0x29 «TIME_KEY_9» - время удержания или простоя кнопки 9:
Регистры только для чтения.
- TIME_KEY[7-0] - Время удержания или простоя кнопки в десятых долях секунд, от 0 (0 сек.) до 255 (25,5 сек). Время сбрасывается в 0 при любом изменении состояния кнопки (была нажата - стала отпущена, или была отпущена - стала нажата), после чего время начинает увеличиваться на 1 каждую десятую долю секунды, пока не достигнет значения 255 (25,5 сек).
- По текущему состоянию кнопки (флаг «FLG_STATE» регистра «KEY») можно определить, относится время регистра «TIME_KEY» к удержанию или простою кнопки.
Регистр 0x2A «ANIMATION» - отвечает за выполнение светодиодной анимации:
Регистр для чтения и записи.
- ANIMATION[7-0] - Содержит номер светодиодной анимации:
- 0 - не выполнять светодиодную анимацию.
- 1 - светодиод включается на «TIME_ANIMATION[7-0]» сек. после каждого нажатия на кнопку.
- 2 - светодиод включается на «TIME_ANIMATION[7-0]» сек. после каждого отпускания кнопки.
- 3 - светодиод включается на «TIME_ANIMATION[7-0]» сек. после нажатия или отпускания.
- 4 - светодиод светится пока нажата его кнопка.
- 5 - светодиод работает как переключатель своей кнопки.
- 6 - светодиод светится если его кнопка удерживается дольше 0,5 сек.
- 7 - светодиод светится при каждом пополнении буфера FIFO номером своей кнопки.
- Представленные режимы анимации актуальны для версии прошивки 4.
В новых версиях, количество режимов анимации может быть увеличено.
Регистр 0x2B «TIME_ANIMATION» - счётчик буфера FIFO:
Регистр для чтения и записи.
- TIME_ANIMATION[7-0] - Время свечения светодиода при выполнении светодиодной анимации, в сотых долях секунд, от 0 (0 сек.) до 255 (2,55 сек). Значение регистра определяет, как долго будет светиться светодиод при выполнении анимации № 1, 2, 3.
Регистры 100+:
У младших версий модулей линейки «FLASH-I2C» нет блока регистров «100+», так же этого блока нет у модулей линейки «Metro», о его наличии свидетельствует установленный флаг «RAND_ADR» в регистре 0x00 «FLAGS_0».
Блок регистров «100+» с адресами от 0x64 (100)10 до 0x75 (117)10 не участвует в работе модуля, он предназначен только для обнаружения модулей с одинаковыми адресами и назначения этим модулям разных адресов, не отключая их от шины I2C.
Карта регистров 100+:
Регистры 0x64-0x65 «RANDOM_NUM» - содержат случайное число:
Регистры только для чтения.
- RANDOM_NUM[15-0] - Содержит двухбайтное случайное число позволяющее определить наличие нескольких устройств с одинаковым адресом.
- Значение из регистров читается одним пакетом (младший и старший байт). После чтения старшего байта, модуль на 5мс перейдёт в режим «молчания». В этом режиме модуль будет отправлять NACK мастеру после получения номера регистра в любых запросах.
- Если прочитать регистры 0x64-0x65 «RANDOM_NUM» дважды, с промежутком между чтениями менее 5мс, то первый раз мы получим два байта случайного числа, а второй раз модуль откажет в чтении, так как отправит NACK. Но это только в том случае, если адрес модуля уникален.
- Если адрес принадлежит нескольким устройствам, то и отвечать на запрос чтения будут несколько устройств. При первом чтении регистров 0x64-0x65 «RANDOM_NUM», биты случайного числа у разных модулей не совпадут, в результате чего один модуль передаст оба байта случайного числа и перейдёт в режим «молчания», а другой модуль (или модули) зафиксирует потерю арбитража и не передаст старший байт, следовательно, и не перейдёт в режим «молчания». Значит при повторном чтении регистров, мы опять получим два байта случайного числа от того модуля который не перешёл в режим «молчания», что будет свидетельствовать о наличии нескольких устройств на одном адресе.
Регистр 0x66 «RANDOM_ADR» - случайный адрес:
Регистр для чтения и записи.
- RANDOM_ADR[7-0] - Позволяет задавать модулю случайный временный адрес, подтверждать временный адрес и получать информацию о состоянии временного адреса.
- Запись 0x0F - Назначить модулю случайный временный адрес на 50 мс.
В регистре 0x06 «ADDRESS» останется значение постоянного адреса. - Запись 0xF0 - Подтвердить назначенный временный адрес до отключения питания.
В регистре 0x06 «ADDRESS» появится назначенный временный адрес. - Чтение 0x55 - Назначен временный случайный адрес на 50 мс.
- Чтение 0xFF - Назначенный временный адрес подтверждён до отключения питания.
- Чтение 0x00 - Временный адрес не назначался или отменён по истечении 50 мс.
- Если на шине несколько устройств имеют одинаковый адрес, то запись значения 0x0F в регистр 0x66 «RANDOM_ADR» этих устройств, приведёт к тому, что каждый модуль сам себе назначит временный случайный адрес на 50 мс. За указанное время следует найти все новые временные адреса устройств и подтвердить их отправив в регистр 0x66 «RANDOM_ADR» значение 0xF0.
- Примечание: Случайный адрес модуль выбирает сам из диапазона от 0x08 до 0x7E включительно, кроме адресов запрещённых регистрами 0x67-0x75 «BUN_ADR».
Регистры 0x67-0x75 «BUN_ADR» - запрещают назначать адреса:
Регистры для чтения и записи.
- BUN_ADR_08 - Бит запрещает назначать адрес 0x08 регистром 0x66 «RANDOM_ADR».
- BUN_ADR_09 - Бит запрещает назначать адрес 0x09 регистром 0x66 «RANDOM_ADR».
- ...
- BUN_ADR_7D - Бит запрещает назначать адрес 0x7D регистром 0x66 «RANDOM_ADR».
- BUN_ADR_7E - Бит запрещает назначать адрес 0x7E регистром 0x66 «RANDOM_ADR».
- Если бит регистров 0x67-0x75 «BUN_ADR» установлен, то модуль не назначит себе случайный временный адрес соответствующий установленному биту.
- Если на шине есть несколько устройств с одинаковым адресом, то отправка команды 0x0F в регистр 0x66 «RANDOM_ADR» этих устройств, приведёт к тому, что каждый модуль сам себе назначит временный случайный адрес на 50 мс. Но вновь назначенный адрес может совпасть с адресом другого модуля на шине I2C, особенно если их много. По этому перед назначением случайного временного адреса рекомендуется записать в регистры 0x67-0x75 «BUN_ADR» все найденные на шине I2C уникальные адреса.
Доступ к данным регистров:
Каждый регистр модуля хранит 1 байт данных. Так как модуль использует интерфейс передачи данных I2C, то и доступ к данным охарактеризован им.
Обмен данными по шине I2C происходит по одному биту за один такт, после каждых переданных 8 бит (1 байта) принимающее устройство отвечает передающему одним битом: «ACK» в случае успешного приёма, или «NACK» в случае ошибки. Пакет приёма/передачи данных начинается сигналом «START» и завершается сигналом «STOP». Первый байт пакета всегда состоит из 7 бит адреса устройства и одного (младшего) бита R/W.
Сигналы интерфейса передачи данных I2C:
- Для удобства восприятия сигналов они выполнены в следующих цветах:
- Зелёный - сигналы формируемые мастером.
- Красный - данные отправляемые мастером.
- Синий - данные отправляемые модулем.
- Фиолетовый - данные отправляемые мастером или модулем.
- «START» - отправляется мастером в начале пакета приема/передачи данных. Сигнал представляет переход уровня линии «SDA» из «1» в «0» при наличии «1» на линии «SCL».
- «STOP» - отправляется мастером в конце пакета приёма/передачи данных. Сигнал представляет переход уровня линии «SDA» из «0» в «1» при наличии «1» на линии «SCL».
- БИТ - значение бита считывается с линии «SDA» по фронту импульса на линии «SCL».
- «ACK» - бит равный 0, отправляется после успешного приёма байта данных.
- «NACK» - бит равный 1, отправляется после байта данных в случае ошибки.
- ПЕРВЫЙ БАЙТ - отправляется мастером, состоит из 7 бит адреса и бита «RW».
- «R/W» - младший бит первого байта данных указывает направление передачи данных пакета, 1 - прием (от модуля к мастеру), 0 - передача (от мастера в модуль).
- «RESTART» - повторный старт, отправляется мастером внутри пакета. Сигнал представляет из себя «START» отправленный не на свободной шине, а внутри пакета.
ВАЖНО: Все изменения на линии «SDA» должны происходить только при наличии «0» на линии «SCL» за исключением сигналов «START», «STOP» и «RESTART».
Запись данных в регистры:
- Отправляем сигнал «START».
- Отправляем первый байт: 7 бит адреса модуля и бит «R/W» равный 0 (запись).
Получаем ответ от модуля в виде одного бита «ACK». - Отправляем второй байт: адрес регистра в который будет произведена запись.
Получаем ответ от модуля в виде одного бита «ACK». - Отправляем третий байт: данные для записи в регистр.
Получаем ответ от модуля в виде одного бита «ACK». - Далее можно отправить четвёртый байт данных для записи в следующий по порядку регистр и т.д.
- Отправляем сигнал «STOP».
Пример записи в один регистр:
Запись значения 0x2A в регистр 0x06 модуля с адресом 0x09:
// Запись в регистр методами библиотеки Wire.h Wire.beginTransmission(0x09); // Инициируем передачу данных в устройство с адресом 0x09. Wire.write(0x06); // Записываем в буфер байт адреса регистра. Wire.write(0x26); // Записываем в буфер байт который будет записан в регистр. Wire.endTransmission(); // Выполняем передачу адреса и байтов из буфера. Функция возвращает: 0-передача успешна / 1 - переполнен буфер для передачи / 2 - получен NACK при передаче адреса / 3 - получен NACK при передаче данных / 4 - другая ошибка.
Пример записи в несколько регистров подряд:
Запись в модуль с адресом 0x09 нескольких значений начиная с регистра 0x12:
В регистр 0x12 запишется значение 0x0F, в следующий по порядку регистр (0x13) запишется значение 0x30 и в следующий по порядку регистр (0x14) запишется значение 0xB1.
// Запись в регистры методами библиотеки Wire.h byte data[3] = {0x0F,0x30,0xB1}; // Определяем массив с данными для передачи. Wire.beginTransmission(0x09); // Инициируем передачу данных в устройство с адресом 0x09. Wire.write(0x12); // Записываем в буфер байт адреса первого регистра. Wire.write(data, 3); // Записываем в буфер 3 байта из массива data. Wire.endTransmission(); // Выполняем передачу адреса и байт из буфера. Функция возвращает: 0-передача успешна / 1 - переполнен буфер для передачи / 2 - получен NACK при передаче адреса / 3 - получен NACK при передаче данных / 4 - другая ошибка.
Чтение данных из регистров:
- При чтении пакет делится на 2 части: запись № регистра и чтение его данных.
- Отправляем сигнал «START».
- Отправляем первый байт: 7 бит адреса модуля и бит «R/W» равный 0 (запись).
Получаем ответ от модуля в виде одного бита «ACK». - Отправляем второй байт: адрес регистра из которого нужно прочитать данные.
Получаем ответ от модуля в виде одного бита «ACK». - Отправляем сигнал «RESTART».
- Отправляем первый байт после «RESTART»: 7 бит адреса и бит «R/W» равный 1 (чтение).
Получаем ответ от модуля в виде одного бита «ACK». - Получаем байт данных из регистра модуля.
Отвечаем битом «ACK» если хотим прочитать следующий регистр, иначе отвечаем «NACK». - Отправляем сигнал «STOP».
Пример чтения одного регистра:
Чтение из модуля с адресом 0x09 байта данных регистра 0x05:
(в примере модуль вернул значение 0x01).
// Чтение регистра методами библиотеки Wire.h byte data; // Объявляем переменную для чтения байта данных. Wire.beginTransmission(0x09); // Инициируем передачу данных в устройство с адресом 0x09. Wire.write(0x05); // Записываем в буфер байт адреса регистра. Wire.endTransmission(false); // Выполняем передачу без установки состояния STOP. Wire.requestFrom(0x09, 1); // Читаем 1 байт из устройства с адресом 0x09. Функция возвращает количество реально принятых байтов. Так как предыдущая функция не установила состояние STOP, то состояние START установленное данной функцией будет расценено как RESTART. data=wire.read(); // Сохраняем прочитанный байт в переменную data.
Пример чтения нескольких регистров подряд:
Чтение из модуля с адресом 0x09 нескольких регистров начиная с регистра 0x05:
(в примере модуль вернул значения: 0x01 из рег. 0x05, 0x13 из рег. 0x06, 0xC3 из рег. 0x07).
// Чтение регистров методами библиотеки Wire.h byte data[3]; // Объявляем массив для чтения данных. Wire.beginTransmission(0x09); // Инициируем передачу данных в устройство с адресом 0x09. Wire.write(0x05); // Записываем в буфер байт адреса регистра. Wire.endTransmission(false); // Выполняем передачу без установки состояния STOP. Wire.requestFrom(0x09, 3); // Читаем 3 байта из устройства с адресом 0x09. Функция возвращает количество реально принятых байтов. Так как предыдущая функция не установила состояние STOP, то состояние START установленное данной функцией будет расценено как RESTART. int i=0; // Определяем счётчик номера прочитанного байта. while( Wire.available() ){ // Выполняем цикл while пока есть что читать из буфера. if(i<3){ // Лучше делать такую проверку, чтоб не записать данные за пределы массива data! data[i] = wire.read(); i++; // Читаем очередной байт из буфера в массив data. } // } //
Примечание:
- Если на линии I2C только один мастер, то сигнал «RESTART» можно заменить на сигналы «STOP» и «START».
- Рекомендуется не выполнять чтение или запись данных чаще 200 раз в секунду.
- Обратите внимание на сигналы «RESTART» и «STOP» в пакетах чтения данных:
- Между фронтом и спадом сигнала «RESTART» проходит фронт импульса на линии «SCL», что расценивается как передача бита равного 1.
- Между сигналом «NACK» и сигналом «STOP» проходит фронт импульса на линии «SCL», что расценивается как передача бита равного 0.
- Эти биты не сохраняются в модулях и не расцениваются как ошибки.
Модуль не поддерживает горячее подключение: Подключайте модуль только при отсутствии питания и данных на шине I2C. В противном случае потребуется отключить питание при уже подключённом модуле.
Пример чтения истории нажатий клавиш из буфера FIFO:
Следующий скетч демонстрирует вывод данных с клавиатуры в монитор.
#include <Wire.h> // Подключаем библиотеку Wire для работы с шиной I2C. const int ADDRESS = 0x09; // Определяем адрес модуля. const int REG_FIFO = 0x1F; // Определяем адрес регистра FIFO. uint8_t i; // Объявляем переменную для хранения номера кнопки считанного из буфера FIFO. // void setup(){ // Serial.begin(9600); // Инициируем связь с монитором последовательного порта на скорости 9600 бит/сек. while(!Serial){;} // Ждём готовность к работе аппаратной шины UART. Wire.setClock(100000L); // Устанавливаем скорость передачи данных по шине I2C. Wire.begin(); // Инициируем работу c шиной I2C в качестве мастера. } // // void loop(){ // Wire.beginTransmission(ADDRESS); // Инициируем передачу данных по шине I2C к устройству с адресом ADDRESS и битом RW=0 (запись). При этом сама передача не начнётся. Wire.write(REG_FIFO); // Функция write() помещает значение своего аргумента в буфер для передачи. Wire.endTransmission(false); // Выполняем инициированную ранее передачу данных (параметр false указывает что состояние STOP устанавливать не требуется). Wire.requestFrom(ADDRESS, 1); // Читаем из модуля с адресом ADDRESS, 1 байт данных в буфер библиотеки Wire. Так как предыдущая функция не установила состояние STOP, то состояние START установленное данной функцией будет расценено как RESTART. if(Wire.available()){ // Если в буфере библиотеки Wire есть данные, то ... i=Wire.read(); // Читаем 1 байт из буфера FIFO в переменную i. if(i!=0xFF){Serial.print(i);} // Выводим прочитанный байт в монитор последовательного порта. } // delay(50); // } //
Обсуждение