modbus RTU、TCP实现

##Modbus常用的功能码: DiscreteInputs,Coils,InputRegisters,HoldingRegisters
在这里插入图片描述
##常用功能码在这里插入图片描述

##核心代码如下:
通过传入connectType_的类型来设置连接类型,串口或者网口,即Serial或TCP,
当为Serial时,需要将串口号、波特率、数据位、校验位、停止位传入,为TCP则只用传入IP和Port即可,然后传入从站号即SetAddress,最后通过connectSlot进行连接即可,以下接口中通过信号与槽的连接将读写操作分别做了区分,可跨线程操作。
ModBus封装接口

class DModbusDevice: public QObject
{
	Q_OBJECT

	signals:
		void connectSignal(bool&);
		void disconnectSignal();

		void readSignal(quint16, quint16&, QModbusDevice::Error&) const;
		void readSignal(quint16, quint16, QVector<quint16>&, QModbusDevice::Error&) const;
		void read2Signal(quint16, quint16, QVector<bool>&, QModbusDevice::Error&) const;
		void read3Signal(quint16, quint16, QVector<bool>&, QModbusDevice::Error&) const;
		void read4Signal(quint16, quint16, QVector<quint16>&, QModbusDevice::Error&) const;
		void readSignal(QModbusDataUnit::RegisterType, quint16, quint16, QVector<quint16>&, QModbusDevice::Error&) const;

		void write2Signal(quint16, bool, QModbusDevice::Error&);
		void writeSignal(quint16, quint16, QModbusDevice::Error&) const;
		void writeSignal(quint16, quint16, const QVector<quint16>&, QModbusDevice::Error&) const;
		void writeSignal(QModbusDataUnit::RegisterType, quint16, quint16, const QVector<quint16>&, QModbusDevice::Error&) const;


public:
	DModbusDevice(QObject* parent = Q_NULLPTR);
	~DModbusDevice();

	void setConnectType(const ConnectType type);
	ConnectType connectType() const;

	void setIp(const QString& ip);
	QString ip() const;

	void setTcpPort(const qint32 port);
	qint32 tcpPort() const;

	void setPort(const QString& port);
	QString port() const;

	void setBaudRate(qint32 baudRate);
	qint32 baudRate() const;

	void setDataBits(QSerialPort::DataBits dataBits);
	QSerialPort::DataBits dataBits() const;

	void setParity(QSerialPort::Parity parity);
	QSerialPort::Parity parity() const;

	void setStopBits(QSerialPort::StopBits stopBits);
	QSerialPort::StopBits stopBits() const;

	void setTimeout(qint32 timeout);
	qint32 timeout() const;

	void setAddress(quint8);
	quint8 address() const;

	QModbusDevice::Error error();
	QString errorString();

	bool connect();
	void disconnect();

	QModbusDevice::Error read(quint16, quint16&) const;
	QModbusDevice::Error read(quint16, quint16, QVector<quint16>&) const;
	QModbusDevice::Error read2(quint16, quint16, QVector<bool>&) const;
	QModbusDevice::Error read3(quint16, quint16, QVector<bool>&) const;
	QModbusDevice::Error read4(quint16, quint16, QVector<quint16>&) const;
	QModbusDevice::Error read(QModbusDataUnit::RegisterType, quint16, quint16, QVector<quint16>&) const;

	QModbusDevice::Error write2(quint16, bool);
	QModbusDevice::Error write(quint16, quint16) const;
	QModbusDevice::Error write(quint16, quint16, const QVector<quint16>&) const;
	QModbusDevice::Error write(QModbusDataUnit::RegisterType, quint16, quint16, const QVector<quint16>&) const;

public slots:
	//
	void connectSlot(bool&);
	void disconnectSlot();

	void readSlot(quint16, quint16&, QModbusDevice::Error&) const;
	void readSlot(quint16, quint16, QVector<quint16>&, QModbusDevice::Error&) const;
	void read2Slot(quint16, quint16, QVector<bool>&, QModbusDevice::Error&) const;
	void read3Slot(quint16, quint16, QVector<bool>&, QModbusDevice::Error&) const;
	void read4Slot(quint16, quint16, QVector<quint16>&, QModbusDevice::Error&) const;
	void readSlot(QModbusDataUnit::RegisterType, quint16, quint16, QVector<quint16>&, QModbusDevice::Error&) const;

