485通信程序(51单片机)
#include
#defineucharunsignedchar
#defineuintunsignedint
/*通信命令*/
#define_ACTIVE_0x01//主机询问从机是否存在
#define_GETDATA_0x02//主机发送读设备请求
#define_OK_0x03//从机应答
#define_STATUS_0x04//从机发送设备状态信息
#define_MAXSIZE0x08//缓冲区长度
#define_ERRLEN12//任何通信帧长度超过12则表示出错
uchardbuf[MAXSIZE]; //该缓冲区用于保存设备状态信息
uchardev;//该字节用于保存本机设备号
sbitM_DE=P1^0;//驱动器使能,1有效
sbitM_RE=P1^1;//接收器使能,0有效
voidget_status();//调用该函数获得设备状态信息,函数全码未给出
voidsend_data(uchartype,ucharlen,uchar*buf);//发送数据帧
bitrecv_cmd(uchar*type);//接收主机命令,主机请求包含命令信息。
voidsend_byte(ucharda);//该函数发送一帧数据中的一个字节,由send_data()函数调用
voidmain()
{
uchartype;
ucharlen;
/*系统初始化*/
P1=0xff;//读取本机设备号
dev=(P1>>2);
TMOD=0x20;//定时器T1使用方式2
TH1=250;
TL1=250;
TR1=1;//开始计时
PCON=0x80;//SMOD=1;
SCON=0x50;//工作方式1,波特优选法9600bps,允许接收
ES=0; //关闭串品中断
IT0=0;//外部中断0使有电平触发模式
EX0=1;//开启外部中断0
EA=0;//开启总中断
/*主程序流程*/
while(1)
{
if(recv_cmd(&type)==0)//发送帧错误或帧地址与本机地址不符,丢弃当前帧后返回
continue;
switch(type)
{
case_ACTIVE_://主机询问从机是否存在
send_data(_OK_,0,dbuf);//发送应答信息,这里的buf的内容并未用到
break;
case_GETDATA_://主机发送读设备请求
len=strlen(dbuf);
snd_data(_STATUS_,len,dbuf);//发送设备信息
break;
default:
break;//命令类型错误,丢弃当前帧返回
}
}
}
}
voidREADSTATUS()interrput0using1//产生外部中断0时表示设备状态发生改变,该函数使用寄存器组1
{
get_status();//获得设备状态信息,并将其存入dbuf指向的存储区,数据最后一个字节置0表示数据结束
}
}
/*该函数接收一帧数据度进行检测,无论该帧是否错误,函数均会返回。
*函数参数type保存接收到的命令字
*当接收的数扭帧错误或其地址位不为0时(非主机发送帧),快活数返回0,反之返回1
*/
bitrecv_cmd(uchar*type)
{
bitdb=0;//当接收到的上一个字节为0xdb时,该位置位
bitc0=0;//当接慢到的上一个字节为0xc0时,该位置位
uchardata_buf[_ERRLEN];//保存接收到的帧
uchartmp;
ucharecc=0;
uchari;
M_DE=0;//置发送禁止,接收允许
M_RE=0;
/*接收一帧数据*/
i=0;
while(!c0)//循环直至帧接收完毕
{
RI=0;
while(RI);
tmp=SBUF;
RI=0;
if(db==1)//接收到的上一个字节为0xdb
{
swithc(tmp)
{
case0xdd:
data_buf[i]=0xdb;//0xdbdd表示0xdb
ecc=ecc^0xdb;
db=0;
break;
case0xdc:
data_buf[i]=0xc0;//0xdbdc表示0xc0
ecc=0;
db=0;
break;
default:
return0;//帧错误,返回
}
i++;
}
switch(tmp)//正常情况下
{
case0xc0://帧结束
c0=1;
break;
case0xdb: //检测到转义字符
db=1;
break;
default://普通数据
data_buf[i]=tmp;//保存数据
ecc=ecc^tmp;//计算校验字节
i++;
}
if(i==_ERRLEN)//帧超长,错误,返回
return0;
}
/*判断帧是否错误*/
if(i<4)//帧过短,错误,返回
return0;
if(ecc!=0)//校验错误,返回
return0;
if(data_buf[i!=dev) //非访问本机命令,错误,返回
return0;
*type=data_buf[1];//获得命令字
return1;//函数成功返回
}
/*该函数发送一数据帧,参数type为命令字,len为数据长度,buf为要发送的数据内容*/
voidsend_data(uchartype,ucharlen,uchar*buf)
{
uchari;
ucharecc=0;
M_DE=1;//置发送允许,接收禁止
M_RE=1;
send_byte(dev);//发送本机地址
ecc=dev;
send_byte(type);//发送命令字
ecc=ecc^type;
send_byte(len);//发送长度
ecc=ecc^len;
for(i=0;i { send_byte(*buf); ecc=ecc^(*buf); buff++; } send_byte(ecc);//发送校验字节 TI=0;//发送帧结束标志 SBUF=0xc0; while(!TI); TI=0; } /*该函数发送一个数据字节,若该字节为0xdb,则发送0xdbdd,若该字节为0xc0,则发送0xdbdc*/ voidsend_byte(ucharda) { switch(da) { case0xdb://字节为0xdb,发送0xdbdd TI=0; SBUF=0xdb; while(!TI); TI=0; SBUF=0xdd; while(!TI); TI=0; break; case0xc0://字节为0xc0,则发送0xdbdc TI=0; SBUF=0xdb; while(!TI); TI=0; SBUF=0xdc; while(!TI); TI=0; break; default://普通数据刚直接发送 TI=0; SBUF=da; while(!TI); TI=0; } }
485通信程序51单片 相关文章:
- Windows CE 进程、线程和内存管理(11-09)
- RedHatLinux新手入门教程(5)(11-12)
- uClinux介绍(11-09)
- openwebmailV1.60安装教学(11-12)
- Linux嵌入式系统开发平台选型探讨(11-09)
- Windows CE 进程、线程和内存管理(二)(11-09)