TCA8418: контроллер матрицы клавиатуры Печать
Добавил(а) microsin   

TCA8418 представляет собой устройство для сканирования клавиатуры, с интегрированной защитой от статического электричества (ESD). Микросхема может работать от напряжения питания в диапазоне 1.65V .. 3.6V, имеет 18 программируемых ножек ввода/вывода общего назначения (GPIO), которые могут поддерживать до 80 кнопок. Кнопки могут быть организованы в матрицу, или подключены к отдельным ножкам GPIO. Конфигурирование микросхемы, информация о нажатиях кнопок передается через интерфейс I2C (микросхема работает как slave-устройство I2C).

Контроллер клавиатуры сканирует кнопки с защитой от дребезга, и сохраняет информацию о нажатиях в стек FIFO размером 10 байт. У этого стека есть возможность перезаписывать по кругу вводимые значения (overflow wrap), что позволяет запоминать самые последние актуальные нажатия. Ножка прерывания ~INT позволяет сигнализировать внешнему контроллеру о событиях нажатий и отпусканий клавиш либо в реальном времени, либо с частотой, не большей заданной.

Основные особенности контроллера клавиатуры TCA8418:

• Рабочий диапазон напряжений питания 1.65V .. 3.6V.
• С помощью 18 ножек портов GPIO поддерживается опрос до 80 кнопок.
• Поддерживается режим клавиатуры QWERTY плюс расширение портов GPIO (QWERTY Keypad Operation Plus GPIO Expansion).
• Низкий ток потребления в режиме ожидания (Idle): 3 мкА.
• Поддерживается быстрый режим интерфейса I2C: 1 МГц.
• FIFO из 10 байт позволяет сохранить 10 нажатий и отпусканий кнопок.
• Выход ножки прерывания ~INT с открытым стоком.
• Встроенное подавление дребезга с временем 50 мкс.
• Триггер Шмитта по входам SDA и SCL позволяет замедлить перепады на входе и повысить устойчивость к импульсам помех. Типовой гистерезис на уровне порога 1.8V составляет 0.18V.

Области применения TCA8418:

• Смартфоны
• Планшеты
• Панели управления оборудованием HMI (Human-Machine Interface)
• Устройства GPS
• MP3-плееры
• Цифровые камеры

Упрощенная схема контроллера TCA8418:

TCA8418 simplified schematic

Примечание: на рис. 1 показано только 7 используемых GPIO для сканирования матрицы кнопок, хотя всего имеется 18 портов GPIO.

[Цоколевка корпуса и назначение выводов]

Корпус WQFN24, вид сверху:

TCA8418 WQFN24 package pinout

Назначение выводов:

Имя Тип Описание
1 ROW7 I/O Либо порт GPIO, либо строка в матрице клавиатуры. Не используемые ножки ROWx должны быть подтянуты к VCC через pull-up резистор.
2 ROW6
3 ROW5
4 ROW4
5 ROW3
6 ROW2
7 ROW1
8 ROW0
9 COL0 Либо порт GPIO, либо столбец в матрице клавиатуры. Не используемые ножки COLx должны быть подтянуты к VCC через pull-up резистор.
10 COL1
11 COL2
12 COL3
13 COL4
14 COL5
15 COL6
16 COL7
17 COL8
18 COL9
19 GND - Земля, минус питания, общий провод для всех сигналов.
20 ~RESET I Вход сброса, активный уровень лог. 0. Если не используется, то соедините с VCC через pull-up резистор.
21 VCC - Напряжение питания в диапазоне от +1.65V до +3.6V.
22 SDA I/O Последовательные данные интерфейса. Соедините с VCC через pull-up резистор.
23 SCL Последовательные такты интерфейса. Соедините с VCC через pull-up резистор.
24 ~INT O Выход сигнала прерывания, активный уровень лог. 0. Соедините с VCC через pull-up резистор.

Примечание: в столбце Тип указан тип вывода. I/O обозначает вход и выход, I вход, O выход.

[Предельные допустимые значения(1)]

Имя Комментарий
min MAX Ед.
VCC Напряжение питания. -0.5 4.6 V
VI Диапазон входного напряжения(2) -0.5 4.6
VO Диапазон уровней напряжения, которое может быть подано на выход, когда он находится в состоянии высокого сопротивления или в состоянии отключения питания(2) -0.5 4.6
Диапазон выходного напряжения в состояниях лог. 0 или лог. 1(2) -0.5 4.6
IIK Входной ток VI < 0   ±20 мА
IOK Выходной ток VO < 0   ±20
IOL Непрерывный выходной ток лог. 0 порт, SDA VO = 0V .. VCC   50
~INT   25
IOH Непрерывный выходной ток лог. 1 порт   50
Tstg Температура хранения -65 150 °C

Примечания:

(1) Стрессовые значения, перечисленные в таблице 2, могут привести к необратимому повреждению устройства. Эти параметры указаны только для справки, не подразумевается работа устройства в таких условиях или в условиях, отличающихся от рекомендованных (см. далее таблицу 4). Длительная работа в условиях, перечисленных в таблице 2, может повлиять на надежность устройства.
(2) Пределы отрицательного входного и выходного напряжения могут быть превышены, если наблюдаются предельные входные и выходные токи.

[Параметры защиты от ESD]

Имя Комментарий MAX Ед.
VESD Модель тела человека (Human Body Model, HBM), по стандарту ANSI/ESDA/JEDEC JS-001, все выводы(1) ±2000 V
Charged Device Model (CDM), по стандарту JEDEC JESD22-C101, все выводы(2) ±1000  

Примечания:

(1) Документ JEDEC JEP155 устанавливает, что 500V HBM позволяет безопасно реализовать производство со стандартным контролем ESD.
(2) Документ JEDEC JEP157 устанавливает, что 250V CDM позволяет безопасно реализовать производство со стандартным контролем ESD.

[Рекомендуемые рабочие условия]

Имя Комментарий
min MAX Ед.
VCC Напряжение питания. 1.65 3.6 V
VIH Напряжение лог. 1 на входе SCL, SDA, ROW0–7, COL0–9, ~RESET 0.7 × VCC 3.6
VIL Напряжение лог. 0 на входе –0.5 0.3 × VCC
IOH Выходной ток лог. 1 ROW0–7, COL0–9   10 мА
IOL Выходной ток лог. 0   25
TA Температура окружающей среды -40 125 °C

[Температурные параметры]

Имя Термальная метрика(1) TCA8418
RTW (WQFN)
24 вывода
Ед.
RθJA Температурное сопротивление кристалл - окружающая среда
38.9 °C/W
RθJC(top) Температурное сопротивление кристалл - корпус (верхняя сторона)
40.6
RθJB Температурное сопротивление кристалл - печатная плата 17.2
ψJT Характеристический параметр кристалл - верхняя сторона 0.9
ψJB Характеристический параметр кристалл - печатная плата 17.2
RθJC(bot) Температурное сопротивление кристалл - корпус (нижняя сторона) 6.6

Примечание (1): для дополнительной информации по температурным метрикам см. документ SPRA953 [3].

[Электрические характеристики]

Параметры указаны для напряжения питания VCC в диапазоне 1.65V .. 3.6V, если не указано нечто иное.

Имя Параметр Условия тестирования
VCC min Typ MAX Ед.
VIK Напряжение на входном защитном диоде II = -18 мА 1.65 .. 3.6V -1.2   81.92 V
VPORR Напряжение порога сброса POR при нарастании VCC VI = VCC или GND, IO = 0 1.03   1.43
VPORF Напряжение порога сброса POR при спаде VCC 0.76   1.15
VOH Напряжение лог. 1 для выходов ROW0–7, COL0–9 IOH = –1 мА 1.65V 1.25    
IOH = –8 мА 1.65V 1.2    
2.3V 1.8    
3V 2.6    
IOH = –10 мА 1.65V 1.1    
2.3V 1.7    
3V 2.5    
VOL Напряжение лог. 0 для выходов ROW0–7, COL0–9 IOL = 1 мА 1.65V     0.4
IOL = 8 мА 1.65V     0.45
2.3V     0.25
3V     0.25
IOL = 10 мА 1.65V     0.6
2.3V     0.3
3V     0.25
IOL SDA VOL = 0.4V 1.65 .. 3.6V 3     мА
  ~INT и ~CAD_INT 3    
II SCL, SDA, ROW0–7, COL0–9, ~RESET VI = VCCI или GND     1 мкА
RINT Значение сопротивления внутреннего резистора подтяжки (pull-up) ROW0–7, COL0–9     105   кОм
ICC Потребляемый ток VI на SDA, ROW0–7, COL0-9 равно VCC или GND, IO = 0, I/O входы fSCL = 0 кГц Генер. OFF 1.65 .. 3.6V     10 мкА
Генер. ON     18
fSCL = 400 кГц 1 нажатие кнопки 1.65V     60
3.6V     90
fSCL = 1 МГц 1.65V     65
3.6V     153
fSCL = 400 кГц GPI в лог. 0 (разрешены pull-up)(1) 1.65 .. 3.6V     55
fSCL = 1 МГц     65
fSCL = 400 кГц GPI в лог. 0 (pull-up запрещены)     15
fSCL = 1 МГц     24
fSCL = 400 кГц Активен 1 выход GPO     55
fSCL = 1 МГц     65
CI SCL VI = VCCI или GND 1.65 .. 3.6V   6 8 пФ
CIO SDA VIO = VCC или GND   10 12.5
ROW0–7, COL0–9   5 6

Примечание (1): подразумевается, что разрешен один GPIO.

[Требования интервалов времени к интерфейсу I2C]

Параметры показаны для рекомендованного диапазона температур окружающей среды. Диаграммы см. на рис. 16.

Параметр
STANDARD MODE FAST MODE
HIGH-SPEED MODE(2) Ед.
min MAX min MAX min MAX
Рабочая частота SCL fSCL 0 100 0 400 0 1000 кГц
Время интервала лог. 1 SCL tsch 4   0.6   0.26   мкс
Время интервала лог. 0 SCL tscl 4.7   1.3   0.5  
Длительность "иголки" tsp   50   50   50 нс
Время установки данных tsds 250   100   50  
Время удержания данных tsdh 0   0   0  
Время нарастания уровня на входе ticr   1000 20 + 0.1Cb(1)  300   120
Время спада уровня на входе ticf   300  
Время спада уровня на выходе; емкость шины 10 пФ .. 400 пФ tocf   300 300   120 мкс
Время свободного состояния шины (idle) между сигналами STOP и START tbuf 4.7   1.3   0.5  
Время установки START или REPEATED START tsts 4.7   0.6   0.26  
Время удержания START или REPEATED START tsth 4   0.6   0.26  
Время установки STOP tsps 4   0.6   0.26  
Время достоверности данных от SCL=0 до достоверного выхода SDA tvd(data)   1   0.9   0.45
Время достоверности данных для ACK; сигнал ACK от SCL = 0 до SDA (выход) = 0 tvd(ack)   1   0.9   0.45

Примечания:

(1) Cb = общая емкость одной линии шины в пФ.
(2) Другое название этого режима FAST MODE PLUS (FM+).

[Требования к интервалам сброса]

Параметры показаны для рекомендованного диапазона температур окружающей среды. Диаграммы времени см. на рис. 19.

Имя Комментарий
min MAX Ед.
tW Длительность импульса сброса 120(1)   мкс
tREC Время восстановления из сброса
tRESET Время до сброса

Примечание (1): схема подавления дребезга GPIO (debounce) пропускает каждую ножку входа GPIO через двухкаскадную схему регистров. Оба этих регистра тактируются одинаковой тактовой частотой, предположительно непрерывной, с номинальным периодом 50 мкс. Когда на входе меняется состояние, новое состояние защелкивается на первом каскаде в одном периоде тактов. Если на следующем такте оба состояния одинаковые, то входной сигнал переходит на второй регистр, и далее на остальные схемы. Поскольку состояния входов изменяются асинхронно по отношению к частоте тактов, может пройти любое время от 0 до 50 мкс до запоминания сигнала в первом каскаде. Таким образом, общее время дебоунсинга может доходить до 100 мкс. И если учитывать понижение частоты тактов, спецификация задержки расширяется до 120 мкс.

[Характеристики переключения]

Имя Параметр   от до min MAX Ед.
tIV Время достоверности прерывания Событие кнопки, или кнопки, разблокировки, или переполнения FIFO ROW0–7, COL0-9 ~INT 20 60 мкс
GPI_INT с разрешенным подавлением дребезга 40 120
GPI_INT с запрещенным подавлением дребезга 10 30
tIR Время задержки сброса прерывания SCL ~INT   200 нс
tPV Время достоверности выходных данных SCL ROW0–7, COL0-9   400
tPS Время установки входных данных порт SCL 0  
tPH Время удержания входных данных порт SCL 300  

[Характеристики опроса кнопок(1)]

