1 В избранное 0 Ответвления 0

OSCHINA-MIRROR/wei513723-key_board

Присоединиться к Gitlife
Откройте для себя и примите участие в публичных проектах с открытым исходным кодом с участием более 10 миллионов разработчиков. Приватные репозитории также полностью бесплатны :)
Присоединиться бесплатно
Клонировать/Скачать
Внести вклад в разработку кода
Синхронизировать код
Отмена
Подсказка: Поскольку Git не поддерживает пустые директории, создание директории приведёт к созданию пустого файла .keep.
Loading...
README.md

key_board

Введение

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

Использование

  1. Инициализировать соответствующие аппаратные ресурсы.
  2. Предоставить 1 мс таймер для периодического вызова функции key_check.
  3. Предоставить описание кнопок и функции чтения/записи ввода-вывода.
  4. Зарегистрировать клавиатуру в системе.
  5. Для конкретных операций обратитесь к примеру программы STM32.
  6. Поскольку программа по умолчанию использует динамическую память, если вы обнаружите, что результаты выполнения программы не являются нормальными, попробуйте увеличить пространство кучи вашей программы или зарегистрировать интерфейс отладки для анализа причины.
  7. Более подробные инструкции по использованию см. в подробных инструкциях по использованию или примере программы STM32.

Дальнейшее развитие

  1. Добавить интерфейс конфигурации параметров (например, возможность настройки различных тайм-аутов).

Журнал обновлений

  1. 2021-01-15 Решена проблема, требующая дополнительного сканирования для обнаружения функций длительного нажатия и множественных нажатий.
  2. 2021-01-18 Добавлена функция подсчёта текущего нажатия клавиш, обычно используемая в ситуациях, когда требуется обнаружить определённое время без нажатия клавиши и выполнить определённые действия.
  3. 2021-01-30 Добавлена поддержка обнаружения состояний произвольного комбинирования, добавлен новый пример программы обнаружения, параметры конфигурации перемещены в отдельный файл конфигурации заголовка, а часть кода оптимизирована.
  4. 2021-02-01 Изменён формат кодирования на UTF-8 (ранее использовался GB2312).
  5. 2021-02-02 Оптимизирован пример кода, добавлена функция регистрации интерфейса вывода отладочной информации.
  6. 2021-05-19 Добавлена обработка дребезга, и один бесполезный параметр конфигурации был удалён.
  7. 2021-05-21 Решена проблема дублирования состояний из-за большого интервала сканирования по сравнению с интервалом считывания клавиш, и выполнена другая оптимизация.
  8. 2021-06-13 После рассмотрения интервал сканирования был установлен на фиксированное значение 1 мс, чтобы уменьшить количество шагов настройки.
  9. 2021-06-13 Функция включения/отключения обработки дребезга была удалена из параметров конфигурации, и обработка дребезга автоматически отключается, когда значение времени установлено на 0.
  10. 2021-06-13 Оптимизировано решение проблемы переполнения значений времени.
  11. 2021-06-13 Выполнена оптимизация некоторых деталей.
  12. 2021-10-20 Оптимизировано использование части памяти кучи.

Поддерживаемые клавиатуры

  1. Матричная клавиатура

![Матричная клавиатура](./матричная клавиатура.jpeg)

  1. Одноканальная клавиатура

![Одноканальная клавиатура](./одноканальная клавиатура.jpeg)

Подробные инструкции по использованию

Поместите файлы key_board.c, key_board.h и key_board_config.h в папку key_board и включите их в свой проект, добавив путь к файлу заголовка.

Базовая миграция функций (на примере матричной клавиатуры STM32)

Сначала необходим доступный таймер (если вы не хотите использовать таймер, вы также можете поместить его непосредственно в основной цикл, но это не рекомендуется, так как это может привести к неточности времени). Установите интервал срабатывания таймера на 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 )

Вы можете оставить комментарий после Вход в систему

Введение

Описание недоступно Развернуть Свернуть
AGPL-3.0
Отмена

Обновления (1)

все

Участники

все

Недавние действия

Загрузить больше
Больше нет результатов для загрузки
1
https://api.gitlife.ru/oschina-mirror/wei513723-key_board.git
git@api.gitlife.ru:oschina-mirror/wei513723-key_board.git
oschina-mirror
wei513723-key_board
wei513723-key_board
master