【自学嵌入式:51单片机】用UART串口通信和矩阵按键实现快速打开win系统中的一些程序

如题,代码实际非常简单,简单说一下我的矩阵按键映射
我矩阵按键映射是
1 2 3 20
4 5 6 23
7 8 9 26
11 12 13 30
因为我最开始用矩阵键盘做9x9非0数字键,懒得改了

相关电路

image

单片机端程序源码

单片机端程序源码如下

#include <REGX52.H>
#define uint8 unsigned char
#define uint16 unsigned int
uint8 KeyNum = 0; //键码值

//延迟函数
void Delay(uint16 xms)		//@11.0592MHz
{
	unsigned char i, j;
	while(xms--)
	{
		i = 2;
		j = 199;
		do
		{
			while (--j);
		} while (--i);
	}
}

//矩阵按键识别
uint8 matrixKey()
{
	uint8 KeyNumber=10; //当前按键对应的数字
	// 第一步:检测行
    P1 = 0x0F;  // 行线(P17-P14)置0,列线(P13-P10)保持高(默认)
	//高电平会被低电平拉低
	Delay(10); //消抖,让按键确定按下来
	
	//有按键输入才检测
	if(P1 != 0x0F)
	{
		//先扫描行
		switch(P1)
		{
			case (0x07):
				KeyNumber = 1;
				break;
			case (0x0B):
				KeyNumber = 2;
				break;
			case (0x0D):
				KeyNumber = 3;
				break;
			case (0x0E):
				KeyNumber = 20;
				break;
		}
		//再扫描列
		P1=0XF0;
		switch(P1)
		{
			case (0x70):
				Delay(20); //消抖
				while(P1 == 0x70);
				Delay(20); //消抖
				KeyNumber = KeyNumber;
				break;
			case (0xB0):
				Delay(20); //消抖
				while(P1 == 0xB0);
				Delay(20); //消抖
				KeyNumber+=3;
				break;
			case (0xD0):
				Delay(20); //消抖
				while(P1 == 0xD0);
				Delay(20); //消抖
				KeyNumber+=6;
				break;
			//第四行比较特殊,都是0
			case (0XE0):
				Delay(20); //消抖
				while(P1 == 0xE0);
				Delay(20); //消抖
				KeyNumber+=10;
				break;
		}
	}
	Delay(10);
	return KeyNumber;
}

//初始化UART串口
void initUART()
{
	SCON = 0x50; // 0101 0000 工作模式1,允许接收
	TMOD = 0x20; //设置定时器T1工作模式,8位自动重载
	// 8位自动重载,省得手动填充波特率
	TH1 = 0xFA; //用4800波特率,按公式计算一下是256-6=250
	TL1 = 0xFA;
	ES = 1; //打开串口
	EA = 1; //开总中断
	TR1 = 1; //打开波特率发生器(定时器1)
}

//Uart串口通信需要发送的字节
void sentUART(uint8 Byte)
{
	TI = 1; //打开发送中断,准备发送数据
	SBUF = Byte; //待发送数据写入缓存
	while(TI == 0); //TI变成1才算发送完成,等待它发送完成
	TI = 0; // 软件复位
}

void main()
{
	initUART();
	while(1)
	{
		KeyNum = matrixKey();
		//默认不发,按下才发
		if(KeyNum != 10)
		{
			sentUART(KeyNum);
		}
	}
}

电脑端Python串口通信源码

import serial
import serial.tools.list_ports
import subprocess  # 用于后续打开应用程序
import ctypes
import sys
import webbrowser

# 判断是否是管理员状态
def is_admin():
    try:
        return ctypes.windll.shell32.IsUserAnAdmin()
    except:
        return False

# 以管理员模式运行
def run_as_admin():
    ctypes.windll.shell32.ShellExecuteW(
        None, "runas", sys.executable, sys.argv[0], None, 1)
    sys.exit()

def find_mcu_port():
    """自动检测可能的51单片机串口"""
    ports = list(serial.tools.list_ports.comports())
    for port in ports:
        # 尝试识别常见的51单片机端口特征
        # 可根据实际设备修改识别条件
        if ("USB-SERIAL" in port.description or
                "CH340" in port.description or  # 常见的USB转串口芯片
                "COM6" in port.device):  # 包含用户提到的COM6
            return port.device
    # 如果没有找到特定设备,返回第一个可用端口
    if ports:
        return ports[0].device
    return None


def handle_key_press(key_code):
    # 1打开记事本
    if key_code == 1:
        open_application("C:/Windows/System32/notepad.exe");
    # 2打开CMD
    elif key_code == 2:
        subprocess.Popen(
            "cmd.exe",
            creationflags=subprocess.CREATE_NEW_CONSOLE  # 关键参数:创建新控制台窗口
        )
    # 3打开资源管理器
    elif key_code == 3:
        open_application("C:/Windows/explorer.exe");

    # 20(实际上是第一行第四个按键,我那个程序的逻辑是只启用9x9键盘,就没做4x4键盘准确数字映射,不过无所谓)
    # 20打开系统设置
    elif key_code == 20:
        subprocess.run(['start', 'ms-settings:'], shell=True, check=True)

    # 4打开Bing搜索
    elif key_code == 4:
        webbrowser.open("https://cn.bing.com/")

    # 以此类推,懒得写了

def open_application(app_path):
    """打开指定的应用程序"""
    try:
        subprocess.Popen(app_path)
        print(f"已打开应用: {app_path}")
    except Exception as e:
        print(f"打开应用失败: {e}")


def main():
    # 查找单片机端口
    port = find_mcu_port()
    if not port:
        print("未找到可用的串口,请检查单片机连接")
        return

    print(f"已找到单片机,使用串口: {port}")

    # 配置串口参数
    ser = None
    try:
        ser = serial.Serial(
            port=port,
            baudrate=4800,
            parity=serial.PARITY_NONE,
            stopbits=serial.STOPBITS_ONE,
            bytesize=serial.EIGHTBITS,
            timeout=1  # 超时时间,单位秒
        )

        print("串口连接成功,等待按键数据...")
        print("按Ctrl+C退出程序")

        # 读取串口输入信息并输出。
        while True:
            com_input = ser.read(1)
            # bytes 转 int
            val = int.from_bytes(com_input, byteorder='little', signed=False)
            if com_input:  # 如果读取结果非空,则输出
                handle_key_press(val);


    except serial.SerialException as e:
        print(f"串口通信错误: {e}")
    except KeyboardInterrupt:
        print("\n程序已手动退出")
    finally:
        if ser and ser.is_open:
            ser.close()
            print("串口已关闭")


if __name__ == "__main__":
    main()

这样按下对应按键能打开快捷操作

posted @ 2025-08-01 18:11  秦瑞迁  阅读(271)  评论(0)    收藏  举报