完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
#ifndef __485_C__
#define __485_C__ #include #include #define uchar unsigned char #define uint unsigned int /* 通信命令 */ #define __ACtiVE_ 0x01 // 主机询问从机是否存在 #define __GETDATA_ 0x02 // 主机发送读设备请求 #define __OK_ 0x03 // 从机应答 #define __STATUS_ 0x04 // 从机发送设备状态信息 #define __MAXSIZE 0x08 // 缓冲区长度 #define __ERRLEN 12 // 任何通信帧长度超过12则表示出错 uchar dbuf[55]; // 该缓冲区用于保存设备状态信息 uchar dev; // 该字节用于保存本机设备号 //***it M_DE = P1^0; // 驱动器使能,1有效 //***it M_RE = P1^1; // 接收器使能,0有效 ***it re=P3^5; 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;/* 系统初始化 */ P3 = 0xff; // 读取本机设备号 dev = (P3>>2); TMOD = 0x20; // 定时器T1使用工作方式2 TH1 = 244; // 设置初值 X=256-f*(SMOD+1)/(384*波特率) TL1 = 244; TR1 = 1; // 开始计时 PCON = 0x00; // SMOD = 0 SCON = 0x50; // 工作方式1,波特率2400bps,允许接收 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时表示设备状态发生改变, { 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;/* 接收一帧数据 */ 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; re=1; send_byte(dev); // 发送本机地址 ecc = dev; send_byte(type); // 发送命令字 ecc = ecc^type; send_byte(len); // 发送长度 ecc = ecc^len; for(i=0; i ecc = ecc^(*buf); buf++; } send_byte(ecc); // 发送校验字节 TI = 0; // 发送帧结束标志 SBUF = 0xc0; while(!TI); TI = 0; } /* 该函数发送一个数据字节,若该字节为0xdb,则发送0xdbdd,若该字节为0xc0则,发送0xdbdc */ void send_byte(uchar da) {switch(da) { case 0xdb: // 字节为0xdb,发送0xdbdd TI = 0; SBUF = 0xdb; while(!TI); TI = 0; SBUF = 0xdd; while(!TI) TI = 0; break; case 0xc0: // 字节为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 |
|
相关推荐
|
|
你正在撰写讨论
如果你是对讨论或其他讨论精选点评或询问,请使用“评论”功能。
【xG24 Matter开发套件试用体验】Silicon Labs 基于 EFR32MG24 Explorer Kit 开发板 开箱试用体验
582 浏览 0 评论
嵌入式设备在远端运行,会有偶发性代码跑飞的情况,无法到现场调试的情况下如何检查出问题?
1487 浏览 3 评论
写一个程序控制像图上这样控制电磁阀 但是没什么头绪 请各位大神帮帮忙
1478 浏览 1 评论
793 浏览 0 评论
【xG24 Matter开发套件试用体验】开箱+开发板资料说明+开发环境搭建
1266 浏览 0 评论
【youyeetoo X1 windows 开发板体验】少儿AI智能STEAM积木平台
10427 浏览 31 评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-8-1 05:20 , Processed in 0.617511 second(s), Total 50, Slave 39 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191