单片机论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2812|回复: 19
收起左侧

关于rs485多机通信系统单片机源程序仿真与通信协议等资料

  [复制链接]
灵现江湖 发表于 2018-1-2 20:27 | 显示全部楼层 |阅读模式
这是rs485通信协议等资料,本人在此共享出来,谢谢

0.png

一、RS485基本知识
RS-485接口芯片已广泛应用于工业控制、仪器、仪表、多媒体网络、机电一体化产品等诸多领域。可用于RS-485接口的芯片种类也越来越多。如何在种类繁多的接口芯片中找到最合适的芯片,是摆在每一个使用者面前的一个问题。RS-485接口在不同的使用场合,对芯片的要求和使用方法也有所不同。使用者在芯片的选型和电路的设计上应考虑哪些因素,由于某些芯片的固有特性,通信中有些故障甚至还需要在软件上作相应调整,如此等等。希望本文对解决RS-485接口的某些常见问题有所帮助。
1 RS-485接口标准
传输方式:差分
传输介质:双绞线
标准节点数:32
最远通信距离:1200m 共模电压最大、最小值:+12V;-7V
差分输入范围:-7V~+12V
接收器输入灵敏度:±200mV
接收器输入阻抗:≥12kΩ
2 节点数及半双工和全双工通信

0.png
0.png
rs485仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)
0.png
单片机源程序如下:
  1.   
  2. /****************************************/
  3. /* Copyright (c) 2017, 通信工程学院     */
  4. /* All rights reserved.                 */
  5. /****************************************/

  6. #include "RS485.h"

  7. //主函数
  8. void main(void)
  9. {
  10.         uchar type;

  11.         Init();//初始化
  12.         
  13.         while (1)
  14.         {
  15.                 if (RecvData(&type)==0)                        // 接收帧错误或者地址不符合,丢弃
  16.                         continue;
  17.                
  18.                 switch (type)
  19.                 {
  20.                         case ACTIVE:                                // 主机询问从机是否在位
  21.                                 SendData(READY,0,StatusBuf);        // 发送READY指令
  22.                                 break;
  23.                         case GETDATA:                                // 主机读设备请求
  24.                                 ClrStatusBuf();
  25.                                 GetStat();                                // 数据采集函数
  26.                                 SendData(SENDDATA,strlen(StatusBuf),StatusBuf);
  27.                                 break;
  28.                         default:
  29.                                 break;                                        // 指令类型错误,丢弃当前帧
  30.                 }
  31.         }
  32. }




  33. //初始化
  34. void Init(void)
  35. {
  36.         P1 = 0xFF;
  37.         DevNo = (P1&0x00111111);                        // 读取本机设备号

  38.         TMOD = 0x20;//定时器T1,工作方式2,自动重装
  39.         SCON = 0x50;//串口通信工作方式1,允许接收
  40.         TH1 = 0xFD;//波特率9600
  41.         TL1 = 0xFD;
  42.         TR1 = 1;
  43.         PCON = 0x00;// SMOD=0,波特率不加倍
  44.         EA = 0;
  45.                                                 
  46. }

  47. //接收数据帧函数,实际上接收的是主机的指令
  48. //*type指令类型
  49. bit RecvData(uchar *type)
  50. {
  51.         uchar tmp,rCount,i;
  52.         uchar r_buf[RECFRMMAXLEN];                        // 保存接收到的帧
  53.         uchar FlagRecvOver;                                // 一帧接收结束标志        
  54.         uchar FlagStartRec;                                // 一帧开始接收标志
  55.         uchar CheckSum;                                                // 校验和
  56.         uchar DataLen;                                                // 数据字节长度变量
  57.                
  58.         //禁止发送,允许接收
  59.         DE = 0;
  60.         RE = 0;

  61.         //接收一帧数据
  62.         rCount = 0;
  63.         FlagStartRec = 0;
  64.   FlagRecvOver = 0;
  65.         
  66.         while (!FlagRecvOver)
  67.         {
  68.                 RI = 0;
  69.                 while (!RI);
  70.                 tmp = SBUF;
  71.                 RI=0;

  72. …………
  73. …………限于本文篇幅 余下代码请从51黑下载附件…………
  74. ,其数值为0x24         
  75.                 if ((!FlagStartRec) && (tmp == 0x24))
  76.                 {
  77.                         FlagStartRec = 1;        
  78.                 }

  79.                 if (FlagStartRec)
  80.                 {
  81.                         r_buf[rCount] = tmp;
  82.                         rCount ++;               
  83.                         
  84.                         //判断是否收到字符'*',其数值为0x2A,根据接收的指令设置相应标志位
  85.                         if (tmp == 0x2A)
  86.                                 FlagRecvOver = 1;
  87.                 }

  88.                 if (rCount == RECFRMMAXLEN)                // 帧超长错误,返回0
  89.                         return 0;
  90.         }
  91.         
  92.         //计算校验和字节
  93.         CheckSum = 0;
  94.         DataLen = r_buf[3];
  95.         
  96.         for (i=0;i<3+DataLen;i++)
  97.         {
  98.                 CheckSum = CheckSum + r_buf[i+1];
  99.         }
  100.         
  101.         //判断帧是否错误
  102.         if (rCount<6)                                                // 帧过短错误,返回0,最短的指令帧为6个字节                                                
  103.                 return 0;
  104.         
  105.         if (r_buf[1]!=DevNo)                                  // 地址不符合,错误,返回0
  106.                 return 0;
  107.         
  108.         if (r_buf[rCount-2]!=CheckSum)                // 校验错误,返回0
  109.             return 0;

  110.         *type = r_buf[2];                                        // 获取指令类型

  111.         return 1;                                                        // 成功,返回1
  112. }


  113. //发送数据帧函数
  114. //type数据类型,len数据长度,*buf数据
  115. void SendData(uchar type,uchar len,uchar *buf)
  116. {
  117.         uchar i,tmp;
  118.         uchar CheckSum = 0;
  119.         
  120.         //允许发送,禁止接收
  121.         DE = 1;
  122.         RE = 1;
  123.         
  124.         //发送帧起始字节
  125.         tmp = 0x24;
  126.         Send(tmp);
  127.         
  128.         Send(DevNo);// 发送地址字节,也即设备号
  129.         CheckSum = CheckSum + DevNo;

  130.         Send(type);                                                        // 发送类型字节
  131.         CheckSum = CheckSum + type;

  132.         Send(len);                                                        // 发送数据长度字节
  133.         CheckSum = CheckSum + len;

  134.         //发送数据
  135.         for (i=0;i<len;i++)                        
  136.         {
  137.                 Send(*buf);
  138.                 CheckSum = CheckSum + *buf;
  139.                 buf++;
  140.         }
  141.         
  142.         Send(CheckSum);// 发送校验和字节

  143.         //发送帧结束字节
  144.         tmp = 0x2A;
  145.         Send(tmp);
  146. }

  147. //采集数据函数经过简化处理,取固定的10个字节数据
  148. void GetStat(void)
  149. {
  150.         StatusBuf[0]=DATA0;
  151.         StatusBuf[1]=DATA1;
  152.         StatusBuf[2]=DATA2;
  153.         StatusBuf[3]=DATA3;
  154.         StatusBuf[4]=DATA4;
  155.         StatusBuf[5]=DATA5;
  156.         StatusBuf[6]=DATA6;
  157. ……………………

  158. …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码

所有资料51hei提供下载:
RS485通信协议及程序.zip (1.41 MB, 下载次数: 203)

评分

参与人数 2黑币 +7 收起 理由
zalkaer + 5 很给力!
切了佛 + 2 共享资料的黑币奖励!

查看全部评分

回复

使用道具 举报

huaishang 发表于 2018-1-5 21:15 | 显示全部楼层
感谢分享,谢谢!
回复

使用道具 举报

xml9527 发表于 2018-1-6 12:24 | 显示全部楼层
485通讯,工控通讯主流
回复

使用道具 举报

simon1777 发表于 2018-6-7 19:11 | 显示全部楼层
这个按键控制要显示的字符吗
回复

使用道具 举报

kidark 发表于 2018-6-26 10:57 | 显示全部楼层
两个从机的程序都是一样的吗
回复

使用道具 举报

kidark 发表于 2018-6-26 18:05 | 显示全部楼层
还有那个通信协议有哪位大佬讲解一下吗。。
回复

使用道具 举报

kidark 发表于 2018-6-26 18:17 | 显示全部楼层
或者数据包格式啊。。
回复

使用道具 举报

xiubing65 发表于 2018-7-4 21:49 | 显示全部楼层
不错,是RTU吗
回复

使用道具 举报

chenxiaojun1234 发表于 2018-7-27 21:09 | 显示全部楼层
感谢分享,谢谢!
回复

使用道具 举报

皂皂奥奥 发表于 2018-11-11 11:47 | 显示全部楼层
感谢分享,谢谢!
回复

使用道具 举报

gemxie 发表于 2018-11-12 15:18 | 显示全部楼层
谢谢分享了。。学习学习
回复

使用道具 举报

Host 发表于 2018-11-20 13:48 | 显示全部楼层
谢谢分享
回复

使用道具 举报

如果能编程回忆 发表于 2018-11-27 11:11 | 显示全部楼层
正好在学习
回复

使用道具 举报

x363731807 发表于 2019-1-11 13:02 | 显示全部楼层
感谢分享
回复

使用道具 举报

该账号已注销 发表于 2019-3-16 10:04 | 显示全部楼层
感谢分享
回复

使用道具 举报

nishuideyu45 发表于 2019-5-12 02:25 | 显示全部楼层
学习了
回复

使用道具 举报

red178 发表于 2019-5-12 11:23 | 显示全部楼层
努力学习中。
回复

使用道具 举报

起个名字下附件 发表于 2019-5-16 13:47 | 显示全部楼层
谢谢分享
回复

使用道具 举报

电气滔滔 发表于 2019-6-7 09:21 | 显示全部楼层
谢谢楼主
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|小黑屋|单片机论坛 |51黑电子论坛单片机 联系QQ:125739409;技术交流QQ群582644647

Powered by 单片机教程网

快速回复 返回顶部 返回列表