找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1019|回复: 2
打印 上一主题 下一主题
收起左侧

单片机,为什么我的键盘没反应

[复制链接]
跳转到指定楼层
楼主
ID:1139566 发表于 2024-12-14 16:35 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
#include <reg51.h>

// 定义 LCD 控制端口
sbit RS = P2^0;
sbit RW = P2^1;
sbit EN = P2^2;

unsigned int speed = 0; // 转速(0-3000 r/min)
unsigned int angle = 0; // 角位移(2-9999 °)

// 延时函数
void delay(unsigned int ms) {
    unsigned int i, j;
    for (i = 0; i < ms; i++)
        for (j = 0; j < 123; j++);
}

// LCD 使能函数
void lcd_enable() {
    EN = 1;
    delay(1);
    EN = 0;
}

// 发送命令到 LCD
void lcd_command(unsigned char cmd);

// 发送数据到 LCD
void lcd_data(unsigned char data_byte);

// 初始化 LCD
void lcd_init();

// 在 LCD 上显示字符串
void lcd_string(char *str);

// 设置 LCD 光标位置
void lcd_set_cursor(unsigned char row, unsigned char col);

// 控制步进电机
void step_motor(unsigned char pattern);

// 键盘扫描
char key_scan();

// 更新 LCD 显示
void update_display();

// 输入值
void input_value(unsigned int *value, unsigned int min, unsigned int max);

// 清除 LCD 显示
void lcd_clear();

// 发送命令到 LCD
void lcd_command(unsigned char cmd) {
    P0 = cmd;
    RS = 0;
    RW = 0;
    lcd_enable();
}

// 发送数据到 LCD
void lcd_data(unsigned char data_byte) {
    P0 = data_byte;
    RS = 1;
    RW = 0;
    lcd_enable();
}

// 初始化 LCD
void lcd_init() {
    delay(15);          // 等待超过 15ms 后上电
    lcd_command(0x38);  // 功能设置:8 位,2 行,5x7 点
    delay(5);           // 等待超过 4.1ms
    lcd_command(0x38);  // 功能设置:8 位,2 行,5x7 点
    delay(1);           // 等待超过 100us
    lcd_command(0x38);  // 功能设置:8 位,2 行,5x7 点
    lcd_command(0x0C);  // 显示开,光标关,闪烁关
    lcd_command(0x06);  // 输入模式设置:光标递增,不移动
    lcd_command(0x01);  // 清屏,光标移到首页
    delay(2);           // 等待超过 1.53ms
}

// 在 LCD 上显示字符串
void lcd_string(char *str) {
    while (*str) {
        lcd_data(*str++);
    }
}

// 设置 LCD 光标位置
void lcd_set_cursor(unsigned char row, unsigned char col) {
    unsigned char addr;
    if (row == 0)
        addr = 0x80 + col;
    else
        addr = 0xC0 + col;
    lcd_command(addr);
}

// 控制步进电机
void step_motor(unsigned char pattern) {
    P1 = pattern;
    delay(speed / 10); // 通过调整延时来控制速度
}

// 键盘扫描
char key_scan() {
    static unsigned char last_key = '\0';
    unsigned char rows[] = {0xF7, 0xFB, 0xFD, 0xFE}; // 行扫描码
    unsigned char cols[] = {0xEF, 0xDF, 0xBF, 0x7F}; // 列扫描码
    unsigned char key_matrix[4][4] = {
        {'1', '2', '3', 'A'},
        {'4', '5', '6', 'B'},
        {'7', '8', '9', 'C'},
        {'*', '0', '#', 'D'}
    };
    unsigned char row, col;

    for (row = 0; row < 4; row++) {
        P3 = rows[row]; // 设置行扫描码
        for (col = 0; col < 4; col++) {
            if (!(P3 & cols[col])) { // 检测列扫描码
                delay(50); // 增加延时时间以消除抖动
                if (last_key != key_matrix[row][col]) {
                    last_key = key_matrix[row][col];
                    return last_key;
                }
            }
        }
    }
    last_key = '\0'; // 没有按键按下
    return '\0';
}

// 更新 LCD 显示
void update_display() {
    lcd_set_cursor(0, 0);
    lcd_string("Speed:");
    lcd_data((speed / 1000) + '0');
    lcd_data(((speed % 1000) / 100) + '0');
    lcd_data(((speed % 100) / 10) + '0');
    lcd_data((speed % 10) + '0');
    lcd_string(" RPM");

    lcd_set_cursor(1, 0);
    lcd_string("Angle:");
    lcd_data((angle / 1000) + '0');
    lcd_data(((angle % 1000) / 100) + '0');
    lcd_data(((angle % 100) / 10) + '0');
    lcd_data((angle % 10) + '0');
    lcd_string(" DEG");
}

// 输入值
void input_value(unsigned int *value, unsigned int min, unsigned int max) {
    unsigned int temp_value = 0;
    char key_pressed;
    char buffer[5];
    unsigned char index = 0;

    lcd_clear(); // 清屏
    lcd_set_cursor(0, 0);
    lcd_string("Enter Value:");

    while (1) {
        key_pressed = key_scan();
        if (key_pressed >= '0' && key_pressed <= '9') {
            if (index < 4) {
                buffer[index++] = key_pressed;
                lcd_data(key_pressed);
                temp_value = temp_value * 10 + (key_pressed - '0');
            }
        } else if (key_pressed == '#') {
            if (temp_value >= min && temp_value <= max) {
                *value = temp_value;
                break;
            } else {
                lcd_set_cursor(1, 0);
                lcd_string("Invalid! Retry:");
                delay(2000);
                lcd_clear();
                lcd_set_cursor(0, 0);
                lcd_string("Enter Value:");
                temp_value = 0;
                index = 0;
            }
        }
    }
}

// 清除 LCD 显示
void lcd_clear() {
    lcd_command(0x01);
    delay(2);
}

void main() {
    unsigned char patterns[] = {0x06, 0x0E, 0x1E, 0x3E, 0x3F, 0x2F};
    unsigned char key_pressed;
    unsigned char i;

    lcd_init();
    update_display();

    while (1) {
        key_pressed = key_scan();
        switch (key_pressed) {
            case '1':
                input_value(&speed, 0, 3000);
                update_display();
                break;
            case '2':
                input_value(&speed, 0, 3000);
                update_display();
                break;
            case '3':
                input_value(&angle, 2, 9999);
                update_display();
                break;
            case '4':
                input_value(&angle, 2, 9999);
                update_display();
                break;
            default:
                break;
        }

        for (i = 0; i < 6; i++) {
            step_motor(patterns[i]);
        }
    }
}


分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:517951 发表于 2025-1-24 13:11 | 只看该作者
要用逻辑分析仪测试一下,char key_scan()函数中的 delay_ms(50)是不是确实有50ms, 这个与晶振的数值有很大关系.
回复

使用道具 举报

板凳
ID:161164 发表于 2025-1-26 16:03 | 只看该作者
原理图呢?用什么开发板?
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表