key_board
Используется для поддержки небольших и многофункциональных кнопок в однокристальных микроконтроллерах. Программное обеспечение основано на многоуровневой концепции, которая обеспечивает независимость от платформы. Пользователю необходимо предоставить только базовую информацию о кнопках и функции чтения/записи ввода-вывода. Это делает его удобным для переноса и поддерживает несколько матричных клавиатур и несколько одноканальных контроллеров клавиатуры. В настоящее время реализованы функции нажатия, отпускания, длительного нажатия, автоматического запуска при длительном нажатии, множественного нажатия и непрерывного нажатия. Функции могут быть произвольно объединены (поддерживаются состояния на одной и той же или разных временных осях), и в будущем будут добавлены дополнительные функции.


Поместите файлы key_board.c, key_board.h и key_board_config.h в папку key_board и включите их в свой проект, добавив путь к файлу заголовка.
Сначала необходим доступный таймер (если вы не хотите использовать таймер, вы также можете поместить его непосредственно в основной цикл, но это не рекомендуется, так как это может привести к неточности времени). Установите интервал срабатывания таймера на 1 мс. Подготовьте базовую информацию об ожидаемых клавишах, которую можно найти в структуре struct key_pin_t в файле key_board_sample.c, например:
struct key_pin_t {
GPIO_TypeDef *port; //порт кнопки
uint16_t pin; //контакт кнопки
GPIO_PinState valid; //действительный уровень кнопки (уровень, когда кнопка нажата)
GPIO_PinState invalid; //недействительный уровень кнопки (уровень, когда кнопка не используется)
/*
Можно добавить свои собственные параметры
*/
};
Определите информацию о клавишах для мониторинга, которую можно найти в массиве const struct key_pin_t key_pin_sig[] в файле key_board_sample.c, соответствующем заголовочном файле key_board_sample.h, например:
//Глобальная переменная
const struct key_pin_t key_pin_sig[] = {
{
.port = KEY_PORT_J12,
.pin = KEY_PIN_J12,
.valid = KEY_PRESS_LEVEL_J12,
.invalid = KEY_RELEASE_LEVEL_J12
},
{
.port = KEY_PORT_J34,
.pin = KEY_PIN_J34,
.valid = KEY_PRESS_LEVEL_J34,
.invalid = KEY_RELEASE_LEVEL_J34
},
{
.port = KEY_PORT_J56,
.pin = KEY_PIN_J56,
.valid = KEY_PRESS_LEVEL_J56,
.invalid = KEY_RELEASE_LEVEL_J56
}
};
Если это матричная клавиатура, вам также необходимо определить информацию о контрольном вводе-выводе, которую можно найти в массиве struct key_pin_t const key_pin_ctrl[] в файле key_board_sample.c и соответствующем заголовочном файле key_board_sample.h, например:
const struct key_pin_t key_pin_ctrl[] = {
{
.port = KEY_PORT_J135,
.pin = KEY_PIN_J135,
.valid = KEY_CTL_LINE_ENABLE,
.invalid = KEY_CTL_LINE_DISABLE
},
{
.port = KEY_PORT_J246,
.pin = KEY_PIN_J246,
.valid = KEY_CTL_LINE_ENABLE,
.invalid = KEY_CTL_LINE_DISABLE
}
};
Реализуйте функцию чтения уровня ввода-вывода, которую можно найти в функции pin_level_get в файле key_board_sample.c, например:
static inline bool pin_level_get(const void *desc)
{
struct key_pin_t *pdesc;
pdesc = (struct key_pin_t *)desc;
return HAL_GPIO_ReadPin(pdesc->port, pdesc->pin) == pdesc->valid;
}
Если это матричная клавиатура, также необходимо реализовать функцию записи уровня ввода-вывода, которую можно найти в функции pin_level_set в файле key_board_sample.c, например:
static inline void pin_level_set(const void *desc, bool flag)
{
struct key_pin_t *pdesc;
pdesc = (struct key_pin_t *)desc;
HAL_GPIO_WritePin(pdesc->port, pdesc->pin, flag ? pdesc->valid : pdesc->invalid);
}
Определите идентификатор кнопки и функцию struct key_public_sig_t, которую можно найти в массиве const struct key_public_sig_t key_public_sig[] в файле key_board_sample.c и заголовочном файле key_board.h, например:
const struct key_public_sig_t key_public_sig[] = {
KEY_PUBLIC_SIG_DEF(KEY_UP, &key_pin_sig[0], pin_level_get, KEY_FLAG_NONE),
KEY_PUBLIC_SIG_DEF(KEY_LEFT, &key_pin_sig[1], pin_level_get, KEY_FLAG_NONE),
KEY_PUBLIC_SIG_DEF(KEY_DOWN, &key_pin_sig[2], pin_level_get, KEY_FLAG_NONE)
};
Если это матричная клавиатура, также необходимо определить идентификатор управляющего ввода-вывода и функцию struct key_public_ctrl_t, которую можно найти в файле key_board_sample.c. Перевод текста на русский язык:
key_public_ctrl[]: структура массива, соответствующая заголовочному файлу key_board.h, например:
const struct key_public_ctrl_t key_public_ctrl[] = {
KEY_PUBLIC_CTRL_DEF(&key_pin_ctrl[0], pin_level_set),
KEY_PUBLIC_CTRL_DEF(&key_pin_ctrl[1], pin_level_set)
};
Инициализация клавиатуры, можно обратиться к функции GPIO_Key_Board_Init() в файле key_board_sample.c, например:
void GPIO_Key_Board_Init(void) {
// Инициализация аппаратного обеспечения ввода-вывода
RCC_KEY_BOARD_CLK_ENABLE();
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
for (i = 0; i < ARRAY_SIZE(key_pin_sig); i++) {
GPIO_InitStruct.Pin = key_pin_sig[i].pin;
HAL_GPIO_Init(key_pin_sig[i].port, &GPIO_InitStruct);
}
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
for (i = 0; i < ARRAY_SIZE(key_pin_ctrl); i++) {
GPIO_InitStruct.Pin = key_pin_ctrl[i].pin;
HAL_GPIO_Init(key_pin_ctrl[i].port, &GPIO_InitStruct);
}
// Инициализация клавиатуры
key_board_init();
// Регистрация клавиатуры в системе (матричная клавиатура)
key_board_register(KEY_BOARD_MATRIX, key_public_sig, ARRAY_SIZE(key_public_sig), key_public_ctrl, ARRAY_SIZE(key_public_ctrl));
}
Основной цикл псевдокода, дополнительные примеры см. в файле main_test.c:
int main(void) {
// Инициализация оборудования ввода-вывода и регистрация клавиатуры
GPIO_Key_Board_Init();
// Инициализация таймера для сканирования клавиш (1 мс)
init_tmr();
for(;;) {
if (key_check_state(KEY_UP, KEY_RELEASE)) {
PRINTF("KEY_UP KEY_RELEASE\r\n");
}
if (key_check_state(KEY_UP, KEY_PRESS)) {
PRINTF("KEY_UP KEY_PRESS\r\n");
}
}
}
// Функция обработки прерывания таймера
void tmr_irq_callback(void) {
// Вызов функции сканирования клавиш
key_check();
}
Сначала убедитесь, что макрос KEY_LONG_SUPPORT в файле key_board_config.h включён, и правильно установите значение макроса KEY_DEFAULT_LONG_TRRIGER_TIME;
Для обнаружения длинного нажатия необходимо настроить функцию клавиши следующим образом:
KEY_PUBLIC_SIG_DEF(KEY_UP, &key_pin_sig[0], pin_level_get, KEY_FLAG_PRESS_LONG | KEY_FLAG_RELEASE_LONG)
Пример использования:
if (key_check_state(KEY_UP, KEY_PRESS_LONG)) {
PRINTF("KEY_UP KEY_PRESS_LONG\r\n");
}
if (key_check_state(KEY_UP, KEY_RELEASE_LONG)) {
PRINTF("KEY_UP KEY_RELEASE_LONG\r\n");
}
Сначала убедитесь, что макрос KEY_CONTINUOUS_SUPPORT в файле key_board_config.h включён, и правильно установите значения макросов KEY_DEFAULT_CONTINUOUS_INIT_TRRIGER_TIME и KEY_DEFAULT_CONTINUOUS_PERIOD_TRRIGER_TIME;
Чтобы обнаружить непрерывное нажатие, необходимо настроить функцию клавиши следующим образом:
KEY_PUBLIC_SIG_DEF(KEY_UP, &key_pin_sig[0], pin_level_get, KEY_FLAG_PRESS_CONTINUOUS)
Пример использования:
if (key_check_state(KEY_UP, KEY_PRESS_CONTINUOUS)) {
PRINTF("KEY_UP KEY_PRESS_CONTINUOUS\r\n");
}
Сначала убедитесь, что макрос KEY_MULTI_SUPPORT в файле key_board_config.h включён, и правильно установите значение макроса KEY_DEFAULT_MULTI_INTERVAL_TIME;
Чтобы обнаружить множественные нажатия, необходимо настроить функцию клавиши следующим образом:
KEY_PUBLIC_SIG_DEF(KEY_UP, &key_pin_sig[0], pin_level_get, KEY_FLAG_PRESS_MULTI | KEY_FLAG_RELEASE_MULTI)
Пример использования:
unsigned int res;
res = key_check_state(KEY_UP, KEY_PRESS_MULTI);
if (res) {
PRINTF("KEY_UP KEY_PRESS_MULTI:%d\r\n", res);
}
res = key_check_state(KEY_UP, KEY_RELEASE_MULTI);
if (res) {
PRINTF("KEY_UP KEY_RELEASE_MULTI:%d\r\n", res);
}
Благодарим пользователя @shi-yuhu за обратную связь, мы исправили предыдущий пример использования.
Пример использования:
unsigned int key_down_release_long, key_up_release_long;
key_down_release_long = key_check_state(KEY_DOWN, KEY_RELEASE_LONG);
key_up_release_long = key_check_state(KEY_UP, KEY_RELEASE_LONG);
if (key_down_release_long && key_up_release_long) {
PRINTF("KEY_DOWN KEY_RELEASE_LONG && KEY_UP KEY_RELEASE_LONG\n");
}
Сначала убедитесь, что макрос KEY_COMBINE_SUPPORT в файле key_board_config.h включён, и правильно установите значение макроса KEY_DEFAULT_COMBINE_INTERVAL_TIME;
Пример использования:
// Используется для сохранения идентификатора зарегистрированного комбинированного состояния
static unsigned int test_id1, test_id2;
// Определяем состояние для проверки
const struct key_combine_t test_combine1[] = {
{ .id = KEY_UP, .state = KEY_PRESS },
{ .id = KEY_DOWN, .state = KEY_PRESS_LONG },
{ .id = KEY_UP, .state = KEY_PRESS }
};
// Регистрируем комбинированное состояние
test_id1 = key_combine_register(test_combine1, ARRAY_SIZE(test_combine1));
const struct key_combine_t test_combine2[] = {
{ .id = KEY_UP, .state = KEY_PRESS },
{ .id = KEY_DOWN, .state = KEY_PRESS },
{ .id = KEY_UP, .state =
``` ```
KEY_PRESS },
{ .id = KEY_DOWN, .state = KEY_PRESS },
};
test_id2 = key_combine_register(test_combine2, ARRAY_SIZE(test_combine2));
if(key_check_combine_state(test_id1))
{
PRINTF("combine test_id1\r\n");
}
if(key_check_combine_state(test_id2))
{
PRINTF("combine test_id2\r\n");
}```
Это язык C.
В тексте идёт речь о проверке состояния комбинаций клавиш.
Вы можете оставить комментарий после Вход в систему
Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.
Комментарии ( 0 )