Параметр min MAX Ед.
Время от нажатия до его детектирования   25 мкс
Время от отпускания до его детектирования   25
Таймер разблокировки клавиатуры (keypad unlock timer)   7 сек
Таймер маскирования прерывания клавиатуры (keypad interrupt mask timer)   31
Подавление дребезга контактов   60 мс

Примечание (1): показанные в таблице min и MAX интервалы опроса кнопок действуют для всех режимов скоростей передачи I2C.

[Типовые характеристики]

Графики характеристик указаны для TA = 25°C (если не указано нечто иное).

TCA8418 Supply Current vs Temperature fig01 TCA8418 Standby Supply Current vs Temperature fig02
Рис. 1. Ток потребления в зависимости от температуры. Рис. 2. Ток потребления режима Standby в зависимости от температуры.
TCA8418 Supply Current vs Supply Voltage fig03 TCA8418 IO Sink Current vs Output Low Voltage fig04
Рис. 3. Ток потребления в зависимости от напряжения питания. Рис. 4. Зависимость выходного напряжения лог. 0 от втекающего тока ножки I/O (при VCC = 1.65V).
TCA8418 IO Sink Current vs Output Low Voltage fig05 TCA8418 IO Sink Current vs Output Low Voltage fig06
Рис. 5. Зависимость выходного напряжения лог. 0 от втекающего тока ножки I/O (при VCC = 1.8V). Рис. 6. Зависимость выходного напряжения лог. 0 от втекающего тока ножки I/O (при VCC = 2.5V).
TCA8418 IO Sink Current vs Output Low Voltage fig07 TCA8418 IO Sink Current vs Output Low Voltage fig08
Рис. 7. Зависимость выходного напряжения лог. 0 от втекающего тока ножки I/O (при VCC = 3.3V). Рис. 8. Зависимость выходного напряжения лог. 0 от втекающего тока ножки I/O (при VCC = 3.6V).
TCA8418 IO Low Voltage vs Temperature fig09 TCA8418 IO Source Current vs Output High Voltage fig10
Рис. 9. Напряжение лог. 0 ножки IO в зависимости от температуры. Рис. 10. Взаимозависимость вытекающего тока ножки I/O и выходного уровня лог. 1 (VCC = 1.65V).
TCA8418 IO Source Current vs Output High Voltage fig11 TCA8418 IO Source Current vs Output High Voltage fig12
Рис. 11. Взаимозависмость вытекающего тока ножки I/O и выходного уровня лог. 1 (VCC = 1.8V). Рис. 12. Взаимозависмость вытекающего тока ножки I/O и выходного уровня лог. 1 (VCC = 2.5V).
TCA8418 IO Source Current vs Output High Voltage fig13 TCA8418 IO Source Current vs Output High Voltage fig14
Рис. 13. Взаимозависимость вытекающего тока ножки I/O и выходного уровня лог. 1 (VCC = 3.3V). Рис. 14. Взаимозависимость вытекающего тока ножки I/O и выходного уровня лог. 1 (VCC = 3.6V).
TCA8418 IO High Voltage vs Temperature fig15
Рис. 15. Напряжение лог. 1 ножки I/O
в зависимости от температуры.

[Информация от измерении параметров]

Конфигурация нагрузки ножки SDA:

TCA8418 SDA load configuration

TCA8418 I2C Interface Load Circuit And Voltage Waveforms fig16

Рис. 16. Диаграммы сигналов (байт 1 адрес I2C, байты 2 и 3 данные P-порта) при нагруженной ножке SDA.

Примечания:

(A) CL включает емкость пробника и емкость jig. tocf измерено с CL 10 пФ или 400 пФ.
(B) На все входы подаются сигналы от генераторов со следующими характеристиками: PRR ≤ 10 МГц, ZO = 50 Ом, tr/tf ≤ 30 нс.
(C) Все параметры и формы сигналов не применимы ко всем устройствам.

Конфигурация тестирования ножки прерывания ~INT:

TCA8418 INT pin load configuration

TCA8418 Interrupt Load Circuit And Voltage Waveforms fig17

Рис. 17. Форма сигналов на схеме нагрузки прерывания.

Примечания:

(A) CL включает емкость пробника и емкость jig.
(B) Сигналы на всех входах предоставлены генераторами со следующими характеристиками: PRR ≤ 10 МГц, ZO = 50 Ом, tr /tf ≤ 30 нс.
(C) Все параметры и формы сигналов не применимы ко всем устройствам.

Конфигурация нагрузки P-порта:

TCA8418 P PORT load configuration

TCA8418 P Port Load Circuit And Timing Waveforms fig18

Рис. 18. Форма сигналов на схеме нагрузки P-порта.

Конфигурация нагрузки ножки SDA:

TCA8418 SDA load configuration2

Конфигурация нагрузки P-порта:

TCA8418 P PORT load configuration2

TCA8418 Reset Load Circuits And Voltage Waveforms fig19

Рис. 19. Форма сигналов на схеме нагрузки сброса.

Примечания:

(A) CL включает емкость пробника и емкость jig.
(B) Сигналы на всех входах предоставлены генераторами со следующими характеристиками: PRR ≤ 10 МГц, ZO = 50 Ом, tr /tf ≤ 30 нс.
(C) Выходы измерялись по одному, с одним переходом на измерение.
(D) Ножки I/O сконфигурированы как входы.
(E) Все параметры и формы сигналов не применимы ко всем устройствам.

[Описание функционала]

TCA8418 поддерживает до 10 столбцов и до 8 строк матрицы клавиатуры, давая возможность подключить до опрашиваемых 80 кнопок. Для организации матрицы клавиатуры может быть сконфигурирована любая комбинация из этих столбцов и строк. Конфигурирование матрицы осуществляется установкой лог. 1 в соответствующие регистры столбцов и строк (регистры KP_GPIO, см. таблицу 9). После того, как столбцы и строки, соединенные с матрицей клавиатуры, были добавлены, контроллер TCA8418 будет опрашивать этот массив кнопок, и также будет работать с любыми сконфигурированными как входы ножками GPIO.

Функциональная блок-схема TCA8418:

TCA8418 Functional Block Diagram

Key Event Table. Контроллер TCA8418 может быть сконфигурирован для поддержки многих различных конфигураций клавиатур. Все 18 ножек GPIO для строк и столбцов опрашиваемой матрицы могут поддерживать до 80 кнопок (режим матрицы). Другой вариант подключения опрашиваемых кнопок - без матрицы, использование 18 ножек GPIO как входы (режим GPI) для прямого подключения до 18 кнопок, просто замыкающих вход на GND. Также доступна любая комбинация опрашиваемой матрицы - например, может быть матрица кнопок 3 x 4, с использованием оставшихся 11 ножек GPIO под любые цели ввода/вывода.

Для обоих типов подключения кнопок (матрица и GPI) в стек событий FIFO может быть добавлено событие кнопки (key event). Значния, которые добавляются в FIFO, зависят от настроенной конфигурации (матрица или GPI), и на каком порте было прочитано нажатие. Таблицы ниже показывают значения, которые соответствуют обоим конфигурациям (Key Event Table, таблица событий кнопок).

Значение кодов кнопок ниже представлены десятичными, поскольку позиция десятков в коде используется для обозначения строки, а позиция единиц для обозначения столбца. Это самый понятный и удобный способ нумерации кодов кнопок.

Таблица 1. Key Event Table, таблица событий кнопок (режим матрицы, кодирование позиций кнопок).

  C0 C1 C2 C3 C4 C5 C6 C7 C8 C9
R0 1 2 3 4 5 6 7 8 9 10
R1 11 12 13 14 15 16 17 18 19 20
R2 21 22 23 24 25 26 27 28 29 30
R3 31 32 33 34 35 36 37 38 39 40
R4 41 42 43 44 45 46 47 48 49 50
R5 51 52 53 54 55 56 57 58 59 60
R6 61 62 63 64 65 66 67 68 69 70
R7 71 72 73 74 75 76 77 78 79 80

Таблица 2. Таблица событий кнопок (режим GPI, события строк).

R0 R1 R2 R3 R4 R5 R6 R7
97 98 99 100 101 102 103 104

Таблица 3. Таблица событий кнопок (режим GPI, события столбцов).

C0 C1 C2 C3 C4 C5 C6 C7 C8 C9
105 106 107 108 109 110 111 112 113 114

События GPI. Столбцы или входы, сконфигурированные как GPI, могут быть запрограммированы для вхождения как часть в Key Event Table, чтобы они могли генерировать прерывание события кнопки (Key Event Interrupt). Тогда Key Event Interrupt, вызванное GPI, будет следовать такому же процессу обработки, как и Key Event Interrupt, вызванное нажатием клавиши в матрице.

GPI, сконфигурированные как часть Key Event Table, позволяют мониторить одиночные кнопки так же, как другие прерывания входов GPI. Как часть таблицы событий, GPI представлены десятичными значениями от 97 до 114. Строки R0-R7 представлены кодами 97 .. 104, и столбцы  C0-C9 представлены кодами 105 .. 114.

Для ножек GPI, которые установлены активными на лог. 1, и добавлены в Key Event Table, конечный автомат будет добавлять событие к счетчику событий код в таблицу событий всякий раз, когда эта ножка GPI перейдет от лог. 0 к лог. 1. Если ножка GPI установлена активной на лог. 0, то переход этой ножки от лог. 1 к лог. 0 будет считаться нажатием, и это событие также будет добавлено к счетчику событий и в таблицу событий. Как только выполнится условие генерации прерывания, машина состояний установит внутри себя прерывание для противоположного состояния, запрограммированного в регистр, чтобы избежать опроса для состояния отпускания, экономя тем самым потребляемый ток. Как только было достигнуто состояние отпускания, оно будет добавлено к таблице событий. Нажатие и отпускание все еще будут индицироваться битом 7 в регистре событий.

События GPI также могут использоваться как последовательности разблокирования. Когда установлен бит GPI_EM, события GPI не будут отслеживаться, когда клавиатура заблокирована. Когда клавиатура заблокирована, бит GPI_EM должен быть очищен для отслеживаемых событий GPI, чтобы они попадали в счетчик событий и таблицу событий.

Чтение событий кнопок (FIFO). TCA8418 содержит встроенный 10-байтный event FIFO, где сохраняются любые нажатия или отпускания кнопок, которые были добавлены в Key Event Table. Все строки (ROW) и столбцы (COL), добавленные в матрицу клавиатуры программированием регистров KP_GPIO1-KP_GPIO3, будут добавлять события в этот FIFO. Любые ножки GPI, сконфигурированные записью лог. 1 в регистры GPI_EM1-GPI_EM3, также будут генерировать события для FIFO.

Когда хосту (I2C master) нужно прочитать FIFO, рекомендуется следовать описанной ниже процедуре.

1. Прочитать регистр INT_STAT (0x02), чтобы определить, выставлен ли сигнал прерывания на выводе ~INT. Если установлен GPI_INT или K_INT, то произошло событие кнопки, и оно было сохранено в FIFO.
2. Прочитать регистр KEY_LCK_EC (0x03), его биты [3:0] покажут, сколько событий сохранено в FIFO.
3. Прочитать регистр событий KEY_EVENT_A (0x04). Значение 0 бита 7 обозначает отпускание кнопки, 1 обозначает нажатие. Биты [6:0] показывают, какая была нажата кнопка по отношению к Key Event Table. Каждое такое чтение регистра событий будет уменьшать на 1 значение счетчика событий в KEY_LCK_EC[3:0], и события будут извлекаться из FIFO.
4. Повторять шаг 3 до тех пор, пока не обнулится поле бит счетчика событий (KEY_LCK_EC[3:0] = 0), или пока не станет нулем регистр событий (KEY_EVENT_A = 0). Это будет означать, что FIFO пуст.
5. Сбросить флаг прерываний INT_STAT, который вызвал прерывание, путем записи 1 в определенный бит.

В качестве примера рассмотрим следующие нажатия кнопок (таблица 4).

Таблица 4. Пример последовательности событий клавиатуры.

Номер события Key (десятичное значение) Нажатие/отпускание
1 1 Нажатие
2 32 Нажатие
3 1 Отпускание
4 32 Отпускание
5 23 Нажатие
6 23 Отпускание
7 45 Нажатие
8 41 Нажатие
9 41 Отпускание
10 45 Отпускание

Если имела место последовательность событий из таблицы 4, то при выполнении рекомендуемых шагов по чтению FIFO хост увидит следующую информацию (таблица 5). Информация на вершине списка соответствует первоначальному чтению регистра KEY_LCK_EC[3:0].

Таблица 5. Пример чтения событий из FIFO.