	void write2Slot(quint16, bool, QModbusDevice::Error&);
	void writeSlot(quint16, quint16, QModbusDevice::Error&) const;
	void writeSlot(quint16, quint16, const QVector<quint16>&, QModbusDevice::Error&) const;
	void writeSlot(QModbusDataUnit::RegisterType, quint16, quint16, const QVector<quint16>&, QModbusDevice::Error&) const;
	QModbusDevice::State state() const;
	QModbusDevice::Error ping();
	QModbusClient* baseDevice() const;

private:
	static QMutex mutex_;
	ConnectType connectType_;
	QString port_;
	qint32 baudRate_;
	QSerialPort::DataBits dataBits_;
	QSerialPort::Parity parity_;
	QSerialPort::StopBits stopBits_;
	qint32 timeout_;

	QString ip_;
	qint32 tcp_port_;

	quint8 address_;
	QModbusClient* client_;
};

实现

DModbusDevice::DModbusDevice(QObject* parent)
	: QObject(parent)
	, port_("")
	, baudRate_(QSerialPort::Baud9600)
	, dataBits_(QSerialPort::Data8)
	, parity_(QSerialPort::EvenParity)
	, stopBits_(QSerialPort::OneStop)
	, timeout_(1500)
	, address_(0)
	, client_(Q_NULLPTR)
	, connectType_(Serial)
	, ip_("127.0.0.1")
	, tcp_port_(8080)
{
	QObject::connect(this, SIGNAL(connectSignal(bool&)), this, SLOT(connectSlot(bool&)), Qt::BlockingQueuedConnection);
	QObject::connect(this, SIGNAL(disconnectSignal()), this, SLOT(disconnectSlot()), Qt::BlockingQueuedConnection);

	QObject::connect(this, SIGNAL(readSignal(quint16, quint16&, QModbusDevice::Error&)), this, SLOT(readSlot(quint16, quint16&, QModbusDevice::Error&)), Qt::BlockingQueuedConnection);
	QObject::connect(this, SIGNAL(readSignal(quint16, quint16, QVector<quint16>&, QModbusDevice::Error&)), this, SLOT(readSlot(quint16, quint16, QVector<quint16>&, QModbusDevice::Error&)), Qt::BlockingQueuedConnection);
	QObject::connect(this, SIGNAL(read2Signal(quint16, quint16, QVector<bool>&, QModbusDevice::Error&)), this, SLOT(read2Slot(quint16, quint16, QVector<bool>&, QModbusDevice::Error&)), Qt::BlockingQueuedConnection);
	QObject::connect(this, SIGNAL(read3Signal(quint16, quint16, QVector<bool>&, QModbusDevice::Error&)), this, SLOT(read3Slot(quint16, quint16, QVector<bool>&, QModbusDevice::Error&)), Qt::BlockingQueuedConnection);
	QObject::connect(this, SIGNAL(readSignal(QModbusDataUnit::RegisterType, quint16, quint16, QVector<quint16>&, QModbusDevice::Error&)), this, SLOT(readSlot(QModbusDataUnit::RegisterType, quint16, quint16, QVector<quint16>&, QModbusDevice::Error&)), Qt::BlockingQueuedConnection);
	QObject::connect(this, SIGNAL(read4Signal(quint16, quint16, QVector<quint16>&, QModbusDevice::Error&)), this, SLOT(read4Slot(quint16, quint16, QVector<quint16>&, QModbusDevice::Error&)), Qt::BlockingQueuedConnection);

	QObject::connect(this, SIGNAL(write2Signal(quint16, bool, QModbusDevice::Error&)), this, SLOT(write2Slot(quint16, bool, QModbusDevice::Error&)), Qt::BlockingQueuedConnection);
	QObject::connect(this, SIGNAL(writeSignal(quint16, quint16, QModbusDevice::Error&)), this, SLOT(writeSlot(quint16, quint16, QModbusDevice::Error&)), Qt::BlockingQueuedConnection);
	QObject::connect(this, SIGNAL(writeSignal(quint16, quint16, const QVector<quint16>&, QModbusDevice::Error&)), this, SLOT(writeSlot(quint16, quint16, const QVector<quint16>&, QModbusDevice::Error&)), Qt::BlockingQueuedConnection);
	QObject::connect(this, SIGNAL(writeSignal(QModbusDataUnit::RegisterType, quint16, quint16, const QVector<quint16>&, QModbusDevice::Error&)), this, SLOT(writeSlot(QModbusDataUnit::RegisterType, quint16, quint16, const QVector<quint16>&, QModbusDevice::Error&)), Qt::BlockingQueuedConnection);
}

