Skip to content

Contributed by bzhou830, curated by Ai-Thinker

I posted a USB keyboard article before:

Peripheral porting: USB keyboard + M61 board - DIY experience sharing - IoT Developer Community - Ai-Thinker Forum

Per the boss's requirement, the matrix keyboard code needs to be added. Here I use the DSL board that Xiaomei gave me to connect the matrix keyboard, because the DSL board conveniently has IOs brought out — just plug in Dupont wires and it works. Couldn't be better.

For hardware wiring, only connect the left row of the printed pin headers. I'm using a 3*4 matrix keyboard, so 7 IOs are needed.

Just like the figure above.

The matrix keyboard scanning principle is simple: pull each row line low one by one, then read the corresponding column lines to determine whether a key is pressed. The code is also very simple:

cpp
#include "bflb_gpio.h"
#include "board.h"

struct bflb_device_s *gpio;

// definitions of the matrix keyboard row and column lines
const uint8_t rows[] = {GPIO_PIN_33, GPIO_PIN_32, GPIO_PIN_31};
const uint8_t cols[] = {GPIO_PIN_30, GPIO_PIN_29, GPIO_PIN_27, GPIO_PIN_25};

const uint8_t rows_cnt = sizeof(rows) / sizeof(rows[0]);
const uint8_t cols_cnt = sizeof(cols) / sizeof(cols[0]);

// initialize the gpio states
void matrix_keys_init()
{
    gpio = bflb_device_get_by_name("gpio");

    // set the row lines to output mode, output low level
    for (uint8_t i = 0; i < rows_cnt; i++) {
        bflb_gpio_init(gpio, rows, GPIO_OUTPUT | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_0);
        bflb_gpio_set(gpio, rows);
    }

    // set the column lines to input mode, pull-up input mode
    for (uint8_t i = 0; i < cols_cnt; i++) {
        bflb_gpio_init(gpio, cols, GPIO_INPUT | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_0);
    }
}

// matrix keyboard scan
uint16_t get_key_val()
{
    uint16_t val = 0;
    for (size_t i = 0; i < rows_cnt; i++) {
        // pull the row line low
        bflb_gpio_reset(gpio, rows);

        // read the column lines
        for (size_t j = 0; j < cols_cnt; j++) {
            if (bflb_gpio_read(gpio, cols[j]) == 0) {
                bflb_mtimer_delay_ms(10);
                if (bflb_gpio_read(gpio, cols[j]) == 0) {
                    val |= (1 << ((i * cols_cnt) + j));
                }
            }
        }

        // pull the row line high
        bflb_gpio_set(gpio, rows);
    }
    return val;
}

In the main function:

cpp
void matrix_keys_task(void *params)
{
    int key_val = 0;
    matrix_keys_init();
    while (1)
    {
        key_val = get_key_val();
        printf("%x\r\n", key_val);
        bflb_mtimer_delay_ms(10);
    }
}

That's how matrix keyboard scanning is implemented — isn't it simple! Go ahead and try it.

Have questions?

For other questions, please visit the unified discussion area: Ai-Thinker Discussions

Released under the MIT License. Build Time 2026-09-11 14:52:23