Proteus仿真时Virtual Terminal不显示弹出窗口
解决方法☞
调试->选中Virtual Terminal
STC-ISP生成代码
STC-ISP可以生成串口初始化代码
STC-ISP还可以下载到肯定能用的示例程序:
下载实验箱4程序包
虚拟串口的使用
[https://blog.csdn.net/farsight_2098/article/details/90210349]
[https://www.cnblogs.com/zhenghaoyu/p/10059848.html]
软件:VSPD(虚拟串口)和串口调试助手
虚拟串口软件激活COM1和COM2,
COM1负责发送数据,COM2负责接收数据
因而,串口调试助手连接COM2,Proteus相应元件绑定COM1.COM2模拟另一台设备向COM1发送/接收数据
,波特率两边一致即可
串口实现命令
已知的bug:仿真时一会儿就会卡死,好像接收数据有问题
/*---------------------------------------------------------------------*/
/* --- STC MCU Limited ------------------------------------------------*/
/*------------------------------------------------------*/
#include <stc15f2k60s2.h>
#include "intrins.h"
#include <stdio.h>
typedef unsigned char BYTE;
typedef unsigned int WORD;
#define FOSC 12000000L //系统频率
#define BAUD 9600 //串口波特率
#define NONE_PARITY 0 //无校验
#define ODD_PARITY 1 //奇校验
#define EVEN_PARITY 2 //偶校验
#define MARK_PARITY 3 //标记校验
#define SPACE_PARITY 4 //空白校验
#define PARITYBIT NONE_PARITY //定义校验位
#ifndef __STC15_H__
sfr P0M1 = 0x93;
sfr P0M0 = 0x94;
sfr P1M1 = 0x91;
sfr P1M0 = 0x92;
sfr P2M1 = 0x95;
sfr P2M0 = 0x96;
sfr P3M1 = 0xb1;
sfr P3M0 = 0xb2;
sfr P4M1 = 0xb3;
sfr P4M0 = 0xb4;
sfr P5M1 = 0xC9;
sfr P5M0 = 0xCA;
sfr P6M1 = 0xCB;
sfr P6M0 = 0xCC;
sfr P7M1 = 0xE1;
sfr P7M0 = 0xE2;
sfr AUXR = 0x8e; //辅助寄存器
sfr P_SW1 = 0xA2; //外设功能切换寄存器1
sbit P22 = P2^2;
#endif
#define S1_S0 0x40 //P_SW1.6
#define S1_S1 0x80 //P_SW1.7
bit busy;
/*
********************全局变量***************************
*/
#define uchar unsigned char
#define uint unsigned int
#define time 100 //在接收函数中通过判断是否接收超时来判断字符串是否接收完毕
#ifndef S4RI
#define S4RI 0x01 //S4CON.0
#define S4TI 0x02 //S4CON.1
#endif
#define send_string SendString
unsigned char code distab[16] = {
0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,
0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71
};//0-F
//字符串开始$,字符串结束#
int _dollar=0;
int _diese=0;
//接收/发送数据变量
uchar rec_data;
uchar send_data;
unsigned char *rec_data_array;
char send_data_array[25];
char code xuehao[]="$xuaohao:20211009128#\n";
/*
指令含义(ASCII):
$+数字+# 数码管显示数字
$+字母+# 流水灯字母状态
*/
#define SMG P7
sbit KEY = P3^3;
sbit LED1=P4^6;
sbit LED2=P4^7;
//按键状态
int count=-1;
/*
*********************结束全局变量************************
*/
//函数声明
void SendData(BYTE dat);
void SendString(char *s);
void delay(int);
void smg_display(int);
void led(uchar);
void ana_command(unsigned char*);
void key_scan();
unsigned char* Receive(int rec_i);
void main()
{
P0M0 = 0x00;
P0M1 = 0x00;
P1M0 = 0x00;
P1M1 = 0x00;
P2M0 = 0x00;
P2M1 = 0x00;
P3M0 = 0x00;
P3M1 = 0x00;
P4M0 = 0x00;
P4M1 = 0x00;
P5M0 = 0x00;
P5M1 = 0x00;
P6M0 = 0x00;
P6M1 = 0x00;
P7M0 = 0x00;
P7M1 = 0x00;
ACC = P_SW1;
ACC &= ~(S1_S0 | S1_S1); //S1_S0=0 S1_S1=0
P_SW1 = ACC; //(P3.0/RxD, P3.1/TxD)
// ACC = P_SW1;
// ACC &= ~(S1_S0 | S1_S1); //S1_S0=1 S1_S1=0
// ACC |= S1_S0; //(P3.6/RxD_2, P3.7/TxD_2)
// P_SW1 = ACC;
//
// ACC = P_SW1;
// ACC &= ~(S1_S0 | S1_S1); //S1_S0=0 S1_S1=1
// ACC |= S1_S1; //(P1.6/RxD_3, P1.7/TxD_3)
// P_SW1 = ACC;
#if (PARITYBIT == NONE_PARITY)
SCON = 0x50; //8位可变波特率
#elif (PARITYBIT == ODD_PARITY) || (PARITYBIT == EVEN_PARITY) || (PARITYBIT == MARK_PARITY)
SCON = 0xda; //9位可变波特率,校验位初始为1
#elif (PARITYBIT == SPACE_PARITY)
SCON = 0xd2; //9位可变波特率,校验位初始为0
#endif
AUXR = 0x40; //定时器1为1T模式
TMOD = 0x00; //定时器1为模式0(16位自动重载)
TL1 = (65536 - (FOSC/4/BAUD)); //设置波特率重装值
TH1 = (65536 - (FOSC/4/BAUD))>>8;
TR1 = 1; //定时器1开始启动
ES = 1; //使能串口中断
EA = 1;
/**
用户程序
*/
smg_display(4);
led('B');
SendString(xuehao);
delay(1000);
while(1){
key_scan();
rec_data_array=Receive(3);
if(*rec_data_array){
send_string(rec_data_array);
//LED2=~LED2;
}
ana_command(rec_data_array);
}
}
/*----------------------------
UART 中断服务程序
-----------------------------*/
void Uart() interrupt 4
{
if (RI)
{
RI = 0; //清除RI位
P0 = SBUF; //P0显示串口数据
P22 = RB8; //P2.2显示校验位
}
if (TI)
{
TI = 0; //清除TI位
busy = 0; //清忙标志
}
}
/*----------------------------
发送串口数据
----------------------------*/
void SendData(BYTE dat)
{
while (busy); //等待前面的数据发送完成
ACC = dat; //获取校验位P (PSW.0)
if (P) //根据P来设置校验位
{
#if (PARITYBIT == ODD_PARITY)
TB8 = 0; //设置校验位为0
#elif (PARITYBIT == EVEN_PARITY)
TB8 = 1; //设置校验位为1
#endif
}
else
{
#if (PARITYBIT == ODD_PARITY)
TB8 = 1; //设置校验位为1
#elif (PARITYBIT == EVEN_PARITY)
TB8 = 0; //设置校验位为0
#endif
}
busy = 1;
SBUF = ACC; //写数据到UART数据寄存器
}
/*----------------------------
发送字符串
----------------------------*/
void SendString(char *s)
{
while (*s) //检测字符串结束标志
{
SendData(*s++); //发送当前字符
}
}
void delay(int ms){//@12MHz
int i,j;
for(i=0;i<ms;i++){
for(j=0;j<1000;j++);
}
}
//数码管
void smg_display(int num){
SMG = ~distab[num];
}
//LED灯
void led(uchar status){
switch(status){
case 'A':LED1=0;LED2=0;break;
case 'B':LED1=1;LED2=0;break;
case 'C':LED1=0;LED2=1;break;
case 'D':LED1=1;LED2=1;break;
default:LED1=1;LED2=0;
}
}
//解析指令
void ana_command(uchar *dat){
if(*dat=="$0#"){
//数码管0
smg_display(0);
send_string("received:0");
}
if(*dat=="$1#"){
//数码管1
smg_display(1);
send_string("received:1");
}
if(*dat=="$2#"){
//数码管2
smg_display(2);
}
if(*dat=="$3#"){
//数码管3
smg_display(3);
}
if(*dat=="$4#"){
//数码管4
smg_display(4);
}
if(*dat=="$5#"){
//数码管5
smg_display(5);
}
if(*dat=="$6#"){
//数码管6
smg_display(6);
}
if(*dat=="$7#"){
//数码管7
smg_display(7);
}
if(*dat=="$8#"){
//数码管8
smg_display(8);
}
if(*dat=="$9#"){
//数码管9
smg_display(9);
}
if(*dat=="$A#"){
led('A');
send_string("received:A");
}
if(*dat=="$B#"){
led('B');
send_string("received:B");
}
if(*dat=="$C#"){
led('C');
send_string("received:C");
}
if(*dat=="$D#"){
led('D');
send_string("received:D");
}
}
//按键监听
void key_scan(){
uchar temp[5];
if(KEY==0){
delay(200);
if(KEY==0){
count++;
if(count>9) count=0;
smg_display(count);
LED1=~LED1;LED2=~LED2;
sprintf(temp,"$%d#",count);
send_string(temp);
//sprintf(temp,"$%c#",'A');
//send_string(temp);
}
}
}
//字符串接受
unsigned char* Receive(int rec_i)
{
int rec_fin_flag=0;
//unsigned count=0; //超时机制 用于短暂计数用作延时
unsigned char rec_str[6];
//unsigned char* rec_str;
unsigned count1;
while(rec_fin_flag!=1)
{
rec_str[rec_i]=SBUF;
RI=0;
rec_i++;
count1=0;
while(rec_fin_flag==0)
{
if(RI==1) break;
count1++;
if(count1==time) rec_fin_flag=1;
}
}
RI=0;
return rec_str;
}
效果