51单片机串口组网

模仿I2C协议利用串口组网

先祭上代码
书上郭天祥的代码有点问题,没法进行通信,但是程序流程图是对的。
我百度过关于51单片机串口多机组网资料,除了郭天祥的代码目前没看到有其他的资料。
我在郭天祥的基础上再改进一下

单片机连接方式在这里插入图片描述

主机通信流程图

流程图

主机代码

/***单片机串口组网
*		主机程序
*		MASTER
*
***/

#include <reg52.h>
#define uchar unsigned char
#define uint unsigned int

#define SLAVE 0x02
#define BN 16

uchar rbuf[16];
uchar tbuf[16]={"master transmit"};

void err(void)//发送复位信号
{
	SBUF = 0xff;
	while(TI!=1);
	TI = 0;
}



uchar master(uchar addr,uchar command)
{
	uchar aa,i,p;
	while(1)
	{
		SBUF = SLAVE;//呼叫从机地址
		while(TI!=1);
			TI = 0;
		while(RI!=1);//等待从机响应
			RI = 0;		
		
		if(SBUF!=addr)//如果地址错误,发送复位信号
		{
			err();
		}
		
		else	//发送完地址发送数据
		{
			TB8 = 0;//清除地址标志,变为数字标志	
			
			SBUF = command;//发命令
			while(TI!=1);
				TI = 0;
			while(RI!=1);//等待从机响应
				RI = 0;		
			//读取返回的数据
			aa = SBUF;		//接收从机返回的状态
			if((aa&0x08)==0x08)//若命令未接收,发送复位信号
			{
				TB8 = 1;
				err();
			}
			
			else
			{
				if(command==0x01)//是发送命令
				{
					//************
					if((aa&0x01)==0x01)//从机准备好接收
					{
						do
						{
							p = 0;
							//此处可优化
							for(i=0;i<BN;i++)
							{
								SBUF = tbuf[i];
								p += tbuf[i];	//p为校验和
								while(TI!=1);
								TI = 0;
							}
							
							//发送校验和
							SBUF = p;
							while(TI!=1);
								TI = 0;
							while(RI!=1);
								RI = 0;
						}
						while(SBUF!=0);//接收不对,重新发送
						TB8 = 1;//切换为地址标志
						return(0);
					}
					//************
					else
					{
						if((aa&0x02)==0x02)//接收命令,从机准备好发送
						{
							while(1)
							{
								p = 0;//清校验
								//接收数据,并计算校验p
								for(i=0;i<BN;i++)
								{
									while(RI!=1);
										RI = 0;
									rbuf[i] = SBUF;
									p += rbuf[i];
								}
								//接收p
								while(RI!=1);
									RI=0;
								if(SBUF==p)		//校验和相同发送0x00,向从机确认
								{
									SBUF=0x00;
									while(TI!=1);
									TI = 0;
									break;
								}
								else
								{
									SBUF = 0xff;//校验和不同发送0xff,
									while(TI!=1);
									TI = 0;
								}
							}
							TB8 = 1;//切换回地址标志
							return(0);
						}
					}
				}
				
			}
				
		}
	}
}

void Init_Timer()
{
	TMOD = 0x20;
	TH1 = 0xfd;
	TL1 = 0xfd;
	PCON = 0x00;
	TR1 = 1;
	SCON = 0x50;
}

void main()
{
	Init_Timer();
	master(SLAVE,0x01);
	master(SLAVE,0x02);
	while(1);
}

从机通信流程图

从机流程图

从机代码

/***单片机串口组网
*		从机程序
*		SLAVE
*
***/

#include <reg52.h>
#define uchar unsigned char
#define uint unsigned int

#define SLAVE 0x02
#define BN 16

uchar rebuf[16];
uchar trbuf[16];

bit tready;
bit rready;


//发送数据块
void str(void)
{
	uchar p,i;
	tready = 0;
	do
	{
		p = 0;
		for(i=0;i<BN;i++)
		{
			SBUF = trbuf[i];
			p += trbuf[i];
			while(TI!=1);
				TI = 0;
		}
		SBUF = p;	//发送校验和
		while(TI!=1);
			TI = 0;
		while(RI!=1);
			RI = 0;
	}while(SBUF!=0);//主机接收错误,重新发送
	SM2 = 1;
	ES = 1;	//发送完,恢复监听
}

void sre(void)//接收数据块
{
	uchar p,i;
	rready = 0;
	while(1)
	{
		p = 0;
		for(i=0;i<BN;i++)
		{
			while(RI!=1);
				RI = 0;
			rebuf[i]=SBUF;
			p += rebuf[i];
		}
		while(RI!=1);
			RI = 0;	//等待接收完成
		if(SBUF==p)
		{
			SBUF = 0x00;//校验和相同发送0x00
			break;
		}	
		else
		{
			SBUF = 0xff;
			while(TI==0);//校验和不同,重新接收
			TI = 0;
		}	
	}
	SM2 = 1;
	ES = 1;
}

void Init_Timer()
{
	TMOD = 0x20;
	TH1 = 0xfd;
	TL1 = 0xfd;
	PCON = 0x00;
	TR1 = 1;
	SCON = 0x50;
	ES = 1;
	EA = 1;
}

void main()
{
	Init_Timer();
	while(1)
	{
		tready = 1;
		rready = 1;
	}
}

void ssio(void) interrupt 4
{
	uchar a;
	RI = 0;
	ES = 0; 	//关闭串口中断
	if(SBUF!=SLAVE)	//非本机地址
	{
		ES = 1;		//继续监听
		goto reti;
	}
	SM2 = 0;	//取消监听状态
	
	SBUF = SLAVE;//发送本机地址,让主机识别
	while(TI!=1);
		TI = 0;
	while(RI!=1);
		RI = 0;
	
	if(RB8==1)	//????
	{
		SM2 = 1;
		ES = 1;
		goto reti;
	}			//如果接收到复位信号,恢复监听
	
	a = SBUF;	//传递接收的数据
	
	if(a==0x01)//从主机接收到数据
	{
		if(rready==1)
		{
			SBUF = 0x01;
		}
		else
		{
			SBUF = 0x00;
		}
		while(TI!=1);
			TI = 0;
		while(RI!=1);
			RI = 0;
		if(RB8==1)
		{
			SM2 = 1;
			ES = 1;
			goto reti;
		}
		sre();	//接收数据
	}
	else
	{
		if(a==0x02)//从机向主机发数据
		{
			if(tready==1)
			{
				SBUF = 0x02; //向主机表明,已准备好数据发送
			}
			else
			{
				SBUF = 0x00;
			}
			while(TI!=1);
				TI = 0;
			while(RI!=1);
				RI = 0;
			
			if(RB8==1)
			{
				SM2 = 1;
				ES = 1;
				goto reti;
			}
			str();
		}
		else
		{
			SBUF = 0x80;//非法命令,发送状态
			while(TI!=1);
				TI=0;
			SM2 = 1;
			ES = 1;	//开启监听
		}
	}
	reti:;
}

目前做到了地址识别,向从机发送数据,但被数据校验难到了,待更新。。。

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值