1、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 1
2、2 / 任何通信帧长度超过 12 则表示出错uchar dbuf_MAXSIZE; / 该缓冲区用于保存设备状态信息uchar dev; / 该字节用于保存本机设备号sbit M_DE = P10; / 驱动器使能,1 有效sbit M_RE = P11; / 接收器使能,0 有效void get_status(); / 调用该函数获得设备状态信息,函数代码未给出void send_data(uchar type, uchar len, uchar *buf); / 发送数据帧bit recv_cmd(uchar *type); / 接收主机命令,主机请求仅包含命令信息void send_by
3、te(uchar da); / 该函数发送一帧数据中的一个字节,由 send_data()函数调用void main()uchar type;uchar len;/* 系统初始化 */P1 = 0xff; / 读取本机设备号dev = (P12);TMOD = 0x20; / 定时器 T1 使用工作方式 2TH1 = 250; / 设置初值TL1 = 250;TR1 = 1; / 开始计时PCON = 0x80; / SMOD = 1SCON = 0x50; / 工作方式 1,波特率 9600bps,允许接收ES = 0; / 关闭串口中断IT0 = 0; / 外部中断 0 使用电平触发模式E
4、X0 = 1; / 开启外部中断 0EA = 1; / 开启中断/* 主程序流程 */while(1) / 主循环if(recv_cmd(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() inter
5、rupt 0 using 1 / 产生外部中断 0 时表示设备状态发生改变,该函数使用寄存器组 1get_status(); / 获得设备状态信息,并将其存入 dbuf 指向的存储区,数据最后一字节置 0表示数据结束/* 该函数接收一帧数据并进行检测,无论该帧是否错误,函数均会返回* 函数参数 type 保存接收到的命令字* 当接收到数据帧错误或其地址位不为 0 时(非主机发送帧),函数返回 0,反之返回 1*/bit recv_cmd(uchar *type)bit db = 0; / 当接收到的上一个字节为 0xdb 时,该位置位bit c0 = 0; / 当接收到的上一个字节为 0xc0
6、 时,该位置位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) / 接收到的上一个字节为 0xdbswitch(tmp)case 0xdd:data_bufi = 0xdb; / 0xdbdd 表示 0xdbecc = ecc0xdb;db = 0;break;case 0xdcdat
7、a_bufi = 0xc0; / 0xdbdc 表示 0xc0ecc = ecc0xc0;db = 0;break;defaultreturn 0; / 帧错误,返回i+;switch(tmp) / 正常情况case 0xc0: / 帧结束c0 = 1;break;case 0xdb: / 检测到转义字符db = 1;break;default: / 普通数据data_bufi = tmp; / 保存数据ecc = ecctmp; / 计算校验字节i+;if(i = _ERRLEN) / 帧超长,错误,返回return 0;/* 判断帧是否错误 */if(i4) / 帧过短,错误,返回retu
8、rn 0;if(ecc != 0) / 校验错误,返回return 0;if(data_buf0 != 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_b
9、yte(dev); / 发送本机地址ecc = dev;send_byte(type); / 发送命令字ecc = ecctype;send_byte(len); / 发送长度ecc = ecclen;for(i=0; ilen; i+) / 发送数据send_byte(*buf);ecc = ecc(*buf);buf+;send_byte(ecc); / 发送校验字节TI = 0; / 发送帧结束标志SBUF = 0xc0;while(!TI);TI = 0;/* 该函数发送一个数据字节,若该字节为 0xdb,则发送 0xdbdd,若该字节为 0xc0 则,发送 0xdbdc */void
10、 send_byte(uchar da)switch(da)case 0xdb: / 字节为 0xdb,发送 0xdbddTI = 0;SBUF = 0xdb;while(!TI);TI = 0;SBUF = 0xdd;while(!TI)TI = 0;break;case 0xc0: / 字节为 0xc0,发送 0xdbdcTI = 0;SBUF = 0xdb;while(!TI);TI = 0;SBUF = 0xdc;while(!TI)TI = 0;break;default: / 普通数据则直接发送TI = 0;SBUF = da;while(!TI);TI = 0;#endifRS-232 接口实现计算机和单片机通信程序作者:佚名 来源: 本站原创 点击数: 更新时间:2008 年 07 月10 日 【字体:大 中 小】
Copyright © 2018-2021 Wenke99.com All rights reserved
工信部备案号:浙ICP备20026746号-2
公安局备案号:浙公网安备33038302330469号
本站为C2C交文档易平台,即用户上传的文档直接卖给下载用户,本站只是网络服务中间平台,所有原创文档下载所得归上传人所有,若您发现上传作品侵犯了您的权利,请立刻联系网站客服并提供证据,平台将在3个工作日内予以改正。