Значение KEY_LCK_EC[3:0] Значение KEY_EVENT_A (BIN/HEX) Key (десятичное значение) Нажатие/отпускание
10 N/A N/A N/A
9 1 000 0001 / 0x81 1 Нажатие
8 1 010 0000 / 0xA0 32 Нажатие
7 0 000 0001 / 0x01 1 Отпускание
6 0 010 0000 / 0x20 32 Отпускание
5 1 001 0111 / 0x97 23 Нажатие
4 0 001 0111 / 0x17 23 Отпускание
3 1 010 1101 / 0xAD 45 Нажатие
2 1 010 1001 / 0xA9 41 Нажатие
1 0 010 1001 / 0x29 41 Отпускание
0 0 010 1101 / 0x2D 45 Отпускание

Key Event Overflow(1). TCA8418 может обработать переполнение key event FIFO. Такое переполнение возникнет, когда FIFO полностью заполнен событиями (в него было сохранено 10 событий кнопок), и возникло новое событие. Это значит, что TCA8418 не может запомнить в своем внутреннем буфере большее количество информации о нажатиях. Когда произошло такое переполнение, установится бит OVR_FLOW_INT в регистре INT_STAT, и если установлен бит OVR_FLOW_IEN в регистре CFG, то выход ~INT установится в лог. 0 для информирования хоста о переполнении FIFO.

Примечание (1): обратите внимание, что старший бит значения KEY_EVENT_A обозначает нажатие или отпускание кнопки. 1 обозначает нажатие, 0 отпускание.

TCA8418 может обработать переполнение одним из двух методов, в зависимости от значения бита OVR_FLOW_M в регистре CFG (таблица 6). Подробнее про поведение переполнения см. секцию Overflow Errata.

Таблица 6. Бит OVR_FLOW_M.

Значение OVR_FLOW_M Режим переполнения Поведение
1 Разрешен Переполнение приедет к сдвигу всех данных событий так, что новые данные события попадут в FIFO, а самые старые данные данные будут отброшены.
0 Запрещен Данные, вызвавшие переполнение, не попадут в FIFO и будут отброшены.

Рассмотрим следующий пример: FIFO заполнен нажатиями, и образовалось новое нажатие. Это новое нажатие соответствует кнопке 2 (0x82 в hex-представлении события нажатия кнопки 2). Тогда событие переполнение будет обработано следующим образом, см. таблицу 7:

Таблица 7. Пример обработки Key Event Overflow.

Регистр FIFO
Оригинальное значение
После события нажатия Key 1 (0x82)
OVR_FLOW_M = 1 OVR_FLOW_M = 0
A 0x81 0xA0 0x81
B 0xA0 0x01 0xA0
C 0x01 0x20 0x01
D 0x20 0x97 0x20
E 0x97 0x17 0x97
F 0x17 0xAD 0x17
H 0xAD 0xA9 0xAD
I 0xA9 0x29 0xA9
J 0x29 0x2D 0x29
K 0x2D 0x82 0x2D

Keypad Lock/Unlock. Пользователь может заблокировать клавиатуру с помощью функции lock/unlock. Клавиатура блокируется установкой BIT6 в регистре KEY_LCK_EC, что может предотвратить выдачу прерываний событий клавиатуры и отключить запись событий. Разблокировка кнопок может быть запрограммирована любым значением кнопки в матрице клавиатуры или любым из входов (GPI), которые введены в Key Event Table. Когда таймер маски прерываний блокировки клавиатуры не равен 0, пользователю нужно нажать 2 специальные клавиши, прежде чем будет сгенерировано прерывание keylock или будут записаны события клавиатуры. Прерывание события кнопки генерируется при первом нажатии пользователем на любую кнопку. Это первое прерывание может использоваться для включения LCD и отображения сообщения о необходимости разблокировки клавиатуры. Затем процессор прочитает регистр состояния блокировки (lock status register) чтобы увидеть, заблокирована ли клавиатураd. Следующее прерывание (keylock interrupt) не будет генерироваться до тех пор, пока обе последовательности кнопок разблокировки не будут правильными. Если корректные кнопки разблокировки не были нажаты до истечения таймера маски, то машина состояния вернется к началу этой процедуры.

Рекомендуется выполнить следующую процедуру для блокировки клавиатуры:

1. Определиться, какие кнопки будут использоваться для последовательности разблокировки. Для этого в регистры UNLOCK1 и UNLOCK2 нужно записать значения кнопок из Key Event Table.
2. Должна быть установлена длительность таймера от UNLOCK1 до UNLOCK2 вводом желаемого значения в секундах (допустимы значения от 0 до 7 секунд) в поле бит [2:0] регистра KP_LCK_TMR.
3. Если нужна маска прерываний (см. далее секцию "Keypad Lock Interrupt Mask Timer"), то должна быть введена желаемая длительность маски прерываний (допустимый диапазон от 0 до 31 секунд) в поле бит [7:3] регистра KP_LCK_TMR.
4. Когда хост готов заблокировать клавиатуру, он должен записать 1 в бит K_LCK_EN bit (BIT6) регистра KEY_LCK_EC. Это действие заблокирует клавиатуру.
5. Если хосту надо программно разблокировать клавиатуру (без нажатия пользователем нужной последовательности кнопок), он должен записать 0 в бит K_LCK_EN bit (BIT6) регистра KEY_LCK_EC. Это действие разблокирует клавиатуру.

TCA8418 Keypad Lock Flowchart fig20

Рис. 20. Алгоритм блокировки клавиатуры.

Keypad Lock Interrupt Mask Timer. Функция Keypad Lock/Unlock контроллера TCA8418 дает возможность пользователю прекратить генерацию событий кнопок путем блокировки клавиатуры. С этим связана функция таймера маски прерываний (interrupt mask timer) блокировки клавиатуры, которая позволяет генерировать только оно прерывание, когда была нажата одна первая клавиша во время заблокированного состояния клавиатуры. Обычное назначение этой функции - дать пользователю понять, что прибор не завис, просто активирована функция блокировки клавиатуры (например, путем включения подсветки LCD и/или вывода сообщения о необходимости разблокировать клавиатуру). Обратите внимание, что этот interrupt mask timer может также использоваться для ограничения количества прерываний, генерируемых на определенном интервале времени.

Разрешается interrupt mask timer путем установки поля бит [7:3] регистра KP_LCK_TIMER. Значение в этом поле может быть любым в диапазоне от 0 до 31 секунд (значение 0 запретит эту функцию interrupt mask). Когда клавиатура заблокирована, и interrupt mask timer установлен в ненулевое значение, то это разрешит функцию таймера маски прерываний. Эта маска ограничивает количество генерируемых прерываний. Обычно эта возможность используется для совместного использования Keypad Lock/Unlock, чтобы зажечь экран LCD и вывести сообщение "клавиатура заблокирована". Проще всего объяснить работу этой функции на следующем примере. Представим себе мобильное устройство с экраном LCD, подсветка которого выключается после 10 прекращения активности пользователя (для экономии энергии). Обычно прерывание для процессора снова включит подсветку LCD. Без функции interrupt mask timer когда клавиатура заблокирована, прерывания от неё не генерируются, и подсветка экрана не включится. Для рассмотрения примера ниже см. алгоритм на рис. 20:

1. Поскольку подсветка выключится через 10 секунд, если не поступают прерывания от клавиатуры, interrupt mask timer (KP_LCK_TIMER[7:3]) получает значение настройки на 10 секунд. Затем клавиатура блокируется.
2. Когда было обнаружено первое нажатие, контроллер TCA8418 пошлет хосту одно прерывание, хост запустится и начнет обратный отсчет 10 секунд.
3. Если в течение 10 секунд не была нажата требуемая последовательность разблокировки, никакие прерывания хосту посылаться не будут, и подсветка снова выключится.
4. После того, как истечет время 10 секунд таймера, если было другое нажатие на кнопку, когда клавиатура заблокирована (независимо от того, корректная ли это кнопка разблокировки, или нет), будет сгенерировано другое прерывание (и только оно одно), и 10-секундный обратный отсчет начнется снова.

Поддержка Control-Alt-Delete. Вместе с обработкой обычных клавиатурных нажатий TCA8418 может поддерживать функцию нажатия клавиш Ctrl-Alt-Del (CAD). Эта функция дает возможность хосту распознать специальную комбинацию клавиш и отреагировать на неё должным образом. TCA8418 распознает нажатие Ctrl-Alt-Del, если одновременно были нажаты кнопки 1, 11 и 21. Эти кнопки связаны со значениями клавиш, перечисленных в Key Event Table. Обратите внимание, что эта комбинация кнопок, которая вызывает прерывание CAD, не настраивается, так что для неё обязательно назначаются кнопки 1, 11 и 21. Для дополнительной информации см. секцию "CAD Interrupt Errata".

Выход прерывания (ножка ~INT). По любому нарастанию или спаду уровня на ножке порта, настроенного в режим ввода, будет сгенерировано прерывание. После времени tiv сигнал ~INT становится достоверным. Сброс схемы прерывания достигается, когда данные на порте меняются на свое исходное состояние, или когда были прочитаны данные порта, который сгенерировал прерывание. Сброс происходит в режиме считывания на бите подтверждения (ACK) или на бите отсутствия подтверждения (NACK) после переднего фронта сигнала SCL. Прерывания, которые возникли в момента тактового импульса бита ACK или NACK, могут быть потеряны (или быть очень короткими по длительности) из-за сброса прерывания во время этого импульса. Каждое изменение уровня I/O после сброса прерывания детектируется и передается как ~INT.

Чтение или запись в другое устройство не влияет на схему прерывания, и ножка, сконфигурированная как выход, не может генерировать прерывание. Перевод ножки I/O из режима выхода в режим входа может вызвать ложное прерывание, если состояние вывода не соответствует содержимому регистра входа порта.

Ножка выхода ~INT реализована как открытый сток, и требует верхнего подтягивающего резистора (pull-up) на шину питания VCC, в зависимости от приложения. Если сигнал ~INT подается обратно на хост, который предоставляет сигнал SCL для TCA8418, то ножка ~INT должна быть подтянута к VCC. Если нет, то ножка ~INT может быть подтянута к VCC.

Конфигурирование прерывания 50 мкс. TCA8418 предоставляет возможность снять сигнал прерываний через 50 мкс, в то время как присутствует не обработанное прерывание. Когда бит INT_CFG в регистре 0x01 установлен, любая попытка очистить бит прерывания, когда ножка прерывания уже установлена, приведет к снятию прерывания через 50 мкс. Когда бит INT_CFG очищен ~INT остается установленным, если хост пытается очистить прерывание. Эта функция обычно полезна при разработке firmware хоста и приложений, обрабатывающих прерывания по перепаду.

[Функциональные режимы TCA8418]

Power-On Reset (POR). Когда подается питание на VCC (напряжение на VCC нарастает, начинаясь от 0V), внутренняя схема сброса по питанию (power-on reset) удерживает TCA8418 в состоянии сброса, пока уровень VCC не достигнет VPORR. В этот момент состояние сброса освобождается, и регистры TCA8418 и машина состояния I2C/SMBus инициализируются в свои значения по умолчанию. После этого VCC должно опуститься ниже VPORF и подняться опять до рабочего напряжения, чтобы произошел новый цикл сброса по питанию. См. секцию "Рекомендации по источнику питания" для дополнительной информации по требованиям к сбросу по питанию.

Powered (Key Scan Mode). TCA8418 может использоваться для чтения уровня GPI от одиночных кнопок, или может быть сконфигурирована в режиме сканирования матрицы кнопок. В режиме сканирования существует 2 режима работы - Idle Key Scan Mode и Active Key Scan Mode.

Idle Key Scan Mode. Как только TCA8418 была сконфигурирована на матрицу кнопок, она входит в режим ожидания (idle mode) когда не была нажата ни одна из кнопок. Все столбцы, сконфигурированпые как часть матрицы клавиатуры, переводятся как выходы в уровень лог. 0, и все строки, сконфигурированные как часть той же матрицы, настраиваются как входы, с разешенными внутренними pullup-резисторами. Во время idle mode внутренний генератор выключается, так что потребляемая мощность от источника питания становится очень малой. В этом состоянии клавиатура ожидает нажатие на кнопку в матрице.

Active Key Scan Mode. Когда контроллер TCA8418 находится в режиме idle key scan, он ожидает нажатия на кнопку. Как только кнопка в матрице была нажата, низкий уровень на входе строки (ROW), соответсвующем кнопке, разбудит внутренний генератор, и TCA8418 перейдет в active key scan mode. В этот момент TCA8418 начнет выполнять алгоритм сканирования клавиатуры, чтобы определить какая кнопка нажата, и этот же генератор используется для алгоритма подавлеия дребезга контактов (debouncing). Когда все кнопки отпущены, TCA8418 возвратится в idle key scan mode.

[Программирование]

TCA8418 снабжен стандартным интерфейсом I2C, и работает как подчиненное (slave) устройство под управлением главного устройства шины I2C (микроконтроллер хоста, устройство master I2C). Через I2C контроллер TCA8418 конфигурируется, и может быть прочитано его состояние. Каждое slave-устройство на шине I2C имеет свой определенный адрес, чтобы можно было обращаться к каждому из устройств на шине I2C по отдельности (к одной шине I2C может быть подключено несколько slave-устройств).

Физически интерфейс I2C состоит из 2 сигналов - последовательные такты (SCL) и последовательные данные (SDA). Оба этих сигнала должны быть подтянуты к уровню питания VCC через pull-up резисторы. Номинал этих резисторов определяется паразитной емкостью сигналов I2C и скоростью обмена по шине (для дополнительной информации по вычислению номиналов резисторов подтяжки см. даташит SLVA689 [2]). Передача данных может быть инициирована только когда шина находится в состоянии ожидания (idle). Состояние idle шины определено как одновременное нахождение уровней SDA и SCL в лог. 1, когда они установились в лог. 1 после сигнала STOP.

Для доступа устройства master к устройству slave выполняется следующая общая процедура.

1. Если master должен послать данные к slave:

– Master генерирует сигнал START и обращается к определенному slave передачей уникального адреса.
– Master передает данные для устройству slave, которое подтверждает каждый байт сигналом ACK.
– Master завершает передачу генерацией сигнала STOP.

2. Если master должен получить (прочитать) данные из slave:

– Master генерирует сигнал START и обращается к определенному slave передачей уникального адреса.
– Master посылает номер запрашиваемого регистра slave, который должен быть прочитан.
– Master принимает данные от slave, подтверждает каждый байт сигналом ACK.
– Master завершает передачу генерацией сигналов NACK и STOP.

TCA8418 Definition Start and Stop Conditions fig21

Рис. 21. Определение для сигналов START и STOP.

Транзакции шины. Данные должны бтыь переданы в slave-устройства и приняты от них путем записи или чтения их соответствующих регистров.

Регистры можно рассматривать как ячейки памяти slave, в которых содержится информация - либо конфигурация, либо какая-то информация, которая нужна устройству master. Устройство master должен записать информацию в эти регистры, чтобы инструктировать slave-устройство на выполнение определенной задачи.

Хотя наличие регистров - обычное дело для slave-устройств I2C, следует отметить, что не все slave-устройства I2C снабжены регистрами. Некоторое очень простые, и представляют только 1 регистр, который может быть записан напрямую отправкой данных после отправки slave-адреса I2C, в этом случае специальная адресация целевого регистра не нужна. Примером такого однорегистрового устройства может служить 8-битный мультиплексор, управляемый командами I2C, или электронный потенциометр.

TCA8418 Bit Transfer fig22

Рис. 22. Транзакция на шине I2C (передача потока бит).

Операция записи. Для записи по шине I2C, устройство master отправит сигнал START далее slave-адрес вместе с последним его битом, установленным в 0 (так называемый R/W бит, его 0 обозначает начало операции записи). После этого slave посылает в ответ бит подтверждения ACK, и master затем отправит адрес нужного регистра, куда он хочет записать данные. Устройство slave снова выдаст в ответ бит ACK, давая понять устройству master, что оно готово к приему записываемых данных. После этого master начнет передачу данных регистра для slave, пока не отправит все необходимые данные (которые иногда могут быть только одним байтом). После этого master завершит передачу генерацией сигнала STOP.

На рис. 23 и 24 показан пример записи одного байта в регистр.

TCA8418 Write to Register fig23

Рис. 23. Запись в регистр.

TCA8418 Write to Configuration Register fig24

Рис. 24. Запись в регистр конфигурации (01h).

Операция чтения. Чтение организовано похоже на запись, но здесь необходимы дополнительные шаги. Чтобы прочитать из slave, устройство master сначала должно указать для slave, какой регистр должен быть прочитан. Это осуществляется предварительной операцией записи адреса нужного регистра (отправка slave-адреса с битом R/W = 0, затем отправка адреса читаемого регистра). После того, как slave подтвердит ACK адрес регистра, устройство master снова пошлет сигнал START (так называемый сигнал REPEATED START), затем slave-адрес, но здесь бит R/W = 1 (обозначает операцию чтения). Устройство slave подтвердит сигналом ACK запрос на чтение, master освободит сигнал SDA и будет генерировать такты SCL, по которым устройство slave будет последовательно передавать данные запрошенного регистра. Во время этой части транзакции устройства меняются местами - master становится приемником и подтверждает кадр данных сигналом ACK, а slave становится передатчиком данных, и будет передавать данные по тактам SCL до тех пор, пока master не остановит передачу сигналами NACK и STOP.

Рис. 25 показывает пример чтения одного байта из регистра slave-устройства.

TCA8418 Read from Register fig25

Рис. 25. Чтение регистра.

Микросхема контроллера TCA8418 отвечает на slave-адрес 0x34 (0110100), как показано в таблице 8.

Таблица 8. Адрес устройства TCA8418.

Байт Бит
7 (MSB)      6           5           4           3           2           1      0 (LSB)
Slave-адрес I2C 0 1 1 0 1 0 0 R/W

Как уже упоминалось, последний бит slave-адреса определяет операцию (чтение или запись). Лог. 1 выбирает чтение (Read), лог. 0 запись (так называемый R/W бит).

[Карта регистров]

Control Register и Command Byte. За успешным подтверждением байта адреса master посылает байт команды (Command Byte), который сохраняется в регистре управления (Control Register) микросхемы TCA8418. Command Byte показывает, какой регистр будет обновлен информацией. Все регистры могут быть записаны и прочитаны устройством master (обычно это микроконтроллер).

Таблица 9 показывает все регистры и их краткое описание. Значение по умолчанию у всех регистров равно 0.

Таблица 9. Описание регистров TCA8418.

Адр. Имя регистра Описание 7 6 5 4 3 2 1 0
0x00 Зарезервировано                  
0x01 CFG Регистр конфигурации (разрешает вывод прерываний для микроконтроллера хоста) AI GPI_E_CGF OVR_FLOW_M INT_CFG OVR_FLOW_IEN K_LCK_IEN GPI_IEN KE_IEN
0x02 INT_STAT Регистр состояния прерываний N/A
0
N/A
0
N/A
0
CAD_INT OVR_FLOW_INT K_LCK_INT GPI_INT K_ INT
0x03 KEY_LCK_EC Регистр блокировки клавиатуры и счетчика событий N/A
0
K_LCK_EN LCK2 LCK1 KLEC3 KLEC2 KLEC1 KLEC0
0x04 KEY_EVENT_A Регистр A событий клавиатуры KEA7
0
KEA6
0
KEA5
0
KEA4
0
KEA3
0
KEA2
0
KEA1
0
KEA0
0
0x05 KEY_EVENT_B Регистр B событий клавиатуры KEB7
0
KEB6
0
KEB5
0
KEB4
0
KEB3
0
KEB2
0
KEB1
0
KEB0
0
0x06 KEY_EVENT_C Регистр C событий клавиатуры KEC7
0
KEC6
0
KEC5
0
KEC4
0
KEC3
0
KEC2
0
KEC1
0
KEC0
0
0x07 KEY_EVENT_D Регистр D событий клавиатуры KED7
0
KED6
0
KED5
0
KED4
0
KED3
0
KED2
0
KED1
0
KED0
0
0x08 KEY_EVENT_E Регистр E событий клавиатуры KEE7
0
KEE6
0
KEE5
0
KEE4
0
KEE3
0
KEE2
0
KEE1
0
KEE0
0
0x09 KEY_EVENT_F Регистр F событий клавиатуры KEF7
0
KEF6
0
KEF5
0
KEF4
0
KEF3
0
KEF2
0
KEF1
0
KEF0
0
0x0A KEY_EVENT_G Регистр G событий клавиатуры KEG7
0
KEG6
0
KEG5
0
KEG4
0
KEG3
0
KEG2
0
KEG1
0
KEG0
0
0x0B KEY_EVENT_H Регистр H событий клавиатуры KEH7
0
KEH6
0
KEH5
0
KEH4
0
KEH3
0
KEH2
0
KEH1
0
KEH0
0
0x0C KEY_EVENT_I Регистр I событий клавиатуры KEI7
0
KEI6
0
KEI5
0
KEI4
0
KEI3
0
KEI2
0
KEI1
0
KEI0
0
0x0D KEY_EVENT_J Регистр J событий клавиатуры KEJ7
0
KEJ6
0
KEJ5
0
KEJ4
0
KEJ3
0
KEJ2
0
KEJ1
0
KEJ0
0
0x0E KP_LCK_TIMER Таймер отслеживания таймаута он нажатия первой кнопки разблокировки до нажатия второй кнопки разблокировки KL7 KL6 KL5 KL4 KL3 KL2 KL1 KL0
0x0F UNLOCK1 Кнопка разблокировки 1 UK1_7 UK1_6 UK1_5 UK1_4 UK1_3 UK1_2 UK1_1 UK1_0
0x10 UNLOCK2 Кнопка разблокировки 2 UK2_7 UK2_6 UK2_5 UK2_4 UK2_3 UK2_2 UK2_1 UK2_0
0x11 GPIO_INT_STAT1 Состояние прерываний GPIO R7IS
0
R6IS
0
R5IS
0
R4IS
0
R3IS
0
R2IS
0
R1IS
0
R0IS
0
0x12 GPIO_INT_STAT2 C7IS
0
C6IS
0
C5IS
0
C4IS
0
C3IS
0
C2IS
0
C1IS
0
C0IS
0
0x13 GPIO_INT_STAT3 N/A
0
N/A
0
N/A
0
N/A
0
N/A
0
N/A
0
C9IS
0
C8IS
0
0x14 GPIO_DAT_STAT1 Состояние данных GPIO (для очистки надо прочитать дважды) R7DS
0
R6DS
0
R5DS
0
R4DS
0
R3DS
0
R2DS
0
R1DS
0
R0DS
0
0x15 GPIO_DAT_STAT2 C7DS
0
C6DS
0
C5DS
0
C4DS
0
C3DS
0
C2DS
0
C1DS
0
C0DS
0
0x16 GPIO_DAT_STAT3 N/A
0
N/A
0
N/A
0
N/A
0
N/A
0
N/A
0
C9DS
0
C8DS
0
0x17 GPIO_DAT_OUT1 Выходные данные GPIO R7DO
0
R6DO
0
R5DO
0
R4DO
0
R3DO
0
R2DO
0
R1DO
0
R0DO
0
0x18 GPIO_DAT_OUT2 C7DO
0
C6DO
0
C5DO
0
C4DO
0
C3DO
0
C2DO
0
C1DO
0
C0DO
0
0x19 GPIO_DAT_OUT3 N/A
0
N/A
0
N/A
0
N/A
0
N/A
0
N/A
0
C9DO
0
C8DO
0
0x1A GPIO_INT_EN1 Разрешение прерываний GPIO R7IE
0
R6IE
0
R5IE
0
R4IE
0
R3IE
0
R2IE
0
R1IE
0
R0IE
0
0x1B GPIO_INT_EN2 C7IE
0
C6IE
0
C5IE
0
C4IE
0
C3IE
0
C2IE
0
C1IE
0
C0IE
0
0x1C GPIO_INT_EN3 N/A
0
N/A
0
N/A
0
N/A
0
N/A
0
N/A
0
C9IE
0
C8IE
0
0x1D KP_GPIO1 Выбор keypad или GPIO.
0: GPIO
1: матрица клавиатуры
ROW7
0
ROW6
0
ROW5
0
ROW4
0
ROW3
0
ROW2
0
ROW1
0
ROW0
0
0x1E KP_GPIO2 COL7
0
COL6
0
COL5
0
COL4
0
COL3
0
COL2
0
COL1
0
COL0
0
0x1F KP_GPIO3 N/A
0
N/A
0
N/A
0
N/A
0
N/A
0
N/A
0
COL9
0
COL8
0
0x20 GPI_EM1 GPI event mode 1  ROW7
0
ROW6
0
ROW5
0
ROW4
0
ROW3
0
ROW2
0
ROW1
0
ROW0
0
0x21 GPI_EM2 GPI event mode 2 COL7
0
COL6
0
COL5
0
COL4
0
COL3
0
COL2
0
COL1
0
COL0
0
0x22 GPI_EM3 GPI event mode 3 N/A
0
N/A
0
N/A
0
N/A
0
N/A
0
N/A
0
COL9
0
COL8
0
0x23 GPIO_DIR1 Направление GPIO.
0: вход
1: выход
R7DD
0
R6DD
0
R5DD
0
R4DD
0
R3DD
0
R2DD
0
R1DD
0
R0DD
0
0x24 GPIO_DIR2 C7DD
0
C6DD
0
C5DD
0
C4DD
0
C3DD
0
C2DD
0
C1DD
0
C0DD
0
0x25 GPIO_DIR3 N/A
0
N/A
0
N/A
0
N/A
0
N/A
0
N/A
0
C9DD
0
C8DD
0
0x26 GPIO_INT_LVL1 Событие по перепаду/уровню GPIO.
0: спад, лог. 0
1: фронт, лог. 1
R7IL
0
R6IL
0
R5IL
0
R4IL
0
R3IL
0
R2IL
0
R1IL
0
R0IL
0
0x27 GPIO_INT_LVL2 C7IL
0
C6IL
0
C5IL
0
C4IL
0
C3IL
0
C2IL
0
C1IL
0
C0IL
0
0x28 GPIO_INT_LVL3 N/A
0
N/A
0
N/A
0
N/A
0
N/A
0
N/A
0
C9IL
0
C8IL
0
0x29 DEBOUNCE_DIS1 Запрет подавления дребезга.
0: подавление дребезга разрешено
1: подавление дребезга запрещено
R7DD
0
R6DD
0
R5DD
0
R4DD
0
R3DD
0
R2DD
0
R1DD
0
R0DD
0
0x2A DEBOUNCE_DIS2 C7DD
0
C6DD
0
C5DD
0
C4DD
0
C3DD
0
C2DD
0
C1DD
0
C0DD
0
0x2B DEBOUNCE_DIS3 N/A
0
N/A
0
N/A
0
N/A
0
N/A
0
N/A
0
C9DD
0
C8DD
0
0x2C GPIO_PULL1 Запрет верхних подтягивающих резисторов GPIO.
0: GPIO pull-up разрешен
1: GPIO pull-up запрещен
R7PD
0
R6PD
0
R5PD
0
R4PD
0
R3PD
0
R2PD
0
R1PD
0
R0PD
0
0x2D GPIO_PULL2 C7PD
0
C6PD
0
C5PD
0
C4PD
0
C3PD
0
C2PD
0
C1PD
0
C0PD
0
0x2E GPIO_PULL3 N/A
0
N/A
0
N/A
0
N/A
0
N/A
0
N/A
0
C9PD
0
C8PD
0
0x2F Зарезервировано                  