void DModbusDevice::connectSlot(bool& result)
{


	if(connectType_ == Serial) {
		client_ = new QModbusRtuSerialMaster(/*this*/);
		if (state() == QModbusDevice::ConnectedState) {
			result = true;
			return;
		}
		client_->setConnectionParameter(QModbusDevice::SerialPortNameParameter, port_);
		client_->setConnectionParameter(QModbusDevice::SerialParityParameter, parity_);
		client_->setConnectionParameter(QModbusDevice::SerialBaudRateParameter, baudRate_);
		client_->setConnectionParameter(QModbusDevice::SerialDataBitsParameter, dataBits_);
		client_->setConnectionParameter(QModbusDevice::SerialStopBitsParameter, stopBits_);
	}
	else if(connectType_ == Tcp) {
		client_ = new QModbusTcpClient();
		if (state() == QModbusDevice::ConnectedState) {
			result = true;
			return;
		}
		client_->setConnectionParameter(QModbusDevice::NetworkAddressParameter, ip_);
		client_->setConnectionParameter(QModbusDevice::NetworkPortParameter, tcp_port_);
	}
	
	client_->setTimeout(timeout_);
	client_->setNumberOfRetries(2);

	result = client_->connectDevice();
}



void DModbusDevice::disconnectSlot()
{
	if (state() == QModbusDevice::UnconnectedState) {
		return;
	}
	client_->disconnectDevice();
	delete client_;
	client_ = Q_NULLPTR;
}

QModbusDevice::State DModbusDevice::state() const
{
	return client_->state();
}



void DModbusDevice::readSlot(quint16 start_address, quint16& value, QModbusDevice::Error& error) const
{
	QVector<quint16> values;
	readSlot(start_address, 1, values, error);
	if (error == QModbusDevice::NoError) {
		value = values[0];
	}

	//return ret;
}

void DModbusDevice::readSlot(quint16 start_address, quint16 count, QVector<quint16>& values, QModbusDevice::Error& error) const
{
	readSlot(QModbusDataUnit::HoldingRegisters, start_address, count, values, error);
}

void DModbusDevice::read2Slot(quint16 start_address, quint16 count, QVector<bool>& values, QModbusDevice::Error& error) const
{
	QVector<quint16> tmp;
	readSlot(QModbusDataUnit::DiscreteInputs, start_address, count, tmp, error);
	if (error == QModbusDevice::NoError) {
		for (int i = 0; i < count; ++i) {
			values.append(tmp.value(i));
		}
	}
	//return ret;
}




void DModbusDevice::read3Slot(quint16 start_address, quint16 count, QVector<bool>& values, QModbusDevice::Error& error) const {
	QVector<quint16> tmp;
	readSlot(QModbusDataUnit::Coils, start_address, count, tmp, error);
	if (error == QModbusDevice::NoError) {
		for (int i = 0; i < count; ++i) {
			values.append(tmp.value(i) == 1);
		}
	}
}

void DModbusDevice::read4Slot(quint16 start_address, quint16 count, QVector<quint16>& values, QModbusDevice::Error& error) const {
	readSlot(QModbusDataUnit::HoldingRegisters, start_address, count, values, error);
}

