一.继电器基础介绍
32路继电器通常用于自动化控制系统中,能够同时控制多达32个不同的电气设备。以下是对32路继电器的一些详细介绍:
1. 基本概念
- 继电器:一种电气控制装置,当输入信号(通常是电流或电压)达到一定标准时,继电器会启动并控制电路的打开或关闭。
- 路数:指可控制的通道数量,32路继电器意味着该设备可以独立控制32个负载。
2. 工作原理
- 电气原理:当继电器的线圈通电时,内部的机械开关闭合(或断开),从而控制负载的电流流通。
- 控制信号:通常采用微控制器、PLC、计算机等控制设备来发送控制信号。
3. 构成部分
- 继电器模块:包括多个继电器和电路的集成,通常设计为插拔式或模块化,便于扩展和维护。
- 控制接口:可以是USB、串口、GPIO等,用于与控制系统进行通信。
- 电源供应:需要提供适当的工作电压(如5V、12V、24V等),以保证继电器正常工作。
4. 应用领域
- 工业自动化:用于机器设备的控制,如电机启停、灯光控制等。
- 家居自动化:用于智能家居系统中,控制家居设备如灯光、空调等。
- 安防系统:用于监控设备或警报系统的控制。
- 实验室设备:在实验过程中实现对不同设备的精准控制。
5. 优缺点
- 优点:
- 同时控制多个设备,提高工作效率。
- 提供远程控制和自动化功能。
- 适应性强,模块化设计便于扩展。
- 缺点:
- 可能需要额外的电源管理。
- 对电路的要求较高,确保不出现故障。
- 如果控制信号不稳定,可能导致误动作。
6. 注意事项
- 在选择和使用32路继电器时,需要注意电气参数(如负载电压和电流),确保其适用性和安全性。
- 适当的散热必须考虑,尤其在同时控制多个高功率负载时。
- 有些继电器需要额外的保护电路(如瞬时保护、延时启动等)。
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
{
// 不 添加0
commend+=" ";
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
{
// 不 添加0
commend+=" ";
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
是低位。若用于存储或传输,需确认具体的字节序以便正确解析。