Бит         7                  6               5                 4                3                2                   1                 0        
Имя AI GPI_E_CFG OVR_FLOW_M INT_CFG OVR_FLOW_IEN K_LCK_IEN GPI_IEN KE_IEN

AI (бит 7): разрешает автоинкремент адреса для операций чтения и записи. 0 автоинкремент запрещен, 1 разрешен.

Бит 7 (AI) в этом регистре используется для определения режима программирования. Если он равен 0, то все записываемые байты данных будут записаны в тот регистр, который определил байт команды. Если он равен 1, то значение байта команды автоматически инкрементируется с каждым записанным байтом, и следующий байт данных будет записан в соответствующий регистр. Регистры будут записаны в последовательности, показанной в таблице 9. Как только был записан последний регистр GPIO_PULL3 (0x2E), байт команды снова станет равным 0. Регистры 0 и 2F зарезервированы, и байт команды, который соответствует этим регистрам, не подтверждается контроллером TCA8418.

GPI_E_CFG (бит 6): конфигурация режима событий GPI. 0 события GPI отслеживаются, когда клавиатура заблокирована, 1 не отслеживаются.

OVR_FLOW_M (бит 5): Overflow mode. 0 задает, что данные нажатий/отпусканий при переполнении FIFO будут теряться. 1 задает, что при переполнении данные FIFO будут смещаться: старые самые данные будут удалены, а новые добавлены.

INT_CFG (бит 4): конфигурация прерывания. 0 прерывание хоста остается выставленным (ножка ~INT в состоянии лог. 0), если хост пытается очистить прерывание, когда все еще ожидают обработки нажатия кнопок, отпускания кнопок или прерывания GPI. 1 прерывание хоста снимается через 50 мкс, и переустановится с ожидающими прерываниями.

OVR_FLOW_IEN (бит 3): разрешение прерывания при переполнении FIFO. 0 запрещено, сигнал ~INT не будет выставлен, если произошло прерывание FIFO. 1 разрешено, ~INT активируется при переполнении FIFO.

K_LCK_IEN (бит 2): Keypad lock interrupt enable. 0 запрещено, ~INT не активируется после корректной последовательности нажатий разблокировки. 1 разрешено, ~INT активируется после корректной последовательности нажатий разблокировки.

Keypad lock interrupt enable определяет, будет ли активна ножка прерываний, когда установлен бит прерывания блокировки клавитатуры (бит key lock interrupt, см. описание Interrupt Status Register).

GPI_IEN (бит 1): разрешение прерывания GPI для хоста. 0 запрещено, ~INT не активируется при изменении уровня GPI. 1 разрешено, ~INT активируется при изменении уровня GPI.

KE_IEN (бит 0): разрешение прерывания от событий кнопок для хоста. 0 запрещено, ~INT не активируется при событии кнопки (нажатие или отпускание). 1 разрешено, ~INT активируется при событии кнопки.

Регистр INT_STAT используется для проверки, какое именно прерывание вызвало активацию ножки ~INT. Если соответствующий биты разрешения прерывания установлены в Configuration Register, то значение 1 в соответствующем бите регистра INT_STAT приведет к переводу сигнала ~INT в лог. 0. Исключение из этого составляет бит CAD_INT, который выставит активный уровень лог. 0 на выводе CAD_INT для корпусов YFP.

Чтение этого регистра возвратит типы произошедших прерываний. Запись 1 в бит регистра INT_STAT очистит его, но бит не очистится, если в FIFO все еще находятся не прочитанные данные (например, не прочитанные события кнопок).

Бит         7                 6                 5                  4             3             2                  1                  0        
Имя N/A N/A N/A CAD_INT OVR_FLOW_INT K_LCK_INT GPI_INT K_INT

Все перечисленные ниже флаги прерывания установятся автоматически при возникновении соответствующего события. Для очистки флага нужно в него записать 1, запись 0 не оказывает никакого действия.

N/A не используемые биты, они всегда равны 0.

CAD_INT (бит 4): CTRL-ALT-DEL key sequence status, статус последовательности клавиш CTRL-ALT-DEL. Лог. 1 означает, что было обнаружено нажатие этих клавиш.

OVR_FLOW_INT (бит 3): Overflow interrupt status. Установится, если было обнаружено переполнение FIFO.

K_LCK_INT (бит 2): Keypad lock interrupt status. Прерывание для хоста - установится, когда началась последовательность keypad lock.

GPI_INT (бит 1): GPI interrupt status. Установится, когда была обнаружена активность на входах GPI.

K_INT (бит 0): Key events interrupt status. Установится, если было обнаружено событие клавиатуры.

Бит         7                 6                  5                  4                   3                  2                  1                  0        
Имя N/A K_LCK_EN LCK2 LCK1 KEC3 KEC2 KEC1 KEC0

N/A не используемый бит, он всегда равен 0.

K_LCK_EN (бит 6): Key lock enable, разрешение блокировки клавиатуры. 0 блокировка запрещена, запись в этот бит 0 программно разблокирует клавиатуру. 1 блокировка разрешена, запись 1 в этот бит блокирует клавиатуру.

LCK2 (бит 5): Keypad lock status, состояние блокировки клавиатуры. 0 разблокировано (если LCK1 также 0). 1 заблокировано (если LCK1 также 1).

LCK1 (бит 4): Keypad lock status, состояние блокировки клавиатуры. 0 разблокировано (если LCK2 также 0). 1 заблокировано (если LCK2 также 1).

KEC3 .. KEC0 (биты 3 .. 0): Key event count, счетчик событий клавиатуры. KEC[3:0] показывает, сколько событий клавиатуры находится в FIFO. Например, KEC[3:0] = 0b0000 = 0 событий, KEC[3:0] = 0b0001 = 1 событие, и KEC[3:0] = 0b1010 = 10 событий. При возникновении событий (нажатие или отпускание кнопки) счетчик увеличивает свое значение.

Бит         7                 6                  5                  4                   3                  2                  1                  0        
Имя KEA7 KEA6 KEA5 KEA4 KEA3 KEA2 KEA1 KEA0

Примечание: показан только регистр KEY_EVENT_A.

Регистры KEY_EVENT_A - KEY_EVENT_J работают как стек FIFO, который может хранить в себе до 10 событий клавиш - нажатий и отпусканий. Пользователь предварительно проверяет регистр INT_STAT, чтобы узнать, были ли какие-либо прерывания. Если были, то считывается регистр блокировки и счетчика событий (KEY_LCK_EC, адрес 0x03), чтобы увидеть, сколько прерываний было сохранено. Затем INT_STAT снова прочитывается, чтобы убедиться, что больше новых прерываний не было. Регистр KEY_EVENT_A затем считывается столько раз, сколько было прерываний (количество прерываний было считано из счетчика событий). При каждом чтении регистра KEY_EVENT_A счетчик в регистре KEY_LCK_EC уменьшается на 1. Данные в стеке FIFO также смещаются в сторону регистра KEY_EVENT_A на одну позицию (в направлении от KEY_EVENT_J к KEY_EVENT_A). Как только все события были прочитаны, счетчик событий становится нулем, и бит KE_INT может быть очищен записью в него лог. 1.

В регистре KEY_EVENT_A биты KEA[6:0] показывают номер клавиши, которая была нажата или отпущена. Значение от 0 до 80 показывают, какая клавиша в матрице была нажата или отпущена. Значения от 97 до 114 соответствуют событиям GPI.

Старший бит KEA[7] показывает, какое именно событие клавиши (с кодом KEA[6:0]) произошло - отпускание или нажатие. 0 означает отпускание клавиши, 1 нажатие (чтобы получить код нажатой клавиши, старший бит при чтении может быть очищен).

Например, были нажаты 3 клавиши, и тогда в FIFO будет записано 6 байт, 3 нажатия и 3 отпускания. При чтении каждого слова будет понятно, что оно означает - нажатие или отпускание, и какая это была клавиша. Нажатия наподобие CTRL+ALT+DEL сохраняются как 3 одновременных нажатия. Нажатия и отпускания клавиш генерируют события клавиатуры (key event interrupts). Бит KE_INT не очистится и ножка ~INT не будет деактивирована до тех пор, пока FIFO не будет очищен от всех событий.

Можно прочитать все регистры от KEY_EVENT_A до KEY_EVENT_J, однако для правильной работы по принципу FIFO (First Input First Output, первым вошел - первым вышел) пользователю нужно считывать только регистр KEY_EVENT_A. Как только все события в FIFO были прочитаны, регистр KEY_EVENT_A будет считываться как 0.

Бит         7                 6                  5                  4                   3                  2                  1                  0        
Имя KL7 KL6 KL5 KL4 KL3 KL2 KL1 KL0

KL[2:0]: эти биты предназначены для таймера отсчета времени от Lock1 до Lock2.

KL[7:3]: эти биты для таймера маски прерывания (interrupt mask timer).

Значение таймера KL[2:0] должно быть не нулевым для разрешения блокировки клавиатуры. Значение KL[2:0] определяет количество секунд, прошедшее между нажатием клавиш разблокировки 2 и 1 (unlock key 2 нажимается после unlock key 1), это нужно для отслеживания таймаута последовательности разблокировки клавиатуры. Более подробно про блокировку и разблокировку клавиатуры см. выше секцию "Keypad Lock/Unlock".

Если таймер маскирования прерывания блокировки клавиатуры (keypad lock interrupt mask timer) не равен 0, будет сгенерировано событие кнопки (key event interrupt, K_INT) только на первом нажатии на любую кнопку. Второе прерывание (K_LCK_IN) будет сгенерировано только когда была выполнена корректная последовательность разблокировки клавиатуры (unlock sequence). Если таймаут любого из таймеров KL[2:0] или KL[7:3] истек, то машина состояния блокировки сбрасывается в исходное положение.

Когда таймер маски прерывания запрещен (0), прерывание блокировки кнопок будет генерироваться только когда была выполнена корректная последовательность разблокировки.

Таймер маски прерывания должен быть установлен на время, которое отводится на интервал включенного состояния экрана LCD. Для дополнительной информации см. выше секцию "Keypad Lock Interrupt Mask Timer".

Адрес Имя регистра 7 6 5 4 3 2 1 0
0x0F Unlock1 UK1_7 UK2_6 UK2_5 UK2_4 UK2_3 UK2_2 UK2_1 UK2_0
0x10 Unlock2 UK2_7 UK2_6 UK2_5 UK2_4 UK2_3 UK2_2 UK2_1 UK2_0

UK1[6:0] содержит номер кнопки, используемой для клавиши разблокировки 1.

UK2[6:0] содержит номер кнопки, используемой для клавиши разблокировки 2.

0 в любом из этих регистров запретит работу функции разблокировки.

Регистры GPIO_INT_STAT1, GPIO_INT_STAT2, GPIO_INT_STAT3 используются для проверки статуса прерывания ножек GPIO. Если установлен бит GPI_INT в регистре INT_STAT, то ножка GPI, которая установила это прерывание, будет помечена 1 в соответствующей таблице. Чтобы очистить бит GPI_INT, значение всех этих регистров должно быть равно 0x00. Чтение регистра GPIO_INT_STAT1 - GPIO_INT_STAT3 автоматически очистит его.

Адрес Имя регистра 7 6 5 4 3 2 1 0
0x11 GPIO_INT_STAT1 R7IS R6IS R5IS R4IS R3IS R2IS R1IS R0IS
0x12 GPIO_INT_STAT2 C7IS C6IS C5IS C4IS C3IS C2IS C1IS C0IS
0x13 GPIO_INT_STAT3 N/A N/A N/A N/A N/A N/A C9IS C8IS

Эти регистры показывают состояние GPIO, когда они считываются в режиме входов и выходов. Для очистки их нужно прочитать дважды.

Адрес Имя регистра 7 6 5 4 3 2 1 0
0x14 GPIO_DAT_STAT1 R7DS R6DS R5DS R4DS R3DS R2DS R1DS R0DS
0x15 GPIO_DAT_STAT2 C7DS C6DS C5DS C4DS C3DS C2DS C1DS C0DS
0x16 GPIO_DAT_STAT3 N/A N/A N/A N/A N/A N/A C9DS C8DS

Эти регистры содержат данные GPIO для записи в выходной драйвер. На входы эти данные не влияют. Данные установят лог. уровень для соответствующей ножки выхода GPIO.

Адрес Имя регистра 7 6 5 4 3 2 1 0
0x17 GPIO_DAT_OUT1 R7DO R6DO R5DO R4DO R3DO R2DO R1DO R0DO
0x18 GPIO_DAT_OUT2 C7DO C6DO C5DO C4DO C3DO C2DO C1DO C0DO
0x19 GPIO_DAT_OUT3 N/A N/A N/A N/A N/A N/A C9DO C8DO

Эти регистры разрешают прерывания (значением 1 бита) или запрещают их (значением 0 бита) только для входов (GPI). Если вход, настроенный как GPI, поменяет свой уровень, то установится бит GPI_INT в регистре INT_STAT.

Значение 0 в любом из используемых бит запретит для соответствующей ножки возможность генерации прерывания, когда состояние её входа поменялось. Это значение по умолчанию.

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

Адрес Имя регистра 7 6 5 4 3 2 1 0
0x1A GPIO_INT_EN1 R7IE R6IE R5IE R4IE R3IE R2IE R1IE R0IE
0x1B GPIO_INT_EN2 C7IE C6IE C5IE C4IE C3IE C2IE C1IE C0IE
0x1C GPIO_INT_EN3 N/A N/A N/A N/A N/A N/A C9IE C8IE

Значение 0 в любом из используемых бит переведет соответствующую ножку в режим GPIO, это состояние по умолчанию. Ножка в режиме GPIO может быть сконфигурирована либо как вход, либо как выход, путем программирования регистров GPIO_DIR1-3.

Значение 1 в любом из используемых бит переведет соответствующую ножку в режим сканирования, и она будет работать в составе клавиатурной матрицы. В результате ножка будет работать как разряд строки или столбца (это уже не настраивается).

Адрес Имя регистра 7 6 5 4 3 2 1 0
0x1D KP_GPIO1 ROW7 ROW6 ROW5 ROW4 ROW3 ROW2 ROW1 ROW0
0x1E KP_GPIO2 COL7 COL6 COL5 COL4 COL3 COL2 COL1 COL0
0x1F KP_GPIO3 N/A N/A N/A N/A N/A N/A COL9 COL8

Значение 0 в любом из используемых бит показывает, что ножка не принимает участие в регистрации событий FIFO. Это значение по умолчанию.

Значение 1 в любом из используемых бит означает, что соответствующая ножка, настроенная на вход (GPI), будет регистрировать события для FIFO. Тогда эта ножка может использоваться для прямого подключения кнопки и записи в FIFO событий нажатия и отпускания. Для дополнительной информации см. выше секцию "Key Event Table".

Адрес Имя регистра 7 6 5 4 3 2 1 0
0x20 GPI_EM1 ROW7 ROW6 ROW5 ROW4 ROW3 ROW2 ROW1 ROW0
0x21 GPI_EM2 COL7 COL6 COL5 COL4 COL3 COL2 COL1 COL0
0x22 GPI_EM3 N/A N/A N/A N/A N/A N/A COL9 COL8

Значение 0 в любом из используемых бит установит соответствующую ножку как вход. Это значение по умолчанию.

Значение 1 в любом из используемых бит установит соответствующую ножку как выход.

Адрес Имя регистра 7 6 5 4 3 2 1 0
0x23 GPIO_DIR1 R7DD R6DD R5DD R4DD R3DD R2DD R1DD R0DD
0x24 GPIO_DIR2 C7DD C6DD C6DD C4DD C3DD C2DD C1DD C0DD
0x25 GPIO_DIR3 N/A N/A N/A N/A N/A N/A C9DD C8DD

Значение 0 в любом из используемых бит показывает, что прерывание будет генерироваться переходах от 1 к 0 и от 0 к 1 на входах, когда соответствующая ножка находится в режиме GPIO. Это значение по умолчанию.

Значение 0 в любом из используемых бит показывает, что прерывание будет генерироваться при переходе от 0 к 1 и при уровне 1 на входах, когда соответствующая ножка находится в режиме GPIO.

Адрес Имя регистра 7 6 5 4 3 2 1 0
0x26 GPIO_INT_LVL1 R7IL R6IL R5IL R4IL R3IL R2IL R1IL R0IL
0x27 GPIO_INT_LVL2 C7IL C6IL C5IL C6IL C3IL C2IL C1IL C0IL
0x28 GPIO_INT_LVL3 N/A N/A N/A N/A N/A N/A C9IL C8IL

Это регистры для запрета подавления дребезга, их значения применимы только для тех ножек, которые сконфигурированы как входы. Значение 0 в любом из используемых бит разрешает подавление дребезга, это значение по умолчанию. Значение 1 для бита запрещает подавление дребезга.

Адрес Имя регистра 7 6 5 4 3 2 1 0
0x29 DEBOUNCE_DIS1 R7DD R6DD R5DD R4DD R3DD R2DD R1DD R0DD
0x2A DEBOUNCE_DIS2 C7DD C6DD C5DD C4DD C3DD C2DD C1DD C0DD
0x2B DEBOUNCE_DIS3 N/A N/A N/A N/A N/A N/A C9DD C8DD

Запрет подавления дребезга дает одинаковый эффект и для режима GPI входов, и для строк, когда они работают в составе сканируемой матрицы клавиатуры. У входа ~RESET всегда присутствует время подавления дребезга 50 мкс.

Интервал подавления дребезга контактов (который составляет 50 мкс) необходим для того, чтобы лог. уровень на входе стал стабильным.

TCA8418 Debounce Disable waveforms

Время подавления дребезга для клавиатуры применимо только для столбцов. Минимальное время составляет 25 мс. Все столбцы сканируются один раз каждые 25 мс, чтобы определить нажатия кнопок. Требуется 2 полных сканирования, чтобы определить, была ли нажата любая кнопка. Если первое сканирование было выполнено сразу после нажатия, то для определение этого нажатия займет по времени 25 мс. Если первое сканирование произошло намного позже нажатия клавиши, то определение этого нажатия займет по времени 40 мс.

Эти регистры разрешают или запрещают внутренние верхние подтягивающие резисторы (pull-up) для входов. Значение 0 бита разрешает pullup-резистор, это значение по умолчанию. Значение бита 1 запрещает pullup-резистор.

Адрес Имя регистра 7 6 5 4 3 2 1 0
0x2C GPIO_PULL1 R7PD R6PD R5PD R4PD R3PD R2PD R1PD R0PD
0x2D GPIO_PULL2 C7PD C6PD C5PD C4PD C3PD C2PD C1PD C0PD
0x2E GPIO_PULL3 N/A N/A N/A N/A N/A N/A C9PD C8PD

[CAD Interrupt Errata]

В регистре состояния прерываний, (Interrupt Status Register, INT_STAT с адресом 0x02, см. выше соответствующую врезку), бит 4 CAD_INT используется для детектирования последовательности нажатия клавиш CTRL-ALT-DEL. Некоторые последовательности нажатий клавиш установят бит CAD_INT ошибочно.

Следующие комбинации нажатий клавиш приведут к неправильной установке CAD_INT:

1 + 11
1 + 21
21 + 1 + 11

Для этой проблемы не существует способа избежать ошибочного детектирования прерывания CAD_INT.

[Overflow Errata]

TCA8418 позволяет обнаружить переполнение 10-байтного FIFO для событий нажатия и отпускания клавиш. Чтобы разрешить обнаружение переполнения, оба бита - бит 3 (OVR_FLOW_IEN) и бит 5 (OVR_FLOW_M) в регистре конфигурации (см. выше врезку "Configuration Register (0x01)") должны быть установлены в лог. 1. Если установлен только бит 3 (OVR_FLOW_IEN), то прерывание переполнения генерироваться не будет.

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

[Рекомендации по применению]

Ghosting (двоение). Этим термином называют нежелательное обнаружение дополнительных клавиш в случае некоторых одновременных нажатий (обнаружение дополнительного, не существующего нажатия), связанное с расположением клавиш в матрице. Несмотря на то, что TCA8418 поддерживает обнаружение нескольких одновременных нажатий кнопок в матрице, для приложений, требующих определения заданных одновременных комбинаций нажатий (наподобие Ctrl-Alt-Del) требуется уделить особое внимание. Необходимо гарантировать, чтобы эти кнопки в матрице занимали особое положение.

Для примера рассмотрим матрицу 3x4 (3 столбца C0-C2 и 4 строки R0-R3), см. рис. 26. Чтобы избежать ситуации ghosting для ожидаемого одновременного нажатия трех кнопок, необходимо эти три кнопки разместить на разных строках и столбцах.

TCA8418 Example Keypad fig26

Рис. 26. Пример клавиатурной матрицы.

Для матрицы клавиатуры на рис. 26 используются выводы ROW0-ROW3 для строк и COL0-COL2 для столбцов. Все строки (ROWx) сконфигурированы как входы с pullup-резисторами. Столбцы (COLx) сконфигурированы как выходы, управляемые лог. 0. Когда происходит нажатие на кнопку, входы ROWx подтягиваются к лог. 0, информируя тем самым TCA8418, что была нажата кнопка, и тогда TCA8418 запускает алгоритм сканирования матрицы. При выполнении этого алгоритма TCA8418 будет сдвигать лог. 0 по столбцам, в любой момент времени выдавая лог. 0 только на 1 столбец. При подаче лог. 0 на каждый столбец TCA8418 считывает уровни на входах строк ROWx, чтобы определить, какая из кнопок в столбце была нажата.

На рис. 27 приведен пример ситуации ghosting, когда были нажаты только кнопки, закрашенные красным, но дополнительно обнаружилось, что якобы была нажата четвертая кнопка, которая закрашена желтым.

TCA8418 Incorrect 3Button Combination fig27

Рис. 27. Некорректно считываемая комбинация одновременного нажатия 3 клавиш.

Очевидно, что одновременное нажатие кнопок 1, 2 и 11 создает ghosting-проблему. Поскольку R1 оказывается подтянутым к GND кнопкой 1 (через кнопку 2, когда на C1 был выдан лог. 0), когда C1 переводится в 0, TCA8418 увидит лог. 0 на обоих строках R0 и R1. Это ошибочно приведет к обнаружению нажатия на кнопке 12 (она подкрашена желтым).

Причина ошибки в том, что клавиатурные матрицы замыкают друг на друга столбцы и строки. Когда C1 переведен в 0, этот 0 передается на R0 через кнопку 2. Нажатая кнопка 1 также замыкает C0 на GND. Нажатая кнопка 11 тогда замкнет R1 на C0. В результате этого процесса R1 замкнется на C1, и получается ghosting для кнопки 12.

Матрицы клавиатуры могут поддерживать корректное обнаружение одновременных нажатий, если был правильно произведен выбор положения этих одновременных нажатий в матрице. На рис. 28 мы видим ситуацию, когда обнаружение комбинации 3 одновременных нажатий срабатывает ожидаемо. Здесь нажаты кнопки 1, 11 и 21, и при этом ситуация ghosting не возникает. Комбинация кнопок 1, 11 и 21 также фиксировано задана для прерывания Ctrl-Alt-Del, для дополнительной информации см. выше секцию "Поддержка Control-Alt-Delete".

TCA8418 Correct 3Button Combination fig28

Рис. 28. Корректное распознавание комбинации нажатия 3 кнопок.