void DModbusDevice::readSlot(QModbusDataUnit::RegisterType type
                             , quint16 start_address, quint16 count, QVector<quint16>& values, QModbusDevice::Error& error) const
{
	//qInfo() << "device read enter" << QThread::currentThread();
	//QMutexLocker locker(&mutex_);
	//qInfo() << "device read leave";
	if (!client_)
	{
		error = QModbusDevice::ConnectionError;
		return;
	}
	int index = 0;
	R:
	const QModbusDataUnit read_unit(type, start_address, count);
	if (QModbusReply* reply = client_->sendReadRequest(read_unit, address_)) {
		QTimer timer;
		QEventLoop event_loop;
		QObject::connect(reply, &QModbusReply::finished, &event_loop, &QEventLoop::quit);
		QObject::connect(&timer, &QTimer::timeout, [&]() {
			event_loop.quit();
			//qCritical() << "device read timeout.";
		});
		timer.start(5000);
		event_loop.exec();
		timer.stop();
		//qInfo() << client_->error() << client_->errorString();

		if (!reply->isFinished()) {
			if(index < 3) {
				index++;
				QThread::msleep(500);
				goto R;
			}
			qCritical() << "device read timeout.";
			error = QModbusDevice::ConnectionError;
			return;
		}
		

		const auto error_code = reply->error();
		const auto error_string = reply->errorString();
		//qDebug() << error_code << error_string;

		if (error_code == QModbusDevice::NoError) {
			values.clear();
			const QModbusDataUnit unit = reply->result();
			//const auto data = reply->rawResult().data();
			for (uint i = 0; i < unit.valueCount(); i++) {
				values.append(unit.value(i));
			}
		}

		reply->deleteLater();
		error = error_code;
		return;
	}

	error = QModbusDevice::ConnectionError;
}


void DModbusDevice::write2Slot(quint16 start_address, bool on, QModbusDevice::Error& error)
{
	QVector<quint16> values;
	values << (on ? 1 : 0);
	qDebug() << "device " << start_address << " write" << on;
	writeSlot(QModbusDataUnit::Coils, start_address, 1, values, error);
}


void DModbusDevice::writeSlot(quint16 start_address, quint16 value, QModbusDevice::Error& error) const
{
	QVector<quint16> values;
	values << value;

	writeSlot(start_address, 1, values, error);
}

void DModbusDevice::writeSlot(quint16 start_address, quint16 count, const QVector<quint16>& values, QModbusDevice::Error& error) const
{
	return writeSlot(QModbusDataUnit::HoldingRegisters, start_address, count, values, error);
}


void DModbusDevice::writeSlot(QModbusDataUnit::RegisterType type
	, quint16 start_address, quint16 count, const QVector<quint16>& values, QModbusDevice::Error& error) const
{

	//qInfo() << "device write enter" << QThread::currentThread();
	//QMutexLocker locker(&mutex_);
	//qInfo() << "device write leave";
	if (!client_)
	{
		error = QModbusDevice::ConnectionError;
		return;
	}

	QModbusDataUnit write_unit(type, start_address, count);
	for (quint32 i = 0; i < write_unit.valueCount(); i++) {
		write_unit.setValue(i, values.value(i));
	}
	int index = 0;
	R:
	if (QModbusReply* reply = client_->sendWriteRequest(write_unit, address_)) {

		QTimer timer;
		QEventLoop event_loop;
		QObject::connect(reply, &QModbusReply::finished, &event_loop, &QEventLoop::quit);
		QObject::connect(&timer, &QTimer::timeout, [&]() {
			event_loop.quit();
		});
		timer.start(3000);
		event_loop.exec();
		timer.stop();

		qDebug() << "device write " << type << start_address << count << reply->isFinished() << reply->error();

		if (!reply->isFinished()) {
			if(index < 3) {
				index++;
				QThread::msleep(500);
				goto R;
			}
			qCritical() << "device write timeout.";
			error = QModbusDevice::ConnectionError;
			return;
		}

		const auto error_code = reply->error();
		//const auto error_string = reply->errorString();
		//qDebug() << error_code << error_string;

		//if(error_code == QModbusDevice::NoError) {
		//	const QModbusDataUnit data = reply->result();
		//	qDebug() << u8"消息数据个数:" << data.valueCount() << " :" << data.values();
		//}

		reply->deleteLater();
		error = error_code;
		return;
	}

	error = QModbusDevice::ConnectionError;
}


QModbusDevice::Error DModbusDevice::ping()
{
	return QModbusDevice::NoError;
}

QModbusClient* DModbusDevice::baseDevice() const
{
	return client_;
}

void DModbusDevice::setConnectType(const ConnectType type) {
	connectType_ = type;
}

ConnectType DModbusDevice::connectType() const {
	return connectType_;
}

void DModbusDevice::setIp(const QString& ip) {
	ip_ = ip;
}

QString DModbusDevice::ip() const {
	return ip_;
}

void DModbusDevice::setTcpPort(const qint32 port) {
	tcp_port_ = port;
}

qint32 DModbusDevice::tcpPort() const {
	return tcp_port_;
}


void DModbusDevice::setPort(const QString& port)
{
	port_ = port;
}

QString DModbusDevice::port() const
{
	return port_;
}

void DModbusDevice::setBaudRate(qint32 baudRate)
{
	baudRate_ = baudRate;
}

qint32 DModbusDevice::baudRate() const
{
	return baudRate_;
}

void DModbusDevice::setDataBits(QSerialPort::DataBits dataBits)
{
	dataBits_ = dataBits;
}

QSerialPort::DataBits DModbusDevice::dataBits() const
{
	return dataBits_;
}

void DModbusDevice::setParity(QSerialPort::Parity parity)
{
	parity_ = parity;
}

QSerialPort::Parity DModbusDevice::parity() const
{
	return parity_;
}

void DModbusDevice::setStopBits(QSerialPort::StopBits stopBits)
{
	stopBits_ = stopBits;
}

QSerialPort::StopBits DModbusDevice::stopBits() const
{
	return stopBits_;
}

void DModbusDevice::setTimeout(qint32 timeout)
{
	timeout_ = timeout;
}

qint32 DModbusDevice::timeout() const
{
	return timeout_;
}

void DModbusDevice::setAddress(quint8 address)
{
	address_ = address;
}
quint8 DModbusDevice::address() const
{
	return address_;
}

QModbusDevice::Error DModbusDevice::error()
{
	return baseDevice()->error();
}

QString DModbusDevice::errorString()
{
	return baseDevice()->errorString();
}

bool DModbusDevice::connect()  {
	bool result;
	if (this->thread() == QThread::currentThread()) {
		connectSlot(result);
	}
	else {
		emit connectSignal(result);
	}
	return result;
}

void DModbusDevice::disconnect()  {

	if (this->thread() == QThread::currentThread()) {
		disconnectSlot();
	}
	else {
		emit disconnectSignal();
	}
}

QModbusDevice::Error DModbusDevice::read(quint16 start_address, quint16& value) const {
	QModbusDevice::Error error;
	if (this->thread() == QThread::currentThread()) {
		readSlot(start_address, value, error);
	}
	else {
		emit readSignal(start_address, value, error);
	}
	return error;
}

QModbusDevice::Error DModbusDevice::read(quint16 start_address, quint16 count, QVector<quint16>& values) const {
	QModbusDevice::Error error;
	if (this->thread() == QThread::currentThread()) {
		readSlot(start_address, count, values, error);
	}
	else {
		emit readSignal(start_address, count, values, error);
	}
	return error;
}

QModbusDevice::Error DModbusDevice::read2(quint16 start_address, quint16 count, QVector<bool>& values) const {
	QModbusDevice::Error error;
	if (this->thread() == QThread::currentThread()) {
		read2Slot(start_address, count, values, error);
	}
	else {
		emit read2Signal(start_address, count, values, error);
	}
	return error;
}

QModbusDevice::Error DModbusDevice::read3(quint16 start_address, quint16 count, QVector<bool>& values) const {
	QModbusDevice::Error error;
	if (this->thread() == QThread::currentThread()) {
		read3Slot(start_address, count, values, error);
	}
	else {
		emit read3Signal(start_address, count, values, error);
	}
	return error;

}

QModbusDevice::Error DModbusDevice::read4(quint16 start_address, quint16 count, QVector<quint16>& values) const {
	QModbusDevice::Error error;
	if (this->thread() == QThread::currentThread()) {
		read4Slot(start_address, count, values, error);
	}
	else {
		emit read4Signal(start_address, count, values, error);
	}
	return error;
}


QModbusDevice::Error DModbusDevice::read(QModbusDataUnit::RegisterType type, quint16 start_address, quint16 count, QVector<quint16>& values) const {
	QModbusDevice::Error error;
	if (this->thread() == QThread::currentThread()) {
		readSlot(type, start_address, count, values, error);
	}
	else {
		emit readSignal(type, start_address, count, values, error);
	}
	return error;
}

QModbusDevice::Error DModbusDevice::write2(quint16  start_address, bool op) {
	QModbusDevice::Error error;
	if (this->thread() == QThread::currentThread()) {
		write2Slot(start_address, op, error);
	}
	else {
		emit write2Signal(start_address, op, error);
	}
	return error;
}

