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%(无凝结)
五、引脚描述
五、硬件连接
电源的连接
RS485的连接
注:RS485建议采用双绞线连接,采用带屏蔽的双绞线连接,并将屏蔽层接地,总线上挂多个模块时,采用手拉手不的连接方式。
继电器输出的连接
六、软件协议
6.1串口通信定义
串口波特率:1位起始位、8位数据位 、1位停止位 、偶校验
默认地址:0x01
通讯接口:RS485
6.1指令功能表
6.2指令示例及详解
读取16路继电器状态(地址0x01)
从机回应
注:返回的十六路状态0为断开,1为吸合
控制多路继电器
a.控制所有继电器全开主机发送:
从机回应:
注:控制多路时数据域中二进制数对应位为1是打开某一路继电器,为0关闭某一路继电器
b控制所有继电器全关主机发送:
从机回应:
注:控制多路时数据域中二进制数对应位为1是打开某一路继电器,为0关闭某一路继电器
控制单个继电器状态
控制第一路继电器开主机发送:
从机回应:
控制第一路继电器关主机发送:
从机回应:
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(); } } ……………………