单片机
返回首页

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

2020-09-21 来源:51hei

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

一、应用场合

  • 工业控制需要扩展输出口的场合

  • PLC输出接口扩展

  • 组态触摸屏控制

  • 简要说明

  • 尺寸:长152mmX宽163mmX高25mm

  • 通讯协议: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系统都已安装)

  • 打开该软件前请先把数据线和控制板连接好,控制板供电

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

产品展示

附录:


单片机源程序如下:

/********************************************************************

                            汇诚科技

实现功能:串口控制继电器程序

使用芯片:AT89S52

晶振:11.0592MHZ

波特率:9600

编译环境:Keil

【声明】此程序仅用于学习与参考,引用请注明版权和作者信息!

*********************************************************************/

#include                 //库文件

#include

#include

#define uchar unsigned char//宏定义无符号字符型

sbit K1=P2^0;

sbit K2=P2^1;

sbit K3=P2^2;

sbit K4=P2^3;

sbit K5=P2^4;

sbit K6=P2^5;

sbit K7=P2^6;

sbit K8=P2^7;

sbit K9=P1^0;

sbit K10=P1^1;

sbit K11=P1^2;

sbit K12=P1^3;

sbit K13=P1^4;

sbit K14=P1^5;

sbit K15=P1^6;

sbit K16=P1^7;


sbit RS485_DIR=P3^7;

uchar dat;

uchar t,r,ii;

uchar add;    //掉电保持485的地址

uchar j=0;

bit flag_zx=0;

uchar sendBuf[10];          //发送缓冲区

uchar receBuf[10];    //接收缓冲区

bit busy;

bit bz1=0;

bit bz2=0;

bit bz3=0;

bit bz4=0;

bit bz5=0;

bit bz6=0;

bit bz7=0;

bit bz8=0;

/********************************************************************

                            延时函数

*********************************************************************/

void delay(uchar t)

