找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 10029|回复: 15
打印 上一主题 下一主题
收起左侧

rs485 16路继电器控制板 仿modbus通信协议控制有上下位机程序

  [复制链接]
跳转到指定楼层
楼主

Modbus十六路继电器输出控制板

一、应用场合

  • 工业控制需要扩展输出口的场合
  • PLC输出接口扩展
  • 组态触摸屏控制
  • 简要说明
  • 尺寸:152mmX163mmX25mm
  • 通讯协议:MODBUS_RTU模式
  • 工作电压:直流12(另有24V)
  • 掉电后保存继电器状态
  • 有看门狗复位功能
特点
  • RS485标准接口
  • 16路输出光隔离控制继电器
  • 标准11.0592M晶振9600波特率、八位数据位、一位停止位、一位校验位(偶校验)
  • 上电复位和手动复位。
  • MODBUS_RTU标准协议控制
  • 输出16继电器LED指示。
  • 通过软件指令设定地址等参数
  • 可控制交流220V/10A下设备
  • 有程序下载口,可随意更改程序。
  • 可按客户要求定制协议

注:顾客可以根据需要选择相应的产品,我们公司有两路开关量2路输入输出、4路开关量输入输出、8路开关量输入输出、8路模拟量输入4路开关量输出、15路开关量输入输出、30路输入输出等继电器控制板,有需要请联系我们,选择您满意的产品!

四、工作环境

  • 工作环境温度:-20℃~65℃
  • 相对湿度:95%(无凝结)

五、引脚描述

名称

描述

名称

描述

VCC

12V电源正极

OUT7

第七路继电器公共端和常开端

GND

电源负极

OUT8

第八路继电器公共端和常开端

A+

RS485数据A+

OUT9

第九路继电器公共端和常开端

B-

RS485数据B-

OUT10

第十路继电器公共端和常开端

OUT1

第一路继电器公共端和常开端

OUT11

第十一路继电器公共端和常开端

OUT2

第二路继电器公共端和常开端

OUT12

第十二路继电器公共端和常开端

OUT3

第三路继电器公共端和常开端

OUT13

第十三路继电器公共端和常开端

OUT4

第四路继电器公共端和常开端

OUT14

第十四路继电器公共端和常开端

OUT5

第五路继电器公共端和常开端

OUT15

第十五路继电器公共端和常开端

OUT6

第六路继电器公共端和常开端

OUT16

第十六路继电器公共端和常开端

五、硬件连接

  • 电源的连接

  • RS485的连接

注:RS485建议采用双绞线连接,采用带屏蔽的双绞线连接,并将屏蔽层接地,总线上挂多个模块时,采用手拉手不的连接方式

  • 继电器输出的连接

六、软件协议

6.1串口通信定义

  • 串口波特率:1位起始位、8位数据位 、1位停止位 、偶校验
  • 默认地址:0x01
  • 通讯接口:RS485

6.1指令功能表

功能

从机地址

0x01~0xff

命令

寄存器地址

高字节、低字节

数据域

CRC校验

高低字节

长度

1个字节

1个字节

2个字节

2个字节

读取继电器状态

Addr

0x02

0x0001

高字节:0x00

低字节:0x0f(16个继电器状态)

CRCH

CRCL

控制多路继电器

Addr

0x0F

0x0000~0x000f

继电器个数

高:0x00

低:0x01~0x0f

字节个数

(1个字节)

0x01~0x02

数据域

对应位为1:开

对应位为0:关

CRCH

CRCL

控制单个继电器

Addr

0x05

0x0000~0x000f

高:0xff  低:0x00 吸合

高:0x00 低:0x00 断开

CRCH

CRCL

设定模块地址

Addr

0x06

0x0010

要修改的地址两个字节

CRCH

CRCL

