rs485通信程序

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

#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) // 帧超长,错误,返回

相关文档
最新文档