1. 程序需求:
- 通过上位机控制单片机的八个LED灯的开关
2. 开发中用到的软件
- pycharm : 开发上位机
- VSPD : 虚拟串口
- Proteus : 仿真电路
- keil C51 : 写51单片机程序
3. 具体步骤
- 首先在Proteus中连接电路:
在keil中编写单片机代码,并将生成Hex的目标文件下载到preteus的单片机内,代码如下
#include<reg51.h> #define ON 0; #define OFF 1; sbit LED1 = P2^0; sbit LED2 = P2^1; sbit LED3 = P2^2; sbit LED4 = P2^3; sbit LED5 = P2^4; sbit LED6 = P2^5; sbit LED7 = P2^6; sbit LED8 = P2^7; unsigned char DATA = 0; void delay(unsigned int a) { while(a--); } void Usat_Init() { EA = 1; // 打开中断总开关 ES = 1; // 打开串口中断开关 SCON = 0x50; // 选择方式1 PCON = 0x80; // 波特率加倍 TH1 = 0xF3; // 芯片频率为12MHz, 设置波特率为2400, 在SMOD作用下加倍,4800 TL1 = 0xF3; // 重载值 TMOD = 0x20; // 选择计时器1,方式2 TR1 = 1; // 启动计时器1 } void main(void) { unsigned char num = 3; Usat_Init(); //LED1 = ON; while(1) { } } void Usat_Func() interrupt 4 { //delay(0xfff); while(RI == 0); RI = 0; DATA = SBUF; switch (DATA) { case 0x01: LED1 = ~LED1; break; case 0x02: LED2 = ~LED2; break; case 0x03: LED3 = ~LED3; break; case 0x04: LED4 = ~LED4; break; case 0x05: LED5 = ~LED5; break; case 0x06: LED6 = ~LED6; break; case 0x07: LED7 = ~LED7; break; case 0x08: LED8 = ~LED8; break; } }
使用pycharm开发上位机,代码如下:
import serial from serial.tools import list_ports import tkinter as tk from tkinter import ttk from tkinter.messagebox import * class MySerial: def __init__(self): self.ser = serial.Serial() # 显示连接的端口 # 建立连接 def connect(self, port, baudrate, bytesize, stopbits, parity, timeout): # 如果之前打开的串口没有关闭,这里自动关闭 if self.ser.is_open: self.ser.close() self.ser = serial.Serial(port=port, baudrate=baudrate,bytesize=bytesize, stopbits=stopbits, parity=parity, timeout=timeout) print("连接成功") # 发送数据 def send(self, data): self.ser.write(data.encode()) # 接受数据 def rcve(self): pass def close(self): self.ser.close() class Interface: def __init__(self): self.my_serial = MySerial() self.window = tk.Tk() self.window.title("LED上位机") self.window.geometry("400x300") self.port_name_var = tk.Variable() self.baudrate_var = tk.Variable() self.button_connect_var = tk.Variable() self.button_connect_var.set("打开串口") self.serial_status = "OFF" self.combobox_port = ttk.Combobox(self.window, textvariable=self.port_name_var) self.combobox_baudrate = ttk.Combobox(self.window, textvariable=self.baudrate_var) self.button_connect = tk.Button(self.window, textvariable=self.button_connect_var, command=self.open_close_serial) self.button_led1 = tk.Button(self.window, text="LED1", command=lambda: self.command(str(chr(0x01)))) self.button_led2 = tk.Button(self.window, text="LED2", command=lambda: self.command(str(chr(0x02)))) self.button_led3 = tk.Button(self.window, text="LED3", command=lambda: self.command(str(chr(0x03)))) self.button_led4 = tk.Button(self.window, text="LED4", command=lambda: self.command(str(chr(0x04)))) self.button_led5 = tk.Button(self.window, text="LED5", command=lambda: self.command(str(chr(0x05)))) self.button_led6 = tk.Button(self.window, text="LED6", command=lambda: self.command(str(chr(0x06)))) self.button_led7 = tk.Button(self.window, text="LED7", command=lambda: self.command(str(chr(0x07)))) self.button_led8 = tk.Button(self.window, text="LED8", command=lambda: self.command(str(chr(0x08)))) self.combobox_port.place(relx=1/9, rely=1/8, relwidth=2/9, relheight=1/10) self.combobox_baudrate.place(relx=6/9, rely=1/8, relwidth=2/9, relheight=1/10) self.button_connect.place(relx=3/9, rely=5/16, relwidth=3/9, relheight=1/8) self.button_led1.place(relx=1 / 9, rely=2 / 4, relwidth=1 / 9, relheight=1 / 8) self.button_led2.place(relx=3 / 9, rely=2 / 4, relwidth=1 / 9, relheight=1 / 8) self.button_led3.place(relx=5 / 9, rely=2 / 4, relwidth=1 / 9, relheight=1 / 8) self.button_led4.place(relx=7 / 9, rely=2 / 4, relwidth=1 / 9, relheight=1 / 8) self.button_led5.place(relx=1 / 9, rely=3 / 4, relwidth=1 / 9, relheight=1 / 8) self.button_led6.place(relx=3 / 9, rely=3 / 4, relwidth=1 / 9, relheight=1 / 8) self.button_led7.place(relx=5 / 9, rely=3 / 4, relwidth=1 / 9, relheight=1 / 8) self.button_led8.place(relx=7 / 9, rely=3 / 4, relwidth=1 / 9, relheight=1 / 8) # 显示串口列表 def show_list(self): # 显示串口列表 self.combobox_port['values'] = [x.name for x in list(list_ports.comports())] # 显示波特率列表 self.combobox_baudrate['values'] = [600, 1200, 1800, 2400, 4800, 9600, 19200, 38400, 57600, 115200] def open_close_serial(self): var = self.button_connect_var.get() if var == "打开串口": port = self.combobox_port.get() baudrate = self.baudrate_var.get() print(port) if port == "": return try: self.my_serial.connect(port=port, baudrate=baudrate, bytesize=8, stopbits=1, parity="N", timeout=1) self.button_connect_var.set("关闭串口") self.combobox_baudrate.configure(state="disable") self.combobox_port.configure(state="disable") except: showerror("串口错误", "该串口被占用或不存在!") else: self.my_serial.close() self.button_connect_var.set("打开串口") self.combobox_baudrate.configure(state="enable") self.combobox_port.configure(state="enable") def command(self, data): self.my_serial.send(data=data) def run(self): self.show_list() self.window.mainloop() if __name__ == '__main__': interface = Interface() interface.run()
打开VSPD软件,建立一对虚拟串口,我这里的串口是COM5和COM6,一端连接的单片机,另一端连接的上位机:
在开始运行前,我们需要配置proteus里面外设的波特率(由你的单片机程序设定的)。
仿真效果如下: