485通信程序(51单片机).pdf
#include#include#define uchar unsigned char#define uintunsigned int/*通信命令*/#define _ACTIVE_ 0 x01/主机询问从机是否存在#define _GETDATA_ 0 x02/主机发送读设备请求#define _OK_0 x03/从机应答#define _STATUS_ 0 x04/从机发送设备状态信息#define _MAXSIZE0 x08/缓冲区长度#define _ERRLEN12/任何通信帧长度超过 12 则表示出错uchar dbufMAXSIZE;/该缓冲区用于保存设备状态信息uchar dev;/该字节用于保存本机设备号sbit M_DE=P10;/驱动器使能,1 有效sbit M_RE=P11;/接收器使能,0 有效void get_status();/调用该函数获得设备状态信息,函数全码未给出void send_data(uchar type,uchar len,uchar*buf);/发送数据帧bitrecv_cmd(uchar*type);/接收主机命令,主机请求包含命令信息。void send_byte(uchar da);/该函数发送一帧数据中的一个字节,由send_data()函数调用void main()uchar type;uchar len;/*系统初始化*/P1=0 xff;/读取本机设备号dev=(P12);TMOD=0 x20;/定时器 T1 使用方式 2TH1=250;TL1=250;TR1=1;/开始计时PCON=0 x80;/SMOD=1;SCON=0 x50;/工作方式 1,波特优选法 9600bps,允许接收ES=0;/关闭串品中断IT0=0;/外部中断 0 使有电平触发模式EX0=1;/开启外部中断 0EA=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;/命令类型错误,丢弃当前帧返回void READSTATUS()interrput 0 using 1/产生外部中断 0 时表示设备状态发生改变,该函数使用寄存器组 1get_status();/获得设备状态信息,并将其存入 dbuf 指向的存储区,数据最后一个字节置 0 表示数据结束/*该函数接收一帧数据度进行检测,无论该帧是否错误,函数均会返回。*函数参数 type 保存接收到的命令字*当接收的数扭帧错误或其地址位不为0 时(非主机发送帧),快活数返回 0,反之返回 1*/bit recv_cmd(uchar*type)bit db=0;/当接收到的上一个字节为0 xdb 时,该位置位bit c0=0;/当接慢到的上一个字节为0 xc0 时,该位置位uchardata_buf_ERRLEN;/保存接收到的帧uchar tmp;uchar ecc=0;uchar i;M_DE=0;/置发送禁止,接收允许M_RE=0;/*接收一帧数据*/i=0;while(!c0)/循环直至帧接收完毕RI=0;while(RI);tmp=SBUF;RI=0;if(db=1)/接收到的上一个字节为0 xdbswithc(tmp)case 0 xdd:data_bufi=0 xdb;/0 xdbdd 表示 0 xdbecc=ecc0 xdb;db=0;break;case 0 xdc:data_bufi=0 xc0;/0 xdbdc 表示 0 xc0ecc=0;db=0;break;default:return 0;/帧错误,返回i+;switch(tmp)/正常 情况下case 0 xc0:/帧结束c0=1;break;case 0 xdb:/检测到转义字符db=1;break;default:/普通数据data_bufi=tmp;/保存数据ecc=ecctmp;/计算校验字节i+;if(i=_ERRLEN)/帧超长,错误,返回return 0;/*判断帧是否错误*/if(i4)/帧过短,错误,返回return 0;if(ecc!=0)/校验错误,返回return 0;if(data_bufi!=dev)/非访问本机命令,错误,返回return 0;*type=data_buf1;/获得命令字return 1;/函数成功返回/*该函数发送一数据帧,参数 type 为命令字,len 为数据长度,buf 为要发送的数据内容*/void send_data(uchar type,uchar len,uchar*buf)uchar i;uchar ecc=0;M_DE=1;/置发送允许,接收禁止M_RE=1;send_byte(dev);/发送本机地址ecc=dev;send_byte(type);/发送命令字ecc=ecctype;send_byte(len);/发送长度ecc=ecclen;for(i=0;ilen;i+)send_byte(*buf);ecc=ecc(*buf);buff+;send_byte(ecc);/发送校验字节TI=0;/发送帧结束标志SBUF=0 xc0;while(!TI);TI=0;/*该函数发送一个数据字节,若该字节为0 xdb,则发送 0 xdbdd,若该字节为 0 xc0,则发送0 xdbdc*/void send_byte(uchar da)switch(da)case 0 xdb:/字节为 0 xdb,发送 0 xdbddTI=0;SBUF=0 xdb;while(!TI);TI=0;SBUF=0 xdd;while(!TI);TI=0;break;case 0 xc0:/字节为 0 xc0,则发送 0 xdbdcTI=0;SBUF=0 xdb;while(!TI);TI=0;SBUF=0 xdc;while(!TI);TI=0;break;default:/普通数据刚直接发送TI=0;SBUF=da;while(!TI);TI=0;