使用Proteus实现51单片机的串口通讯仿真实验

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里面外设的波特率(由你的单片机程序设定的)。

  • 仿真效果如下:

  • 物联沃分享整理
    物联沃-IOTWORD物联网 » 使用Proteus实现51单片机的串口通讯仿真实验

    发表评论