{

  uchar i,j;

   for(i=0;i   {

            for(j=13;j>0;j--);

         { ;

         }

   }

}


/********************************************************************

              功能:串口初始化,波特率9600,方式1

*********************************************************************/

void Init_Com(void)

{

TMOD = 0x20;

PCON = 0x00;

SCON = 0x50;

TH1 = 0xFd;

TL1 = 0xFd;

TR1 = 1;

ES=1;

EA=1;

}


/****************发送函数*********************/

void senduart2()

{          

RS485_DIR=1;

SBUF=sendBuf[0];while(!TI);TI=0;

SBUF=sendBuf[1];while(!TI);TI=0;

SBUF=sendBuf[2];while(!TI);TI=0;

SBUF=sendBuf[3];while(!TI);TI=0;

SBUF=sendBuf[4];while(!TI);TI=0;

RS485_DIR=0;

}

/*****************清空发送缓冲区*************************/

void clear_receBuf()

{

    uchar i;

        for(i=0;i<5;i++)

        {

            receBuf[i]=0;

        }

}

/********************************************************************

                            主函数

*********************************************************************/

void main()

{

Init_Com();//串口初始化

add = EEPROMReadByte(0);

//add = 0X00;

    P2=0XFF;

        P1=0XFF;

        RS485_DIR=0;

while(1)

{


/********************************************************************

                            接收数据判断函数

*********************************************************************/

if(RI)  //如果有接收

           {

             RI=0; //接收标志清零

             receBuf[r++&0x0F]=SBUF;     //把接受的数据存储到BUT数组中

                 if(receBuf[0]!=0xaa){r=0;}

                 if(r>=5)

                 {        r=0;


                    flag_zx=1;

                 }

           }

           if(flag_zx==1)

           {                     


                flag_zx=0;

                    //0         1       2       3        4               

                        //起始位   地址位  功能位   数据位  结束位

                        if((receBuf[0]==0xaa)&&(receBuf[4]==0xbb)&&(receBuf[1]==add))          //如果开始位和结束位,还有地址都正确,进行下一步判断

                        {

                           if(receBuf[2]==0x01)  //修改板子地址

                           {

                                add=receBuf[3];

                                        EEPROMSectorErase(0);//擦除扇区

                                EEPROMWriteByte(0,add);//写入新的地址

                           }

                           else if(receBuf[2]==0x02)  //打开单路继电器

                           {

                                       switch(receBuf[3])

                                        {

                                            case 0x01: K1=0; break;

                                                case 0x02: K2=0; break;

                                            case 0x03: K3=0; break;

                                                case 0x04: K4=0; break;

                                            case 0x05: K5=0; break;

                                                case 0x06: K6=0; break;

                                            case 0x07: K7=0; break;

                                                case 0x08: K8=0; break;

                                                case 0x09: K9=0; break;

                                                case 0x0A: K10=0; break;

                                            case 0x0B: K11=0; break;

                                                case 0x0C: K12=0; break;

                                            case 0x0D: K13=0; break;

                                                case 0x0E: K14=0; break;

                                            case 0x0F: K15=0; break;

                                                case 0x10: K16=0; break;

                                                default:break;

                                        }

                           }

                           else if(receBuf[2]==0x03)  //关闭单路继电器

                           {

                                       switch(receBuf[3])

                                        {

                                            case 0x01: K1=1; break;

                                                case 0x02: K2=1; break;

                                            case 0x03: K3=1; break;

                                                case 0x04: K4=1; break;

                                            case 0x05: K5=1; break;

                                                case 0x06: K6=1; break;

                                            case 0x07: K7=1; break;

                                                case 0x08: K8=1; break;

                                              case 0x09: K9=1; break;

                                                case 0x0A: K10=1; break;

                                            case 0x0B: K11=1; break;

                                                case 0x0C: K12=1; break;

                                            case 0x0D: K13=1; break;

                                                case 0x0E: K14=1; break;

                                            case 0x0F: K15=1; break;

                                                case 0x10: K16=1; break;

                                                default:break;

                                        }                       

                           }

                           else if(receBuf[2]==0x04)  //打开全部继电器

                           {

                                if(receBuf[3]==0xff)

                                {

                                            P2=0X00;

                                            P1=0X00;

                                        }  

                           }

                           else if(receBuf[2]==0x05)  //关闭全部继电器

                           {

                                if(receBuf[3]==0x00)

                                {

                                            P2=0XFF;

                                                P1=0XFF;

                                        }                       

                           }

                           else if(receBuf[2]==0x06)  //查询继电器

                           {

                                        sendBuf[0]=0xaa;

                                        sendBuf[1]=add;

                                        sendBuf[2]=0x07;

                                        //sendBuf[3]=0xfe;

                                        sendBuf[4]=0xbb;       

                               switch(receBuf[3])

                                   {

                                       case 0x01: if(K1==0) sendBuf[3]=0xFF;else sendBuf[3]=0x00;break;

                                           case 0x02: if(K2==0) sendBuf[3]=0xFF;else sendBuf[3]=0x00;break;

                                       case 0x03: if(K3==0) sendBuf[3]=0xFF;else sendBuf[3]=0x00;break;

                                           case 0x04: if(K4==0) sendBuf[3]=0xFF;else sendBuf[3]=0x00;break;

                                       case 0x05: if(K5==0) sendBuf[3]=0xFF;else sendBuf[3]=0x00;break;

                                           case 0x06: if(K6==0) sendBuf[3]=0xFF;else sendBuf[3]=0x00;break;

                                       case 0x07: if(K7==0) sendBuf[3]=0xFF;else sendBuf[3]=0x00;break;

                                           case 0x08: if(K8==0) sendBuf[3]=0xFF;else sendBuf[3]=0x00;break;

                                       case 0x09: if(K9==0) sendBuf[3]=0xFF;else sendBuf[3]=0x00;break;

                                           case 0x0A: if(K10==0) sendBuf[3]=0xFF;else sendBuf[3]=0x00;break;

                                       case 0x0B: if(K11==0) sendBuf[3]=0xFF;else sendBuf[3]=0x00;break;

                                           case 0x0C: if(K12==0) sendBuf[3]=0xFF;else sendBuf[3]=0x00;break;

                                       case 0x0D: if(K13==0) sendBuf[3]=0xFF;else sendBuf[3]=0x00;break;

                                           case 0x0E: if(K14==0) sendBuf[3]=0xFF;else sendBuf[3]=0x00;break;

                                       case 0x0F: if(K15==0) sendBuf[3]=0xFF;else sendBuf[3]=0x00;break;

                                           case 0x10: if(K16==0) sendBuf[3]=0xFF;else sendBuf[3]=0x00;break;

                                           default:break;

                                   }  

                                   senduart2();

                           }

                           else if(receBuf[2]==0x08)  //查询输入

                           {

                                        sendBuf[0]=0xaa;

                                        sendBuf[1]=add;

                                        sendBuf[2]=0x09;

                                        //sendBuf[3]=0xfe;

                                        sendBuf[4]=0xbb;

                               

                               switch(receBuf[3])

                                   {

                                       case 0x01: sendBuf[3]=0xFF;break;


                                           default:break;

                                   }  

                                        senduart2();

                           }                          

                        }

……………………




进入单片机查看更多内容>>
相关视频
  • RISC-V嵌入式系统开发

  • SOC系统级芯片设计实验

  • 云龙51单片机实训视频教程(王云,字幕版)

  • 2022 Digi-Key KOL 系列: 你见过1GHz主频的单片机吗?Teensy 4.1开发板介绍

  • TI 新一代 C2000™ 微控制器:全方位助力伺服及马达驱动应用

  • MSP430电容触摸技术 - 防水Demo演示

精选电路图
  • 简洁的过零调功器电路设计与分析

  • 单稳态控制电路设计与分析

  • 光控电路设计与分析

  • 永不缺相启动运行的电动机控制电路

  • 开关电源的基本组成及工作原理

  • MT3608构成3.7V转12V的升压电路图

    相关电子头条文章