6.2指令示例及详解

  • 读取16路继电器状态(地址0x01

地址

功能

继电器起始地址

读取个数

CRC校验

0x01

0x02

高:0x00

低:0x01

高:0x00

低:0x0F

0x69

0xCE

从机回应

地址

功能

字节数

返回继电器状态

CRC校验

0x01

0x02

0x02

高:0x00

低:0x00

0xB9

0xB8

注:返回的十六路状态0为断开,1为吸合

  • 控制多路继电器

a.控制所有继电器全开主机发送:

地址

功能

继电器起始地址

控制继电器个数

字节个数

数据域

CRC校验

0x01

0x0F

高:0x00

低:0x00

高:0x00

低:0x0F

0x02

0xff 0xff

0xE4

0x44

从机回应:

地址

功能

继电器起始地址

控制继电器个数

CRC校验

0x01

0x0F

高:0x00

低:0x00

高:0x00

低:0x0F

0x15

0xCF

注:控制多路时数据域中二进制数对应位为1是打开某一路继电器,为0关闭某一路继电器

b控制所有继电器全关主机发送:

地址

功能

继电器起始地址

控制继电器个数

字节个数

数据域

CRC校验

0x01

0x0F

高:0x00

低:0x00

高:0x00

低:0x0F

0x02

0x00 x00

0xE5

0xF4

从机回应:

地址

功能

继电器起始地址

控制继电器个数

CRC校验

0x01

0x0F

高:0x00

低:0x00

高:0x00

低:0x0F

0x15

0xCF

注:控制多路时数据域中二进制数对应位为1是打开某一路继电器,为0关闭某一路继电器

  • 控制单个继电器状态

控制第一路继电器开主机发送:

地址

功能

继电器地址

打开继电器

CRC校验

0x01

0x05

高:0x00

低:0x00

高:0xFF

低:0x00

0x8C

0x3A

从机回应:

地址

功能

继电器地址

打开继电器

CRC校验

0x01

0x05

高:0x00

低:0x00

高:0xFF

低:0x00

0x8C

0x3A


控制第一路继电器关主机发送:

地址

功能

继电器地址

打开继电器

CRC校验

0x01

0x05

高:0x00

低:0x00

高:0x00

低:0x00

0xCD

0xCA

从机回应:

地址

功能

继电器地址

打开继电器

CRC校验

0x01

0x05

高:0x00

低:0x00

高:0x00

低:0x00

0xCD

0xCA

6.3上位机测试软件

上位机简介

  • 上位机编译环境:vs2008.net
  • 使用语言是vb.net
  • 使用该软件需要安装framwork3.5软件(一般win7系统都已安装)
  • 打开该软件前请先把数据线和控制板连接好,控制板供电

上位机软件可控制七个十六路继电器输出控制板,如要需要控制更多从机设备,需要更改上位机软件,

产品展示

附录:


单片机源程序如下:
  1. /********************************************************************
  2.                             汇诚科技
  3. 实现功能:串口控制继电器程序
  4. 使用芯片:AT89S52
  5. 晶振:11.0592MHZ
  6. 波特率:9600
  7. 编译环境:Keil
  8. 【声明】此程序仅用于学习与参考,引用请注明版权和作者信息!
  9. *********************************************************************/
  10. #include<reg52.h>                 //库文件
  11. #include <intrins.H>
  12. #include<EEPROM.h>
  13. #define uchar unsigned char//宏定义无符号字符型
  14. sbit K1=P2^0;
  15. sbit K2=P2^1;
  16. sbit K3=P2^2;
  17. sbit K4=P2^3;
  18. sbit K5=P2^4;
  19. sbit K6=P2^5;
  20. sbit K7=P2^6;
  21. sbit K8=P2^7;
  22. sbit K9=P1^0;
  23. sbit K10=P1^1;
  24. sbit K11=P1^2;
  25. sbit K12=P1^3;
  26. sbit K13=P1^4;
  27. sbit K14=P1^5;
  28. sbit K15=P1^6;
  29. sbit K16=P1^7;

  30. sbit RS485_DIR=P3^7;
  31. uchar dat;
  32. uchar t,r,ii;
  33. uchar add;    //掉电保持485的地址
  34. uchar j=0;
  35. bit flag_zx=0;
  36. uchar sendBuf[10];          //发送缓冲区
  37. uchar receBuf[10];    //接收缓冲区
  38. bit busy;
  39. bit bz1=0;
  40. bit bz2=0;
  41. bit bz3=0;
  42. bit bz4=0;
  43. bit bz5=0;
  44. bit bz6=0;
  45. bit bz7=0;
  46. bit bz8=0;
  47. /********************************************************************
  48.                             延时函数
  49. *********************************************************************/
  50. void delay(uchar t)
  51. {
  52.   uchar i,j;
  53.    for(i=0;i<t;i++)
  54.    {
  55.             for(j=13;j>0;j--);
  56.          { ;
  57.          }
  58.    }
  59. }

  60. /********************************************************************
  61.               功能:串口初始化,波特率9600,方式1
  62. *********************************************************************/
  63. void Init_Com(void)
  64. {
  65. TMOD = 0x20;
  66. PCON = 0x00;
  67. SCON = 0x50;
  68. TH1 = 0xFd;
  69. TL1 = 0xFd;
  70. TR1 = 1;
  71. ES=1;
  72. EA=1;
  73. }

  74. /****************发送函数*********************/
  75. void senduart2()
  76. {          
  77. RS485_DIR=1;
  78. SBUF=sendBuf[0];while(!TI);TI=0;
  79. SBUF=sendBuf[1];while(!TI);TI=0;
  80. SBUF=sendBuf[2];while(!TI);TI=0;
  81. SBUF=sendBuf[3];while(!TI);TI=0;
  82. SBUF=sendBuf[4];while(!TI);TI=0;
  83. RS485_DIR=0;
  84. }
  85. /*****************清空发送缓冲区*************************/
  86. void clear_receBuf()
  87. {
  88.     uchar i;
  89.         for(i=0;i<5;i++)
  90.         {
  91.             receBuf[i]=0;
  92.         }
  93. }
  94. /********************************************************************
  95.                             主函数
  96. *********************************************************************/
  97. void main()
  98. {
  99. Init_Com();//串口初始化
  100. add = EEPROMReadByte(0);
  101. //add = 0X00;
  102.     P2=0XFF;
  103.         P1=0XFF;
  104.         RS485_DIR=0;
  105. while(1)
  106. {

  107. /********************************************************************
  108.                             接收数据判断函数
  109. *********************************************************************/
  110. if(RI)  //如果有接收
  111.            {
  112.              RI=0; //接收标志清零
  113.              receBuf[r++&0x0F]=SBUF;     //把接受的数据存储到BUT数组中
  114.                  if(receBuf[0]!=0xaa){r=0;}
  115.                  if(r>=5)
  116.                  {        r=0;

  117.                     flag_zx=1;
  118.                  }
  119.            }
  120.            if(flag_zx==1)
  121.            {                     

  122.                 flag_zx=0;
  123.                     //0         1       2       3        4               
  124.                         //起始位   地址位  功能位   数据位  结束位
  125.                         if((receBuf[0]==0xaa)&&(receBuf[4]==0xbb)&&(receBuf[1]==add))          //如果开始位和结束位,还有地址都正确,进行下一步判断
  126.                         {
  127.                            if(receBuf[2]==0x01)  //修改板子地址
  128.                            {
  129.                                 add=receBuf[3];
  130.                                         EEPROMSectorErase(0);//擦除扇区
  131.                                 EEPROMWriteByte(0,add);//写入新的地址
  132.                            }
  133.                            else if(receBuf[2]==0x02)  //打开单路继电器
  134.                            {
  135.                                        switch(receBuf[3])
  136.                                         {
  137.                                             case 0x01: K1=0; break;
  138.                                                 case 0x02: K2=0; break;
  139.                                             case 0x03: K3=0; break;
  140.                                                 case 0x04: K4=0; break;
  141.                                             case 0x05: K5=0; break;
  142.                                                 case 0x06: K6=0; break;
  143.                                             case 0x07: K7=0; break;
  144.                                                 case 0x08: K8=0; break;
  145.                                                 case 0x09: K9=0; break;
  146.                                                 case 0x0A: K10=0; break;
  147.                                             case 0x0B: K11=0; break;
  148.                                                 case 0x0C: K12=0; break;
  149.                                             case 0x0D: K13=0; break;
  150.                                                 case 0x0E: K14=0; break;
  151.                                             case 0x0F: K15=0; break;
  152.                                                 case 0x10: K16=0; break;
  153.                                                 default:break;
  154.                                         }
  155.                            }
  156.                            else if(receBuf[2]==0x03)  //关闭单路继电器
  157.                            {
  158.                                        switch(receBuf[3])
  159.                                         {
  160.                                             case 0x01: K1=1; break;
  161.                                                 case 0x02: K2=1; break;
  162.                                             case 0x03: K3=1; break;
  163.                                                 case 0x04: K4=1; break;
  164.                                             case 0x05: K5=1; break;
  165.                                                 case 0x06: K6=1; break;
  166.                                             case 0x07: K7=1; break;
  167.                                                 case 0x08: K8=1; break;
  168.                                               case 0x09: K9=1; break;
  169.                                                 case 0x0A: K10=1; break;
  170.                                             case 0x0B: K11=1; break;
  171.                                                 case 0x0C: K12=1; break;
  172.                                             case 0x0D: K13=1; break;
  173.                                                 case 0x0E: K14=1; break;
  174.                                             case 0x0F: K15=1; break;
  175.                                                 case 0x10: K16=1; break;
  176.                                                 default:break;
  177.                                         }                       
  178.                            }
  179.                            else if(receBuf[2]==0x04)  //打开全部继电器
  180.                            {
  181.                                 if(receBuf[3]==0xff)
  182.                                 {
  183.                                             P2=0X00;
  184.                                             P1=0X00;
  185.                                         }  
  186.                            }
  187.                            else if(receBuf[2]==0x05)  //关闭全部继电器
  188.                            {
  189.                                 if(receBuf[3]==0x00)
  190.                                 {
  191.                                             P2=0XFF;
  192.                                                 P1=0XFF;
  193.                                         }                       
  194.                            }
  195.                            else if(receBuf[2]==0x06)  //查询继电器
  196.                            {
  197.                                         sendBuf[0]=0xaa;
  198.                                         sendBuf[1]=add;
  199.                                         sendBuf[2]=0x07;
  200.                                         //sendBuf[3]=0xfe;
  201.                                         sendBuf[4]=0xbb;       
  202.                                switch(receBuf[3])
  203.                                    {
  204.                                        case 0x01: if(K1==0) sendBuf[3]=0xFF;else sendBuf[3]=0x00;break;
  205.                                            case 0x02: if(K2==0) sendBuf[3]=0xFF;else sendBuf[3]=0x00;break;
  206.                                        case 0x03: if(K3==0) sendBuf[3]=0xFF;else sendBuf[3]=0x00;break;
  207.                                            case 0x04: if(K4==0) sendBuf[3]=0xFF;else sendBuf[3]=0x00;break;
  208.                                        case 0x05: if(K5==0) sendBuf[3]=0xFF;else sendBuf[3]=0x00;break;
  209.                                            case 0x06: if(K6==0) sendBuf[3]=0xFF;else sendBuf[3]=0x00;break;
  210.                                        case 0x07: if(K7==0) sendBuf[3]=0xFF;else sendBuf[3]=0x00;break;
  211.                                            case 0x08: if(K8==0) sendBuf[3]=0xFF;else sendBuf[3]=0x00;break;
  212.                                        case 0x09: if(K9==0) sendBuf[3]=0xFF;else sendBuf[3]=0x00;break;
  213.                                            case 0x0A: if(K10==0) sendBuf[3]=0xFF;else sendBuf[3]=0x00;break;
  214.                                        case 0x0B: if(K11==0) sendBuf[3]=0xFF;else sendBuf[3]=0x00;break;
  215.                                            case 0x0C: if(K12==0) sendBuf[3]=0xFF;else sendBuf[3]=0x00;break;
  216.                                        case 0x0D: if(K13==0) sendBuf[3]=0xFF;else sendBuf[3]=0x00;break;
  217.                                            case 0x0E: if(K14==0) sendBuf[3]=0xFF;else sendBuf[3]=0x00;break;
  218.                                        case 0x0F: if(K15==0) sendBuf[3]=0xFF;else sendBuf[3]=0x00;break;
  219.                                            case 0x10: if(K16==0) sendBuf[3]=0xFF;else sendBuf[3]=0x00;break;
  220.                                            default:break;
  221.                                    }  
  222.                                    senduart2();
  223.                            }
  224.                            else if(receBuf[2]==0x08)  //查询输入
  225.                            {
  226.                                         sendBuf[0]=0xaa;
  227.                                         sendBuf[1]=add;
  228.                                         sendBuf[2]=0x09;
  229.                                         //sendBuf[3]=0xfe;
  230.                                         sendBuf[4]=0xbb;
  231.                                
  232.                                switch(receBuf[3])
  233.                                    {
  234.                                        case 0x01: sendBuf[3]=0xFF;break;

  235.                                            default:break;
  236.                                    }  
  237.                                         senduart2();
  238.                            }                          
  239.                         }
  240. ……………………

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


所有资料51hei提供下载:
该板配套参考程序.rar (141.45 KB, 下载次数: 256)
仿modbus通信协议控制.rar (47.45 KB, 下载次数: 226)
modbus上下位机程序.rar (857.01 KB, 下载次数: 254)
使用手册.docx (2.25 MB, 下载次数: 187)


分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏28 分享淘帖 顶1 踩
回复

使用道具 举报

沙发
ID:47652 发表于 2018-4-9 10:44 | 只看该作者
不错,收藏,谢谢LZ
回复

使用道具 举报

板凳
ID:322178 发表于 2018-5-8 17:10 | 只看该作者
学习学习
回复

使用道具 举报

地板
ID:147570 发表于 2018-7-28 22:57 | 只看该作者
好资料,51黑有你更精彩!!!
回复

使用道具 举报

5#
ID:607314 发表于 2019-9-4 18:58 | 只看该作者
有labview程序吗
回复

使用道具 举报

6#
ID:503472 发表于 2019-9-6 10:36 | 只看该作者
信息量很大
回复

使用道具 举报

7#
ID:57896 发表于 2019-9-7 10:03 | 只看该作者
非常好的modbus资料,收藏了
回复

使用道具 举报

8#
ID:428400 发表于 2019-9-17 19:39 | 只看该作者
这个连不了触摸屏的
回复

使用道具 举报

9#
ID:821299 发表于 2020-9-20 23:22 | 只看该作者
非常实用的资料。
回复

使用道具 举报

10#
ID:795427 发表于 2020-9-21 10:00 来自手机 | 只看该作者
没有物料清单
回复

使用道具 举报

11#
ID:97678 发表于 2020-9-21 15:04 | 只看该作者
好东西! 能不能提供原理图 和PCB文件啊?
回复

使用道具 举报

12#
ID:315554 发表于 2020-9-26 11:20 | 只看该作者
谢谢分享,很好的资料,modbus慢慢学了,
回复

使用道具 举报

13#
ID:361341 发表于 2020-11-6 10:37 | 只看该作者
好东西谢谢分享
回复

使用道具 举报

14#
ID:811405 发表于 2020-11-17 15:33 | 只看该作者
收藏,学习学习
回复

使用道具 举报

15#
ID:1108581 发表于 2024-1-20 20:15 | 只看该作者
感谢大佬分享资源,刚好想学习下这个,就是不知道文件里面有没有提供原理图和PCB文件之类的
回复

使用道具 举报

16#
ID:228452 发表于 2024-1-21 06:23 | 只看该作者
schematics and PCB files are not included ...
回复

使用道具 举报

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

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

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