📄 485.c
字号:
#include<reg51.h>
#include"string.h"
/*4种帧的宏定义*/
#define ACTIVE 0x11
#define GETDATA 0x22
#define READY 0x33
#define SENDDATA 0x44
//数据帧的数据字节最多为10,帧起始字节、地址、类型、数据长度、校验和
//帧结束字节共6个字节,最短帧长为6个字节的指令帧
#define RECFRMMAXLEN 16 //接收帧的最大长度,超过此值 认为帧超长错误
#define STATUSMAXLEN 10 //设备状态信息最大长度
unsigned DevNo; //设备号
xdata unsigned StatusBuf[STATUSMAXLEN]; //设备状态信息缓冲区
sbit DE=P1^6;
/*初始化*/
void init(void)
{
P1=0xff;
DevNo=(P1&0x00111111); //读取本机设备号
TMOD=0x20;
SCON=0x50;
TH1=0xfd;
TL1=0xfd;
TR1=1;
PCON=0x00;
EA=0;
}
/*接收数据帧函数,实际上接收的是主机的指令*/
bit Recv_Data(unsigned char *type)
{
unsigned char tmp,rCount,i;
unsigned char r_buf[RECFRMMAXLEN]; //保存接收到的帧
unsigned char Flag_RecvOver; //一帧接受结束标志
unsigned char Flag_StartRec; //一帧接开始接收标志
unsigned char CheckSum; //校验和
unsigned char DataLen; //数据字节长度变量
DE=0; //禁止发送,允许接收
rCount=0;
Flag_StartRec=0;
Flag_RecvOver=0;
while(!Flag_RecvOver)
{
RI=0;
while(!RI);
tmp=SBUF;
RI=0;
/*判断是否收到字符"$",其数值为0x24*/
if((!Flag_StartRec)&&(tmp==0x24))
{
Flag_StartRec=1;
}
if(Flag_StartRec)
{
r_buf[rCount]=tmp;
rCount++;
if(tmp==0x2A)
Flag_RecvOver=1;
}
if(rCount==RECFRMMAXLEN) //帧超长错误,返回0
return 0;
}
/*计算校验和字节*/
CheckSum=0;
DataLen=r_buf[3];
for(i=0;i++;i<3+DataLen)
{
CheckSum=CheckSum+r_buf[i+1];
}
/*判断帧是否错误*/
if(rCount<6) //帧过短错误,返回0,最短的指令帧为6个字节
return 0;
if(r_buf[1]!=DevNo) //地址不符合,错误,返回0
return 0;
if(r_buf[rCount-2]!=CheckSum) //校验错误,返回0
return 0;
*type=r_buf[2]; //获取指令类型
return 1; //成功,返回1
}
/*发送单字节数据函数*/
void Send(unsigned m)
{
TI=0;
SBUF=m;
while(!TI);
TI=0;
}
/*发送数据函数,包括发送指令和发送设备状态信息*/
void Send_Data(unsigned type,unsigned len,unsigned *buf)
{
unsigned i,tmp;
unsigned CheckSum=0;
DE=1;
/*发送帧起始字节*/
tmp=0x24;
Send(tmp);
Send(DevNo);
CheckSum=CheckSum+DevNo;
Send(type);
CheckSum=CheckSum+type;
Send(len);
CheckSum=CheckSum+len;
/*发送数据*/
for(i=0;i<len;i++)
{
Send(*buf);
CheckSum=CheckSum+*buf;
buf++;
}
Send(CheckSum);
tmp=0x2A;
Send(tmp);
}
/* 清除设备状态信息缓冲区函数*/
void Clr_StatusBuf(void)
{
unsigned char i;
for (i=0;i<STATUSMAXLEN;i++)
StatusBuf[i] = 0;
}
/*主程序*/
void main()
{
unsigned char type; //数据帧类型字节的变量定义
init();
while(1)
{
if(Recv_Data(&type)==0) //接收帧错误或者地址不符合,丢弃
continue;
switch(type)
{
case ACTIVE: //主机询问从机是否在位
Send_Data(READY,0,StatusBuf); //发送READY指令
break;
case GETDATA: //主机读设备请求
Clr_StatusBuf(); //设备状态信息缓冲区初始化
//Get_Stat(); //数据采集函数
Send_Data(SENDDATA,strlen(StatusBuf),StatusBuf);
break;
default:
break; //指令类型错误,丢弃当前帧
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -