【单片机】— {STC15}—{双机通信&异步串行通信&Proteus}

【单片机】— {STC15}—{双机通信&异步串行通信&Proteus}

例一

 ●题目

在这里插入图片描述

 ●原理图

在这里插入图片描述
在这里插入图片描述

 ●Method

  ●Method 1

这道例题是来自丁向荣老师的《单片微机原理与接口技术》上的演示例题。
在这里插入图片描述
同时,也给出了代码,同时在老师的网课中也进行了演示,代码如下:

#include<STC15.H>
#include<intrins.h>

#define uchar unsigned char
#define uint unsigned int
	
uchar temp;    
uchar temp1; 

void Delay100ms()		//@11.0592MHz
{
	unsigned char i, j, k;

	_nop_();
	_nop_();
	i = 5;
	j = 52;
	k = 195;
	do
	{
		do
		{
			while (--k);
		} while (--j);
	} while (--i);
}
void UartInit(void)		//[email protected]
{
	SCON = 0x50;		//8位数据,可变波特率
	AUXR |= 0x40;		//定时器1时钟为Fosc,即1T
	AUXR &= 0xFE;		//串口1选择定时器1为波特率发生器
	TMOD &= 0x0F;		//设定定时器1为16位自动重装方式
	TL1 = 0xE0;		//设定定时初值
	TH1 = 0xFE;		//设定定时初值
	ET1 = 0;		//禁止定时器1中断
	TR1 = 1;		//启动定时器1
}
//-----------------------------------IO口初始化函数-----------------------------//
void GPIO(void)
{
	P0M1=0;
	P0M0=0;
	P1M1=0;
	P1M0=0;
	P2M1=0;
	P2M0=0;
	P3M1=0;
	P3M0=0;
	P4M1=0;
	P4M0=0;
	P5M1=0;
	P5M0=0;

}
void main()
{
	GPIO();    //调用IO初始化函数
	UartInit();//调用串行口1初始化函数
	ES=1;
	EA=1;
	while(1)
	{
		temp=P3;
		temp=temp&0X0C;  //读P33,P32引脚的输入状态值
		SBUF=temp;       //串行发送
		while(TI==0);    //检测穿行发送是否结束
		TI=0;
		Delay100ms();	   //设置串行发送间隔
	}
}

void uart_isr() interrupt 4  //串行接收中断函数
{
	if(RI==1)
	{
		RI=0;
		temp1=SBUF;
		switch(temp1&0x0c)
	   	{
			case 0x00:P4=0XFE;break;
			case 0x04:P4=0XFD;break;
			case 0x08:P4=0XFB;break;
			default:P4=0XF7;break;
		  }		
	}
}

  但实际的运行结果是:双机串行异步通信只能发送一次数据,即刚上电时刻自锁开关的状态值,之后无论开关状态如何,数据都不能继续发送。(没有尝试过其他的热启动复位)。网上有说是发送中断标志位TI或(和)接收中断标志位RI实际上没有清零的,也没有解决。
在这里插入图片描述

  ●Method 2

参照官方例程和DL的代码,修改出了一个暂且在仿真中能正常使用的的程序(区别以及原因ing):

#include<STC15.H>
#include<intrins.h>

#define uchar unsigned char
#define uint unsigned int
	
uchar temp;     //串行发送临时传递参数
uchar temp1;    //串行接收临时传递参数 
uchar busy;     //正忙标志(数据正在传输)
void Delay100ms();		//@11.0592MHz
void GPIO(void);      //IO口初始化函数
void UartInit(void);	//[email protected] 串行口1初始化函数
void SendData(void);  //发送串口数据 (串行发送采用查询方式)
	
void main()
{
	GPIO();
	UartInit();
	ES=1;   //允许串行口1中断
	EA=1;   //总中断允许控制位
	while(1)
	{
      SendData();  //发送串口数据
	}
}

//-----------------------------------IO口初始化函数-----------------------------//
void GPIO(void)
{
	P0M1=0;
	P0M0=0;
	P1M1=0;
	P1M0=0;
	P2M1=0;
	P2M0=0;
	P3M1=0;
	P3M0=0;
	P4M1=0;
	P4M0=0;
	P5M1=0;
	P5M0=0;

}

//-------------------------------------串行口1初始化函数-----------------------------//
void UartInit(void)		//[email protected]
{
	SCON = 0x50;		 //8位数据,可变波特率
	AUXR |= 0x40;		 //定时器1时钟为Fosc,即1T
	AUXR &= 0xFE;		 //串口1选择定时器1为波特率发生器
	TMOD &= 0x0F;		 //设定定时器1为16位自动重装方式
	TL1 = 0xE0;		   //设定定时初值
	TH1 = 0xFE;		   //设定定时初值
	ET1 = 0;		     //禁止定时器1中断
	TR1 = 1;		     //启动定时器1
}
//------------------------串行接收中断函数 (串行接收采用中断方式)---------------------//
void uart_isr() interrupt 4
{
	if(RI)
	{
	  RI=0;       //清除RI位
      temp1=SBUF;
      switch(temp1&0x0c)
	   	{
			   case 0x00:P4=0XFE;break;
			   case 0x04:P4=0XFD;break;
			   case 0x08:P4=0XFB;break;
			   default:P4=0XF7;break;
		  }		
   }
	 if(TI)
    {
       TI = 0;         //清除TI位
       busy = 0;       //清零正忙标志
    }

}


//-----------------------发送串口数据(串行发送采用查询方式)-------------------------------//
void SendData(void)
{
    while(busy);          //等待前面的数据发送完成
    temp = P3;            //
	temp=temp&0X0C;       //读取P33,P32引脚的输入状态值 
    busy = 1;             //将正忙标志置1,
	SBUF = temp;          //串行发送
}

猜你喜欢

转载自blog.csdn.net/qq_43935020/article/details/106909431