首页 > 其他分享 >51单片机笔记[8]-串口通信2

51单片机笔记[8]-串口通信2

时间:2022-09-25 18:12:06浏览次数:78  
标签:PARITY 51 S1 0x00 sfr 单片机 串口 rec define

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; 	
}

效果

标签:PARITY,51,S1,0x00,sfr,单片机,串口,rec,define
From: https://www.cnblogs.com/qsbye/p/16727893.html

相关文章

  • Visual Studio 2022 开发 STM32 单片机 - 环境搭建点亮LED灯
    安装VS2022社区版软件选择基础的功能就好  安装VisualGDB软件(CSDN资源) 按照提示一步一步安装就好 VisualGDB激活软件(CSDN资源)将如下软件放在VisualGDB的安......
  • 51单片机复位原理
    51单片机复位原理【个人解读】单片机复位电路原理图复位原理单片机里面,复位有两种情况。第一种是上电的时候;第二种是已经上电了,按下S1可以复位。复位的原理是,RST保持......
  • 串口连接到电脑,只能显示不能输入
    原因是串口RX,TX接反了.旧板的电路设计有问题,需要连接到电脑的RX,TX交叉一下,然后显示和输入都正常了.接反了为什么还能显示装置的串口输出?估计是电脑端的TX接受了装......
  • 448stream流中的常用方法_concai和451方法基本介绍
    组合concat如果有两个流,希望合并成为一个流,那么可以使用Stream接口的静态方法concatstatic<T>Stream<T>concat(Stream<?extendsT>a,Stream<?extendsT>b)备注:这......
  • javascript: 复制对象时的深拷贝及浅拷贝(chrome 105.0.5195.125)
    一,js代码<html><head><metacharset="utf-8"/><title>测试</title></head><body><buttononclick="assign()">无效:变量直接赋值</button><br/><br/><br......
  • 51 信用卡微服务集成测试自动化探索
    1简介51信用卡管家自2015年开始实施微服务架构,是业界较早尝试微服务架构的技术团队,整个团队有幸见证了微服务从最初的个服务试点到全面铺开的过程。架构的演变也催生......
  • T1051 分段函数(信息学一本通C++)
     目录 [题目描述]编写程序,计算下列分段函数y=f(x)的值。 y=-x+2.5;0<=x<5 y=2-1.5(x-3)(x-3);5<=x<10 y=x/2-1.5;10<=x<20[输入]一个浮点数N......
  • javascript: 复制数组时的深拷贝及浅拷贝(chrome 105.0.5195.125)
    一,js代码:<html><head><metacharset="utf-8"/><title>测试</title></head><body><buttononclick="assignCopy()">无效:变量直接赋值</button><br/><br......
  • STC51单片机学习笔记
    点灯系列STC8点灯点击查看STC8点灯代码#include<STC8H.H>//include了stc8h.h,就不用声明P0M1之类的//#include"reg51.h"//sfrP0M1=0x93;//sfrP0M0=0x94;......
  • 517 筛法求约数和
    视频链接: #include<iostream>usingnamespacestd;constintN=1000010;intp[N],vis[N],cnt;//g[i]表示i的最小质因子的1+p^1+...+p^kintg[N],f[N];//f[......