QModbusDevice::Error DModbusDevice::write(quint16 start_address, quint16 value) const {
	QModbusDevice::Error error;
	if (this->thread() == QThread::currentThread()) {
		writeSlot(start_address, value, error);
	}
	else {
		emit writeSignal(start_address, value, error);
	}
	return error;
}

QModbusDevice::Error DModbusDevice::write(quint16 start_address, quint16 count, const QVector<quint16>& values) const {
	QModbusDevice::Error error;
	if (this->thread() == QThread::currentThread()) {
		writeSlot(start_address,count, values, error);
	}
	else {
		emit writeSignal(start_address, count,  values, error);
	}
	return error;
}

QModbusDevice::Error DModbusDevice::write(QModbusDataUnit::RegisterType type, quint16 start_address, quint16 count,
	const QVector<quint16>& values) const {
	QModbusDevice::Error error;
	if (this->thread() == QThread::currentThread()) {
		writeSlot(type, start_address, count, values, error);
	}
	else {
		emit writeSignal(type, start_address, count, values, error);
	}
	return error;
}

DModbusDevice::~DModbusDevice()
{
	delete client_;
}

配置连接类型和配置参数,我通过读写ini将配置信息保存在本地。在这里插入图片描述测试读写线圈是否正常在这里插入图片描述

测试写保持寄存器在这里插入图片描述

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
支持Modbus TCPModubus RTURTU可以为RS232或者RS485。 支持RTU做主站或者Modubs TCP做主站。 支持多主机访问支持,最多连接100个TCP客户端。 支持所有的Modubus功能码和寄存器范围。 同时也可以做普通串口服务器使用。 ZLAN5142 概述 ZLAN5142 Modbus网关是上海卓岚信息科技有限公司开发的一款在Modbus TCPModbus RTU之间进行协议化的换器,其中Modbus RTU可以是RS485也可以是RS232接口。 ZLAN5142具备了强大的多主机访问支持功能和RS485总线冲突控制功能。所谓多主机功能是指,ZLAN5142作为Modbus TCP服务器时可以支持多达100个TCP客户端同时连接,多个TCP连接可以随机性的访问,ZLAN5142能够分别对不同的连接给出正确应答,保证数据稳定不丢包。相对于RS485总线只能够有一个主机进行访问,ZLAN5142实现了“多主机”功能。ZLAN5142实现了RS485总线的冲突控制,防止了多主机时的串口总线抢占问题。 另外,将ZLAN5142的“化协议”选择为“无”,也可以当作普通的透明传输的串口服务器使用。但是不同于普通的串口服务器例如ZLAN5102,ZLAN5142即使作为普通串口服务器模式下也可以支持“多主机”功能,可解决多个计算机或主站如何同时监控一个串口设备的难题。 特点 支持Modbus TCPModubus RTURTU可以为RS232或者RS485。 支持RTU做主站或者TCP做主站。 支持多主机访问支持,最多连接100个TCP客户端。 支持1200~460800波特率。 支持RS485总线冲突调度机制,防止总线冲突。 支持所有的Modubus功能码和寄存器范围。 可作为普通的透传串口服务器使用,具备ZLAN5102相同功能。 小于1W的低功耗设计。 内嵌485防雷保护功能,适合室外485通信。 支持DNS,满足通过域名实现通信的要求。支持DHCP。 2KV网络浪涌保护。 外壳采用抗辐射的SECC板,保证在高电磁辐射区也能够正常工作。 规格 网络界面 以太网 10/100 Mbps, RJ45 保护 内建2KV电磁隔离 串口界面 界面 RS-232/485 串口数 1 校验位 None, Even, Odd, Space, Mark 数据位 5~9 停止位 1,2 流控 RTS/CTS,DTR/DCR, XON/XOFF 速率 1200bps~460800bps 软件特性 协议 TCP,HTTP,UDP,ICMP,ARP,IP,DNS,DHCP 虚拟串口平台 Windows 95/98/ME/NT/2000/XP/WIN7/WIN8 配置方式 Web浏览器、卓岚ZLVirCom、串口类AT命令 电器特性 电压输入 DC9~24V,100mA 机械特性 外壳材料 抗电磁材料SECC钢板 尺寸 长×宽×高=9.4cm×6.5cm×2.5cm 工作环境 工作温度,湿度 -45~85℃,5~95% RH 储存温度,湿度 -45~165℃,5~95% RH W

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值