You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

树莓派通过C语言读取USB键盘输入的技术咨询

Hey there! I've worked through similar setups on Raspbian before, so let's walk through how to read USB keyboard input in C and send it over serial to your computer. Here's what you need to know:

1. First, Locate Your USB Keyboard Device

On Linux (including Raspbian), USB keyboards show up as input devices under /dev/input/. To find the exact path for your keyboard:

  • Run ls /dev/input/by-id/ in the terminal
  • Look for an entry with event-kbd in the name (e.g., usb-Logitech_USB_Keyboard-event-kbd)
  • Copy this path—you'll need it in your code later.
2. C Code to Read Keyboard Input & Send Over Serial

Linux uses input_event structures to handle input device events. We'll open the keyboard device file, read these events, map keycodes to readable characters, and send them over serial to your computer.

Here's a complete, ready-to-use code example:

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <linux/input.h>
#include <unistd.h>
#include <string.h>
#include <termios.h>

int serial_fd = -1;

// Map Linux keycodes to ASCII characters (expand this as needed)
char keycode_to_char(int keycode, int shift_pressed) {
    switch(keycode) {
        case KEY_A: return shift_pressed ? 'A' : 'a';
        case KEY_B: return shift_pressed ? 'B' : 'b';
        case KEY_C: return shift_pressed ? 'C' : 'c';
        case KEY_1: return shift_pressed ? '!' : '1';
        case KEY_2: return shift_pressed ? '@' : '2';
        case KEY_ENTER: return '\n';
        case KEY_SPACE: return ' ';
        case KEY_BACKSPACE: return '\b';
        // Add more key mappings from /usr/include/linux/input.h
        default: return 0; // Ignore unhandled keys
    }
}

// Initialize serial port for communication with your computer
void init_serial() {
    // Use /dev/ttyAMA0 or /dev/ttyS0 depending on your Pi model
    serial_fd = open("/dev/ttyAMA0", O_RDWR | O_NOCTTY | O_NDELAY);
    if (serial_fd == -1) {
        perror("Failed to open serial port");
        exit(EXIT_FAILURE);
    }

    struct termios serial_options;
    tcgetattr(serial_fd, &serial_options);

    // Configure serial settings: 9600 baud, 8N1 (8 bits, no parity, 1 stop bit)
    cfsetispeed(&serial_options, B9600);
    cfsetospeed(&serial_options, B9600);
    serial_options.c_cflag &= ~PARENB;
    serial_options.c_cflag &= ~CSTOPB;
    serial_options.c_cflag &= ~CSIZE;
    serial_options.c_cflag |= CS8;
    serial_options.c_cflag &= ~CRTSCTS; // Disable hardware flow control
    serial_options.c_cflag |= CREAD | CLOCAL; // Enable receiver, ignore modem controls
    serial_options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); // Disable canonical mode
    serial_options.c_oflag &= ~OPOST; // Disable output processing

    tcsetattr(serial_fd, TCSANOW, &serial_options);
}

// Send a character over serial
void send_over_serial(char c) {
    if (serial_fd == -1) {
        init_serial();
    }
    write(serial_fd, &c, 1);
}

int main() {
    // Replace this path with your keyboard's path from step 1
    const char* keyboard_path = "/dev/input/by-id/usb-Your_Keyboard_Model-event-kbd";
    int keyboard_fd = open(keyboard_path, O_RDONLY);
    
    if (keyboard_fd == -1) {
        perror("Failed to open keyboard device");
        exit(EXIT_FAILURE);
    }

    struct input_event event;
    int shift_active = 0;

    printf("Reading keyboard input... Press Ctrl+C to exit.\n");

    while (1) {
        ssize_t bytes_read = read(keyboard_fd, &event, sizeof(struct input_event));
        if (bytes_read == -1) {
            perror("Failed to read input event");
            close(keyboard_fd);
            exit(EXIT_FAILURE);
        }

        // Only process key press/release events
        if (event.type == EV_KEY) {
            // Update shift state
            if (event.code == KEY_LEFTSHIFT || event.code == KEY_RIGHTSHIFT) {
                shift_active = (event.value == 1); // 1 = pressed, 0 = released
            }
            // Handle key press (ignore release events for simplicity)
            else if (event.value == 1) {
                char input_char = keycode_to_char(event.code, shift_active);
                if (input_char != 0) {
                    printf("Sent: %c\n", input_char);
                    send_over_serial(input_char);
                }
            }
        }
    }

    close(keyboard_fd);
    close(serial_fd);
    return 0;
}
3. Compile and Run the Code
  1. Save the code as keyboard_serial.c
  2. Compile it with: gcc keyboard_serial.c -o keyboard_serial
  3. Run it with sudo (input devices and serial ports require root access): sudo ./keyboard_serial
4. Critical Setup Tips
  • Serial Port Configuration:
    • Open raspi-config -> Interface Options -> Serial
    • Select "No" when asked if you want a login shell over serial
    • Select "Yes" to enable the serial port hardware
    • Reboot your Pi for changes to take effect
  • Permissions (Optional): To avoid using sudo every time, add your user to the input and dialout groups:
    sudo usermod -aG input pi
    sudo usermod -aG dialout pi
    
    Log out and back in for the group changes to apply.
  • Expand Key Mappings: Check all available keycodes with cat /usr/include/linux/input.h and add more entries to the keycode_to_char function as needed.

内容的提问来源于stack exchange,提问作者Ricardo Luis

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 07:33:00