微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > 51单片机实现的485通讯程序

51单片机实现的485通讯程序

时间:11-11 来源:互联网 点击:
#ifndef__485_C__
#define__485_C__
#include
#include

#defineunsignedcharuchar
#defineunsignedintuint
/*通信命令*/
#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=1;//开启中断
/*主程序流程*/
while(1)//主循环
{
if(recv_cmd(&type)==0)//发生帧错误或帧地址与本机地址不符,丢弃当前帧后返回
continue;
switch(type)
{
case__ACTIVE_://主机询问从机是否存在
send_data(__OK_,0,dbuf);//发送应答信息,这里buf的内容并未用到
break;
case__GETDATA_:
len=strlen(dbuf);
send_data(__STATUS_,len,dbuf);//发送设备状态信息
break;
default:
break;//命令类型错误,丢弃当前帧后返回
}
}
}
voidREADSTATUS()interrupt0using1//产生外部中断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
{
switch(tmp)
{
case0xdd:
data_buf[i]=0xdb;//0xdbdd表示0xdb
ecc=ecc^0xdb;
db=0;
break;
case0xdc
data_buf[i]=0xc0;//0xdbdc表示0xc0
ecc=ecc^0xc0;
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[0]!=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);
buf++;
}
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;
}
}
#endif

RS-232接口实现计算机和单片机通信程序
作者:
佚名来源:
本站原创点击数:…更新时间:2008年07月10日 

//此程序通过RS-232接口来完成计算机和单片机通信(程序已用p18f458试验板上调试通过)
//程序的调试可以用"

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top