Рис. 29 показывает типичное приложение для TCA8418 - стандартная цифровая клавиатура из 12 кнопок (цифры от 0 до 9, кнопки * и #).

TCA8418 Typical Application fig29

Рис. 29. Пример реализации матрицы цифровой клавиатуры.

Разработчику следует учесть следующие моменты для своей системы на контроллере клавиатуры TCA8418.

• Необходимое количество клавиш.
• Должны ли клавиши быть мультиплексированы.
• Разводка мультиплексируемых клавиш.
• Не используемые клавиши подтягиваются к VCC через pullup-резистор (10 кОм).

Первые шаги в разработке массива клавиш - определение желаемой компоновки клавиатуры, отображение каждой кнопки на подходящее значение, которое будет записываться в FIFO. Для этого примера не предполагается, что будут использоваться другие выводы TCA8418, не входящие в матрицу.

Предполагается следующее желаемое поведение:

• В FIFO должны добавляться события нажатия и отпускания всех кнопок в матрице.
• Попытка очистить прерывание до того, как были правильно очищены соответствующие регистры, приведет к снятию сигнала ~INT на 50 мкс, и затем к повторной активации ~INT.
• Никакие дополнительные выводы не используются, кроме тех, что входят в матрицу клавиатуры.
• Используется функция блокировки клавиатуры (Keypad lock), которая требует для разблокировки комбинации нажатий # и 1, которые должны быть нажаты в пределах 2 секунд одно за другим.
• Задействован Keypad lock interrupt mask timer на 10 секунд, чтобы подсветка экрана выключилась через 10 секунд, и в течение этого времени, когда клавиатура заблокирована, прерывания от кнопок не генерировались.
• Разрешена аппаратная функция подавления дребезга контактов (hardware debouncing).

Поскольку TCA8418 сообщает о нажатиях клавиш в соответствии со значениями в своей внутренней таблица (key value table), важно заранее знать, каковы будут эти значения для каждой из кнопки в матрице.

В соответствии с Key Event Table нажатия клавиш назначаются, как показано в таблице 12.

Таблица 12. Коды, назначенные событиям клавиш в матрице.

Кнопка на клавиатуре 1 2 3 4 5 6 7 8 9 * 0 #
Значение из таблицы событий клавиатуры (десятичные) 1 2 3 11 12 13 21 22 23 31 32 33

Схема для этой клавиатуры показана на рис. 30 вместе со значениями кодов клавиш. Обратите внимание на отсутствие резисторов подтяжки, потому что используются внутренние резисторы подтяжки TCA8418.

TCA8418 Keypad Schematic fig30

Рис. 30. Схема матрицы клавиатуры.

Конфигурация регистров. Следующий шаг в разработке клавиатуры - конфигурирование соответствующих регистров TCA8418. Регистры должны быть модифицированы, как показано в следующей таблице.

Шаг Изменяемые регистры Записываемое значение Описание
Настройка матрицы клавиатуры KP_GPIO1 (0x1D) 0x0F Установка строк ROW0-ROW3 для матрицы клавиатуры.
KP_GPIO2 (0x1E) 0x07 Установка столбцов COL0-COL2 для матрицы клавиатуры.
KP_GPIO3 (0x1F) 0x00 Установка столбцов COL8-COL9 для матрицы клавиатуры.
Настройка генерации прерываний на ножке ~INT CFG (0x01) 0x95 Установка бит KE_IEN, K_LCK_IEN, INT_CFG и AI.
Настройка клавиш для разблокировки клавиатуры UNLOCK1 (0x0F) 0x21 Первая клавиша разблокировки с кодом 33 (== 0x21).
UNLOCK2 (0x10) 0x01 Вторая клавиша разблокировки с кодом 1 (== 0x01).
Настройка таймеров разблокировки клавиатуры KP_LCK_TIMER (0x0E) 0x52 Установка интервала 2 секунды от нажатия первой клавиши разблокировки до нажатия второй клавиши разблокировки. Таймер маски прерываний установлен на 10 секунд.

TCA8418 Initial Key Press to Interrupt Output fig31

Рис. 31. Сигнал прерывания ~INT при начальном нажатии на кнопку.

TCA8418 Zoom On Second Scan fig32

Рис. 32. Диаграммы сигналов второго сканирования.

[Рекомендации по источнику питания]

В случае сбоя или повреждения данных контроллер TCA8418 может быть сброшен в состояние по умолчанию с использованием функции сброса по питанию (power-on reset, POR). Power-on reset требует, чтобы устройство прошло весь цикл спада и нарастания уровня напряжения питания, чтобы произошел полный сброс. Этот сброс также произойдет, когда устройство только что получило питание при первом включении.

Два типа сброса power-on reset показаны на рис. 33 и 34.

TCA8418 VCC and POR fig33

Рис. 33. VCC понизилось до уровня ниже 0.2V или до 0V, и затем возросло до VCC.

TCA8418 VCC and POR fig34

Рис. 34. VCC понизилось до уровня ниже порога POR, и затем возросло обратно до VCC.

Таблица 13 показывает параметры power-on reset для обоих таких типов сброса.

Таблица 13. Рекомендуемые последовательности подачи питания(1).

Имя Параметр
min Typ MAX Ед.
VCC_GH Уровень, до которого VCC может падать, но не вызывать нарушения функционирования при VCCX_GW = 1 мкс. См. рис. 35     1.2 V
VCC_GW Длительность сбоя по питанию, который не приведет к нарушению функционирования при VCCX_GH = 0.5 x VCCx. См. рис. 35     10 мкс
VPORF Напряжение порога сброса POR при спаде VCC.   0.76   1.15 V
VPORR Напряжение порога сброса POR при нарастания VCC.   1.03   1.43

Примечание (1): значения показаны для температуре окружающей среды TA = –40°C .. 85°C (если не указано нечто иное).

Сбои в блоке питания также могут повлиять на работоспособность TCA8418 при формировании сброса по питанию. Ширина (VCC_GW) и высота (VCC_GH) импульса провала зависят друг от друга. Блокирующая емкость, импеданс источника и импеданс устройства являются факторами, влияющими на характеристики сброса по питанию. На рис. 35 и в таблице 13 представлена дополнительная информация по том, как измерять эти характеристики.

TCA8418 Glitch Width and Glitch Height fig35

Рис. 35. Ширина и высота провала по питанию.

VPOR критично для формирования сброса по питанию. Это уровень напряжения, при котором состояние сброса освобождается, и все регистры вместе с машиной состояния I2C/SMBus инициализируются в значения по умолчанию. Значение VPOR отличается в зависимости от того, понижается ли VCC, или же нарастает от 0V. Рис. 36 и таблица 13 более подробно описывают эти характеристики.

TCA8418 VPOR fig36

Рис. 36. VPOR.

Чтобы правильно работал сброс по питанию, соблюдайте вышеперечисленные рекомендации по параметрам, показанные на рисунках 33-36 и в таблице 13.

Рекомендации по разводке печатной платы, получение поддержки, информацию по закупке, размерам корпусов и посадочных мест TCA8418 см. в даташите [1].

[Пример работы с TCA8418]

Этот пример скетча основан на библиотеке [4].

#include < Wire.h>
#include < tca8418.h>
 
KEYS Keypad;
volatile bool KeyInt=false;
 
void KeyISR(void) {  // Обработчик прерывания клавиатурной матрицы
   KeyInt = true;
}
 
void setup() {
   Serial.begin(9600);
   Wire.begin();
 
   // Конфигурирование матрицы 4x4 на COL0-COL3, ROW0-ROW3,
   // и разрешение прерываний:
   Keypad.begin(ROW0|ROW1|ROW2|ROW3, COL0|COL1|COL2|COL3, 
                CFG_KE_IEN|CFG_OVR_FLOW_IEN|CFG_INT_CFG|CFG_OVR_FLOW_M);
   // Первый аргумент это номер порта Arduino для подключения
   // к сигналу ~INT от TCA8418, второй аргумент это адрес ISR:
   Keypad.enableInterrupt(2, KeyISR);
}
 
void loop() {
   // Проверка флага прерывания и его обработка
   if(KeyInt) {
      uint8_t key;
      // Получение первого кода кнопки из FIFO TCA8418:
      key=Keypad.readKeypad();
      // Печать HEX-кода кнопки ...
      Serial.print("Keyboard ISR...Key:");
      Serial.print((key&0x7F), HEX);
      // ... и события нажатия или отпускания (по биту 7):
      if(key & 0x80) {
         Serial.println(" key down");
      } else {
         Serial.println(" key up");
      } 
      KeyInt=false;  // Сброс нашего флага прерывания
      // Очистка флага прерывания в регистре статуса TCA8418:
      Keypad.clearInterruptStatus();
   }
   // Тут можно вставить другую обработку:
   ;
} 

[Как реализовать остлеживание автоповтора]

Ниже приведен код, где с контроллером TCA8418 реализован автоповтор кнопок при их удержании.

Заголовок TCA8418auto.h:

#pragma once
#include < stdbool.h>
#include < stdint.h>
#include "FreeRTOS.h"
#include "queue.h"
 
#define KEY_THREAD_SLEEP_MS      30
#define NO_KEY_PRESS_TIMEOUT_MS  15000
 
// Состояние регистра:
// I английские буквы, II русские, III цифры и символы
typedef enum
{
   KM1_low  = 0,     // I
   KM2_low  = 2,     // II
   KM3_low  = 4,     // III
}TKeyMode;
 
// Функциональные действия клавиатуры:
typedef enum
{
   KA_NONE,
   KA_SHIFT_ONCE,
   KA_SHIFT_PERMANENT,
   KA_MENU,
   KA_ENTER,
   KA_BACK,
   KA_DEL,
   KA_UP,
   KA_LEFT,
   KA_RIGHT,
   KA_DOWN,
   KA_III,
   KA_II,
   KA_I,
   KA_VOLUME_MINUS,
   KA_VOLUME_PLUS
}TKeyboardAction;
 
// Состояния выдачи больших или маленьких букв:
typedef enum
{
   SHIFT_NONE = 0,   // всегда маленькие буквы
   SHIFT_ONCE,       // большая буква 1 раз
   SHIFT_PERMANENT   // большие буквы постоянно
}TShiftState;
 
// Состояния отслеживания автоповтора и нажатия SHIFT:
typedef enum
{
   KEYAUTO_NONE = 0,
   KEYAUTO_PRESS_INIT,
   KEYAUTO_PRESS_PULSE,
   KEYAUTO_SHIFT_PRESS_INIT
}TKeyAutoState;
 
// Структура, где хранится состояние алгоритма функции
// отслеживания автоповтора AutoRepeatHandler:
typedef struct
{
   uint8_t scancode;
   TKeyAutoState state;
   uint32_t counter;
}TKeyInfo;
 
extern TKeyboardAction keybaction;
extern TKeyMode km;
extern TShiftState shiftstate;
 
void keypadtask(void const * argument);

Модуль TCA8418auto.c:

#include "keyapp.h"
#include "beeper.h"
#include "screenthread.h"
#include "modes.h"
#include "guiapp.h"
#include "editor.h"
#include "TCA8418.h"
 
static int16_t key_press_timeout = NO_KEY_PRESS_TIMEOUT_MS; // 30 мс
TShiftState shiftstate = SHIFT_NONE;
static SemaphoreHandle_t keybsem;
static TKeyInfo kinfo = {0, KEYAUTO_NONE, 0};
TKeyboardAction keybaction = KA_NONE;
 
// Обработчик прерывания от ножки ~INT контроллера клавиатуры TCA8418.
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
   static BaseType_t xHigherPriorityTaskWoken;   
   xSemaphoreGiveFromISR(keybsem, &xHigherPriorityTaskWoken);
}
 
// Таблица перекодировки сканкодов TCA8418 в символы ASCII.
static uint8_t KeyMap[KEYMAP_TOT_KEYS][KEYMAP_TOT_MODES] =
{ // Регистры: верхний, средний, нижний
  {      'q',       'Q',       'й',       'Й',       '1',       '1'},
  {      'w',       'W',       'ц',       'Ц',       '2',       '2'},
  {      'e',       'E',       'у',       'У',       '3',       '3'},
  {      'r',       'R',       'к',       'К',       '4',       '4'},
  {      't',       'T',       'е',       'Е',       '5',       '5'},
  {      'y',       'Y',       'н',       'Н',       '6',       '6'},
  {      'u',       'U',       'г',       'Г',       '7',       '7'},
  {      'i',       'I',       'ш',       'Ш',       '8',       '8'},
  {      'o',       'O',       'щ',       'Щ',       '9',       '9'},
  {      'p',       'P',       'з',       'З',       '0',       '0'},
 
  {      'a',       'A',       'ф',       'Ф',       '?',       '?'},
  {      's',       'S',       'ы',       'Ы',       '!',       '!'},
  {      'd',       'D',       'в',       'В',       '$',       '$'},
  {      'f',       'F',       'а',       'А',       '#',       '#'},
  {      'g',       'G',       'п',       'П',       '%',       '%'},
  {      'h',       'H',       'р',       'Р',       '(',       '('},
  {      'j',       'J',       'о',       'О',       ')',       ')'},
  {      'k',       'K',       'л',       'Л',       '+',       '+'},
  {      'l',       'L',       'д',       'Д',       '-',       '-'},
  {     '\a',      '\a',      '\a',      '\a',      '\a',      '\a'},   // TX
 
  {      'z',       'Z',       'я',       'Я',       '`',       '`'},
  {      'x',       'X',       'ч',       'Ч',       ';',       ';'},
  {      'c',       'C',       'с',       'С',       ':',       ':'},
  {      'v',       'V',       'м',       'М',       '@',       '@'},
  {      'b',       'B',       'и',       'И',       '"',       '"'},
  {      'n',       'N',       'т',       'Т',       '/',       '/'},
  {      'm',       'M',       'ь',       'Ь',      '< ',       '< '},
{ '\a', '\a', 'б', 'Б', '>', '>'}, { '\a', '\a', 'ю', 'Ю', '=', '='}, { '\a', '\a', '\a', '\a', '\a', '\a'}, // RX
 
  {      '.',       '.',       'х',       'х',       'ъ',       'Ъ'},
  {      ',',       ',',       'ж',       'Ж',       '*',       '*'},
  {      '&',       '&',       'э',       'Э',       'ё',       'Ё'},
  {      ' ',       ' ',       ' ',       ' ',       ' ',       ' '},
  {     '\a',      '\a',      '\a',      '\a',      '\a',      '\a'},   // M1
  {     '\a',      '\a',      '\a',      '\a',      '\a',      '\a'},   // M2
  {     '\a',      '\a',      '\a',      '\a',      '\a',      '\a'},   // M3
  {     '\a',      '\a',      '\a',      '\a',      '\a',      '\a'},   // SHIFT
  {     '\a',      '\a',      '\a',      '\a',      '\a',      '\a'},   // MENU
  {     '\a',      '\a',      '\a',      '\a',      '\a',      '\a'},   // ENTER
};
 
// Подпрограмма перекодировки сканкодов TCA8418.
static char fullkeysdecode (uint8_t scancode)
{
   char key = 0;
   
   switch(scancode)
   {
   case 0xC5:
      keybaction = KA_MENU;
      break;
   case 0xC6:  // ENTER
      keybaction = KA_ENTER;
      break;
   case 0xC7:  // BACK
      keybaction = KA_BACK;
      break;
   case 0xC8:  // DEL
      keybaction = KA_DEL;
      break;
   case 0xC9:  // UP
      keybaction = KA_UP;
      break;
   case 0xCA:  // LEFT
      keybaction = KA_LEFT;
      break;
   case 0xCB:  // RIGHT
      keybaction = KA_RIGHT;
      break;
   case 0xCC:  // DOWN
      keybaction = KA_DOWN;
      break;
   case 0xCE:
      // mode III
      km = KM3_low;
      keybaction = KA_III;
      break;
   case 0xCF:
      // mode II
      km = KM2_low;
      keybaction = KA_II;
      break;
   case 0xBA:
   case 0xBB:
      // Кнопки регулировки громкости:
      keybaction = (TKeyboardAction)(KA_VOLUME_MINUS + (scancode - 0xBA));
      break;
   case 0xD0:
      // mode I
      km = KM1_low;
      keybaction = KA_I;
      break;
   default:
      // Выдача символа в зависимости от регистра и состояния SHIFT:
      if (SHIFT_ONCE==shiftstate)
      {
         key = KeyMap[scancode-0x9F][km+1];
         shiftstate = SHIFT_NONE;
         UpdateAtScreen(SCR_UPDATE_RUS_ENG);
      }
      else if (SHIFT_PERMANENT==shiftstate)
         key = KeyMap[scancode-0x9F][km+1];
      else
         key = KeyMap[scancode-0x9F][km];
   }
   return key;
}
 
// Отслеживание времени, сколько не было нажатий на клавиатуре.
static bool KeyTimeout (void)
{
   bool result = false;
   switch(appmode)
   {
   case MODE_MAIN_MENU:
   case MODE_MENU_SETTINGS:
      key_press_timeout -= KEY_THREAD_SLEEP_MS;
      if (key_press_timeout < 0)
         result = true;
      break;
   default:
      key_press_timeout = NO_KEY_PRESS_TIMEOUT_MS;
   }
   return result;
}
 
// Инициализация I2C STM32 в режиме master для работы с контроллером
// клавиатуры TCA8418.
static void MX_I2C1_Init(void)
{
   hi2c1.Instance = I2C1;
   hi2c1.Init.ClockSpeed = 100000;
   hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2;
   hi2c1.Init.OwnAddress1 = 0;   // Для режима master I2C
   hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
   hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
   hi2c1.Init.OwnAddress2 = 0;
   hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
   hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
   if (HAL_I2C_Init(&hi2c1) != HAL_OK)
      HALerrorHandler(__FILE__, __LINE__);
   if (HAL_I2CEx_ConfigAnalogFilter(&hi2c1, I2C_ANALOGFILTER_ENABLE) != HAL_OK)
      HALerrorHandler(__FILE__, __LINE__);
   if (HAL_I2CEx_ConfigDigitalFilter(&hi2c1, 0) != HAL_OK)
      HALerrorHandler(__FILE__, __LINE__);
}
 
// Если на кнопке работает автоповтор, то вернет true.
static bool IsRepeatKey (uint8_t scancode)
{
   switch (scancode)
   {
   case 0xC4:     // SHIFT
   case 0xC5:     // MENU
   case 0xC6:     // ENTER
   case 0xC7:     // BACK
   case 0xC8:     // DEL
   case 0xCE:     // III
   case 0xCF:     // II
   case 0xD0:     // I
      return false;
   default:
      return true;
   }
}
 
// Функция, которая реализует работу автоповтора и поведение кнопки
// SHIFT. Чтобы отслеживался автоповтор, эта функция должна вызываться
// с периодом порядка 30 мс (в этом случае на входе scancode == 0),
// либо в любой момент получения сканкода от TCA8418 (в этом случае
// на входе 8-битный сканкод, лог. 1 в старшем разряде которого
// означает нажатие, лог. 0 отпускание). На выходе также выдает сканкод.
// 
// Если кнопка удерживалась дольше 1 секунды, то функция автоматически
// генерирует выдачу сканкодов этой кнопки каждые 30 мс для регулировки
// громкости, и (30*8) мс для символьных кнопок. Если действие на выходе
// не требуется, то на выходе возвращает 0.
static uint8_t AutoRepeatHandler (uint8_t scancode)
{
   bool press = (scancode & 0x80) ? true : false;
   switch (kinfo.state)
   {
   case KEYAUTO_NONE:
      if (press)
      {
         if (IsRepeatKey(scancode))
         {
            kinfo.scancode = scancode;
            kinfo.counter = 0;
            kinfo.state = KEYAUTO_PRESS_INIT;
         }
         else if (0xC4 == scancode)
         {
            kinfo.scancode = scancode;
            scancode = 0;
            kinfo.counter = 0;
            if (MODE_EDIT_TX_MESSAGE == appmode)
               kinfo.state = KEYAUTO_SHIFT_PRESS_INIT;
            else
               kinfo.state = KEYAUTO_NONE;
         }
      }
      else
         scancode = 0;
      break;
   case KEYAUTO_PRESS_INIT:
      if (0 == scancode)
      {
         if (kinfo.counter > 500)
         {
            scancode = kinfo.scancode;
            kinfo.state = KEYAUTO_PRESS_PULSE;
         }
         else
         {
            kinfo.counter += KEY_THREAD_SLEEP_MS;
         }
      }
      else if (press)
      {
         if (IsRepeatKey(scancode))
         {
            kinfo.scancode = scancode;
            kinfo.counter = 0;
         }
         else if (0xC4 == scancode)
         {
            kinfo.scancode = scancode;
            scancode = 0;
            kinfo.counter = 0;
            if (MODE_EDIT_TX_MESSAGE == appmode)
               kinfo.state = KEYAUTO_SHIFT_PRESS_INIT;
            else
               kinfo.state = KEYAUTO_NONE;
         }
      }
      else
      {
         scancode = 0;
         kinfo.state = KEYAUTO_NONE;
      }
      break;
   case KEYAUTO_PRESS_PULSE:
      if (0 == scancode)
      {
         kinfo.counter++;
         if (IsVolumeAction(kinfo.scancode))
         {
            scancode = kinfo.counter % 2 ? kinfo.scancode : 0;
         }
         else
         {
            scancode = (7 == (kinfo.counter % 8)) ? kinfo.scancode : 0;
         }
      }
      else if (press)
      {
         if (IsRepeatKey(scancode))
         {
            kinfo.scancode = scancode;
            kinfo.counter = 0;
         }
         else if (0xC4 == scancode)
         {
            kinfo.scancode = scancode;
            scancode = 0;
            kinfo.counter = 0;
            if (MODE_EDIT_TX_MESSAGE == appmode)
               kinfo.state = KEYAUTO_SHIFT_PRESS_INIT;
            else
               kinfo.state = KEYAUTO_NONE;
         }
      }
      else
      {
         scancode = 0;
         kinfo.state = KEYAUTO_NONE;
      }
      break;
   case KEYAUTO_SHIFT_PRESS_INIT:
      if (0 == scancode)
      {
         if (kinfo.counter < 1000)
         {
            kinfo.counter += KEY_THREAD_SLEEP_MS;
         }
         else
         {
            Beep(100);
            osDelay(100);
            Beep(100);
            // Поменять состояние SHIFT "на постоянку".
            if (SHIFT_PERMANENT == shiftstate)
            {
               keybaction = KA_NONE;
               shiftstate = SHIFT_NONE;
               UpdateAtScreen(SCR_UPDATE_RUS_ENG);
            }
            else
            {
               keybaction = KA_SHIFT_PERMANENT;
               shiftstate = SHIFT_PERMANENT;
               UpdateAtScreen(SCR_UPDATE_RUS_ENG);
            }
            kinfo.scancode = scancode = 0;
            kinfo.counter = 0;
            kinfo.state = KEYAUTO_NONE;
         }
      }
      else if (press)
      {
         if (IsRepeatKey(scancode))
         {
            kinfo.scancode = scancode;
            kinfo.counter = 0;
            if (MODE_EDIT_TX_MESSAGE == appmode)
               kinfo.state = KEYAUTO_SHIFT_PRESS_INIT;
            else
               kinfo.state = KEYAUTO_NONE;
         }
         else if (0xC4 == scancode)
         {
            kinfo.scancode = scancode;
            scancode = 0;
            kinfo.counter = 0;
            if (MODE_EDIT_TX_MESSAGE == appmode)
               kinfo.state = KEYAUTO_SHIFT_PRESS_INIT;
            else
               kinfo.state = KEYAUTO_NONE;
         }
      }
      else
      {
         if (scancode = kinfo.scancode)
         {
            // Поменять состояние SHIFT однократно.
            Beep(100);
            if (SHIFT_PERMANENT == shiftstate || (SHIFT_ONCE == shiftstate))
               shiftstate = SHIFT_NONE;
            else
            {
               shiftstate = SHIFT_ONCE;
               keybaction = KA_SHIFT_ONCE;
            }
            UpdateAtScreen(SCR_UPDATE_RUS_ENG);
         }
         kinfo.scancode = scancode = 0;
         kinfo.counter = 0;
         kinfo.state = KEYAUTO_NONE;
      }
      break;
   }
   return scancode;
}
 
// Поток, который обрабатывает клавиатурные нажатия:
void keypadtask(void const * argument)
{
   uint8_t scancode;
   
   keybsem = xSemaphoreCreateBinary();
   if( NULL == keybsem )
      FreeRTOSerrorHandler(__FILE__, __LINE__);
   MX_I2C1_Init();
   TCA8418_configure();
   for(;;)
   {
      // Цикл прокручивается каждый раз, когда контроллер TCA8418
      // выдает сканкод, либо каждые KEY_THREAD_SLEEP_MS миллисекунд.
      if (pdTRUE == xSemaphoreTake(keybsem, KEY_THREAD_SLEEP_MS))
      {
         scancode = TCA8418_getState();
         TCA8418_clearFlag();
      }
      else
      {
         scancode = 0;
         if (KeyTimeout())
         {
            SetAppMode(MODE_RX_SCREEN, SCR_UPDATE_RX_SCREEN_TEXT
                                      |SCR_UPDATE_RX_SCREEN_WATERFALL);
         }
      }
      scancode = AutoRepeatHandler (scancode);
      if (scancode)
      {
         TWork* pwork = &work[idxwork++];
         idxwork &= WORKCMDMASK;
         pwork->cmd = CMD_KEY;
         pwork->scancode = fullkeysdecode(scancode | 0x80);
         xQueueSend( work_queue, &pwork, 0 );
         key_press_timeout = NO_KEY_PRESS_TIMEOUT_MS;
      }
   }
}

[Ссылки]

1. TCA8418 I2C Controlled Keypad Scan IC With Integrated ESD Protection site:ti.com.
2. SLVA689 I2C Bus Pullup Resistor Calculation site:ti.com.
3. SPRA953 Semiconductor and IC Package Thermal Metrics site:ti.com.
4. phishman TCA8418 I2C Keypad Controller Arduino Library site:github.com.