使用Proteus实现51单片机的串口通讯仿真实验
1. 程序需求:
2. 开发中用到的软件
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里面外设的波特率(由你的单片机程序设定的)。
仿真效果如下: