一.继电器基础介绍
32路继电器通常用于自动化控制系统中,能够同时控制多达32个不同的电气设备。以下是对32路继电器的一些详细介绍:
1. 基本概念
2. 工作原理
- 电气原理:当继电器的线圈通电时,内部的机械开关闭合(或断开),从而控制负载的电流流通。
- 控制信号:通常采用微控制器、PLC、计算机等控制设备来发送控制信号。
3. 构成部分
- 继电器模块:包括多个继电器和电路的集成,通常设计为插拔式或模块化,便于扩展和维护。
- 控制接口:可以是USB、串口、GPIO等,用于与控制系统进行通信。
- 电源供应:需要提供适当的工作电压(如5V、12V、24V等),以保证继电器正常工作。
4. 应用领域
- 工业自动化:用于机器设备的控制,如电机启停、灯光控制等。
- 家居自动化:用于智能家居系统中,控制家居设备如灯光、空调等。
- 安防系统:用于监控设备或警报系统的控制。
- 实验室设备:在实验过程中实现对不同设备的精准控制。
5. 优缺点
- 优点:
- 同时控制多个设备,提高工作效率。
- 提供远程控制和自动化功能。
- 适应性强,模块化设计便于扩展。
- 缺点:
- 可能需要额外的电源管理。
- 对电路的要求较高,确保不出现故障。
- 如果控制信号不稳定,可能导致误动作。
6. 注意事项
7. 协议
二.项目相关展示
1. 继电器的选择
- 这里的继电器选择的是32路继电器
- 对应继电器的通信不需要进行引入多余的库,使用本地的 QSerialPort 模块就行,不过如果有modbus当然更建议使用modbus库。
三.项目代码
- 我这个代码写的很粗糙,仅供参考。
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include<Windows.h>MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);Init();
}MainWindow::~MainWindow()
{if (serial.isOpen()) {serial.close();}delete ui;
}void MainWindow::Init()
{// 对串口进行初始化serial.setPortName("COM3");serial.setBaudRate(QSerialPort::Baud9600); // 设置波特率serial.setDataBits(QSerialPort::Data8); // 设置数据位serial.setParity(QSerialPort::NoParity); // 设置奇偶校验serial.setStopBits(QSerialPort::OneStop); // 设置停止位serial.setFlowControl(QSerialPort::NoFlowControl); // 设置流控制if (serial.open(QIODevice::ReadWrite)) {qDebug() << "Serial port opened successfully.";} else {qDebug() << "Failed to open serial port.";}// 01 69// 命令:55 %1 13 00 00 00 00 %2//55 01 13 00 00 00 00 69
}void MainWindow::on_pushButton_open_clicked()
{// 将和转换为十六进制字符串//QString hexString = QString::number(sum, 16).toUpper();int last=0x88;// 打开 继电器 前面 指令 字节 数 之和// 计算 最后一个 数last+=ui->spinBox_open->value();QString hexString = QString::number(last, 16).toUpper();// 组装 指令QString commend="55 01 32 00 00 00";if(ui->spinBox_open->value()>0&&ui->spinBox_open->value()<10){// 添加 零commend+=" ";commend+=("0"+QString::number(ui->spinBox_open->value()));commend+=" ";commend+=hexString;ui->textEdit->append("open commend = "+commend);} else{// 不 添加0commend+=" ";if(ui->spinBox_open->value()>=10&&ui->spinBox_open->value()<16){commend+="0";}commend+=(QString::number(ui->spinBox_open->value(),16).toUpper());commend+=" ";commend+=hexString;ui->textEdit->append("open commend = "+commend);}serial.write(QByteArray::fromHex(commend.toLatin1().data())); // 发送指令打开继电器}void MainWindow::on_pushButton_close_clicked()
{// 将和转换为十六进制字符串//QString hexString = QString::number(sum, 16).toUpper();int last=0x87;// 打开 继电器 前面 指令 字节 数 之和// 计算 最后一个 数last+=ui->spinBox_close->value();QString hexString = QString::number(last, 16).toUpper();// 组装 指令QString commend="55 01 31 00 00 00";if(ui->spinBox_close->value()>0&&ui->spinBox_close->value()<10){// 添加 零commend+=" ";commend+=("0"+QString::number(ui->spinBox_close->value()));commend+=" ";commend+=hexString;ui->textEdit->append("close commend = "+commend);} else{// 不 添加0commend+=" ";if(ui->spinBox_close->value()>=10&&ui->spinBox_close->value()<16){commend+="0";}commend+=(QString::number(ui->spinBox_close->value(),16).toUpper());commend+=" ";commend+=hexString;ui->textEdit->append("open commend = "+commend);}serial.write(QByteArray::fromHex(commend.toLatin1().data())); // 发送指令打开继电器}void MainWindow::on_pushButton_req_clicked()
{
// serial.write("1");
// ui->textEdit->append("继电器请求状态");serial.write("?");ui->textEdit->append("request");if (serial.waitForReadyRead(1000)){QByteArray responseData = serial.readAll();while (serial.waitForReadyRead(100)){responseData += serial.readAll();}qDebug() << "接收到响应: " << responseData;} else{qDebug() << "没有接收到数据!";}}void MainWindow::on_pushButton_read_clicked()
{QByteArray data = serial.readAll();if (!data.isEmpty()){ui->textEdit->append(data);} else{ui->textEdit->append("读取信息为空");}
}void MainWindow::on_pushButton_send_clicked()
{//QString command=ui->lineEdit_send->text();QString _qstrData=ui->lineEdit_send->text();//QByteArray commandBytes = command.toUtf8();serial.write(QByteArray::fromHex(_qstrData.toLatin1().data()));if (serial.waitForBytesWritten(1000)){ui->textEdit->append("send:"+_qstrData);}// 全部闭合 55 01 33 FF FF FF FF 85// 全部断开 55 01 33 00 00 00 00 89}
四.协议详细分析
1. 55 01 32 00 00 00 01 89
-
32路每一路代表一位,这里01代表的十六进制,总共是有8位。
-
这里高位字节在前,低位字节在后。
-
前面的01代表的是 0000 0001,低位的这一个字节以表示所有的位。
0x32
这个功能码代表闭合某一路。
2. 55 01 35 00 00 00 15 A0(同时打开1,3,5)
- 假如我要打开135路的开关,这里要使用功能码
0x35
,则低位部分为0001 0101,此时组合成16进制为0x15
,所以打开135命令为55 01 35 00 00 00 15 A0 - 对于校验位:是前面几位十六进制的和A0
- 0000 0000
3. 大端序(Big-Endian)和 小端序(Little-Endian)
在十六进制表示中,通常高位和低位的顺序取决于具体的上下文,特别是数据的存储格式(例如大端序和小端序)。
- 大端序(Big-Endian): 最高有效位(高位)在前面,最低有效位(低位)在后面。
- 小端序(Little-Endian): 最高有效位(高位)在后面,最低有效位(低位)在前面。
对于你的例子 00 00 00 01
:
- 大端序存储:
- 表示为:
00 00 00 01
- 高位在前,低位在后。
- 高位是
00
,低位是01
。
- 表示为:
- 小端序存储:
- 表示为:
01 00 00 00
- 高位在后,低位在前。
- 高位是
01
,低位是00
。
- 表示为:
- 结论
如果没有特定的上下文来指明是使用大端还是小端,单独看 00 00 00 01
这个序列,一般可以认为第一个 00
是高位(在大端序的情况下),而 01
是低位。若用于存储或传输,需确认具体的字节序以便正确解析。