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

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

举报
开通vip

51单片机实现的485通讯程序 51单片机实现的485通讯程序 #ifndef __485_C__ #define __485_C__ #include #include #define unsigned char uchar #define unsigned int uint /* 通信命令 */ #define __ACTIVE_ 0x01    // 主机询问从机是否存在 #define __GETDATA_ 0x02    // 主机发送读设备请求 #define __OK_ 0x03    // 从机应答 #define...

51单片机实现的485通讯程序
51单片机实现的485通讯程序 #ifndef __485_C__ #define __485_C__ #include #include #define unsigned char uchar #define unsigned int uint /* 通信命令 */ #define __ACTIVE_ 0x01    // 主机询问从机是否存在 #define __GETDATA_ 0x02    // 主机发送读设备请求 #define __OK_ 0x03    // 从机应答 #define __STATUS_ 0x04    // 从机发送设备状态信息 #define __MAXSIZE 0x08    // 缓冲区长度 #define __ERRLEN 12    // 任何通信帧长度超过12则表示出错 uchar dbuf[__MAXSIZE];    // 该缓冲区用于保存设备状态信息 uchar dev;    // 该字节用于保存本机设备号 sbit M_DE = P1^0;    // 驱动器使能,1有效 sbit M_RE = P1^1;    // 接收器使能,0有效 void get_status();    // 调用该函数获得设备状态信息,函数代码未给出 void send_data(uchar type, uchar len, uchar *buf);    // 发送数据帧 bit recv_cmd(uchar *type);    // 接收主机命令,主机请求仅包含命令信息 void send_byte(uchar da);    // 该函数发送一帧数据中的一个字节,由send_data()函数调用 void main() { uchar type; uchar len; /* 系统初始化 */ 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;    // 命令类型错误,丢弃当前帧后返回    } } } void READSTATUS() interrupt 0 using 1    // 产生外部中断0时表示设备状态发生改变,该函数使用寄存器组1 { get_status();    // 获得设备状态信息,并将其存入dbuf指向的存储区,数据最后一字节置0表示数据结束 } /* 该函数接收一帧数据并进行检测,无论该帧是否错误,函数均会返回 * 函数参数type保存接收到的命令字 * 当接收到数据帧错误或其地址位不为0时(非主机发送帧),函数返回0,反之返回1 */ bit recv_cmd(uchar *type) { bit db = 0;    // 当接收到的上一个字节为0xdb时,该位置位 bit c0 = 0;    // 当接收到的上一个字节为0xc0时,该位置位 uchar data_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)    // 接收到的上一个字节为0xdb    {     switch(tmp)     {      case 0xdd:       data_buf[i] = 0xdb;    // 0xdbdd表示0xdb       ecc = ecc^0xdb;       db = 0;       break;      case 0xdc       data_buf[i] = 0xc0;    // 0xdbdc表示0xc0       ecc = ecc^0xc0;       db = 0;       break;      default       return 0;    // 帧错误,返回     }     i++;    }    switch(tmp)    // 正常情况    {     case 0xc0:    // 帧结束      c0 = 1;      break;     case 0xdb:    // 检测到转义字符      db = 1;      break;     default:    // 普通数据      data_buf[i] = tmp;    // 保存数据      ecc = ecc^tmp;    // 计算校验字节      i++;    }    if(i == __ERRLEN)    // 帧超长,错误,返回     return 0; } /* 判断帧是否错误 */ if(i<4)    // 帧过短,错误,返回    return 0; if(ecc != 0)    // 校验错误,返回    return 0; if(data_buf[0] != dev)    // 非访问本机命令,错误,返回    return 0; *type = data_buf[1];    // 获得命令字 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 = ecc^type; send_byte(len);    // 发送长度 ecc = ecc^len; for(i=0; i 例:用8051单片机串行口外接CD4094扩展8位并行输出口,如图所示,8位并行口的各位都接一个发光二极管,要求发光管呈流水灯状态。 串行口方式0的数据传送可采用中断方式,也可采用查询方式,无论哪种方式,都要借助于TI或RI标志。串行发送时,能靠TI置位(发完一帧数据后)引起中断申请,在中断服务程序中发送下一帧数据,或者通过查询TI的状态,只要TI为0就继续查询,TI为1就结束查询,发送下一帧数据。在串行接收时,则由RI引起中断或对RI查询来确定何时接收下一帧数据。无论采用什么方式,在开始通信之前,都要先对控制寄存器SCON进行初始化。在方式0中将,将00H送SCON就能了。 -----------------单片机串行口通信程序设计列子-------------------------- ORG 2000H START: MOV SCON,#00H ;置串行口工作方式0 MOV A,#80H ;最高位灯先亮 CLR P1.0 ;关闭并行输出(避象传输过程中,各LED的"暗红"现象) OUT0: MOV SBUF,A ;开始串行输出 OUT1: JNB TI,OUT1 ;输出完否 CLR TI ;完了,清TI标志,以备下次发送 SETB P1.0 ;打开并行口输出 ACALL DELAY ;延时一段时间 RR A ;循环右移 内容来自单片机之家www.dpj100.com CLR P1.0 ;关闭并行输出 JMP OUT0 ;循环 说明:DELAY延时子程序能用前面我们讲P1口流水灯时用的延时子程序,这里就不给出了
本文档为【51单片机实现的485通讯程序】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
该文档来自用户分享,如有侵权行为请发邮件ishare@vip.sina.com联系网站客服,我们会及时删除。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。
本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。
网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。
下载需要: 免费 已有0 人下载
最新资料
资料动态
专题动态
is_313817
暂无简介~
格式:doc
大小:133KB
软件:Word
页数:22
分类:互联网
上传时间:2012-10-22
浏览量:79