基于ARM开发,对接modbus-rtu设备读取数据

本文介绍了如何在基于ARM的系统中使用Modbus-RTU协议与温湿度设备进行数据交互,包括发送读取请求、处理反馈数据以及CRC16校验的过程。代码示例展示了如何初始化网络通信库,执行数据读取,并解析接收到的报文数据。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

基于ARM开发,对接modbus-rtu设备读取数据

modbus说明
Modbus协议有三类,分别是:Modbus-RTU、Modbus-ASCII、Modbus-TCP。一般来说,一个设备只有其中的一种协议,而且Modbus规定,Modbus-RTU是设备必须支持的协议,也是默认选项。所以大多数设备都采用了Modbus-RTU协议通信。本次就拿modbus-rtu设备来读取下。

读取命令

地址功能码读取寄存器Hi读取寄存器Lo读取长度Hi读取数据长度Lo校验CRC16 Hi校验CRC16 Lo
010300000002C40B

反馈命令

地址功能码数据长度寄存器内容数据1Hi寄存器内容数据1Lo寄存器内容数据2Hi寄存器内容数据2Lo校验CRC16 Hi校验CRC16 Lo
01030400EA01C8BDC1

功能码说明

在这里插入图片描述

以下模拟温湿度设备报文数据
温度 寄存器 0000 系数0.1
湿度 寄存器 0001 系数0.1

在这里插入图片描述

[2024-03-20 08:35:11.883]# SEND HEX> 01 03 00 00 00 02 C4 0B
[2024-03-20 08:35:11.889]# RECV HEX> 01 03 04 00 EA 01 C8 DB C1

温度(0000)-> 00 EA  --> 234 * 0.1(系数) = 23.4

在这里插入图片描述

湿度(0001)-> 01 C8 --> 456 * 0.1(系数) = 45.6

在这里插入图片描述
在这里插入图片描述

#include "../CommunicationLibrary/CommunicationLibrary.h"
void NeInitNetCommLib()
{
#ifdef WIN32
	WSADATA wd;
	WSAStartup(MAKEWORD(2, 2), &wd);
#else
	signal(SIGPIPE, SIG_IGN);
	signal(SIGABRT, SIG_IGN);
	signal(SIGFPE, SIG_IGN);
	signal(SIGILL, SIG_IGN);
	signal(SIGSEGV, SIG_IGN);
	signal(SIGTERM, SIG_IGN);
#endif
}
//CRC校验
unsigned short CRC16(unsigned char *Msg, unsigned short len)
{
	unsigned short CRC = 0xffff;
	unsigned short i, temp;
	while (len--)
	{
		CRC = CRC ^ (*Msg++);
		for (i = 0; i < 8; i++)
		{
			if (CRC & 0x0001)
				CRC = (CRC >> 1) ^ 0xa001;
			else
				CRC >>= 1;
		}
	}
	temp = CRC & 0xff;
	CRC = ((CRC >> 8) & 0xff) + (temp << 8);
	return(CRC);
}
void printf_hex(BYTE * buf, const int len) {
	for (int i = 0; i < len; i++) {
		printf("%02X ", buf[i]);
	}
	printf("\n");
}
void modbus_wsd(CommunicationLibrary::SocketTcpClient * m_tcp_cli) {
	BYTE nSendBuf[10] = { 0x00,0x03,0x00,0x00,0x00,0x02,0x00,0x00 };
	BYTE Frame[256] = { 0 };
	unsigned short CRC;
	int nUnitNo = 1;
	int nRecve = 0;
	int nSend = 8;  //modbus tcp nsend=12; modbus rtu nsend=8;

	nSendBuf[0] = (BYTE)nUnitNo;//设备地址
	CRC = CRC16(nSendBuf, 6);        // CRC验证
	nSendBuf[6] = (BYTE)((CRC >> 8) & 0x00FF);    // 高位在前
	nSendBuf[7] = (BYTE)(CRC & 0x00FF);         // 低位在后
	nRecve = nSendBuf[5] * 2 + 5;    //一个寄存器 数据接收2bye
	printf_hex(nSendBuf, 8);
	int len = CommunicationLibrary::send_data(m_tcp_cli, (const char *)nSendBuf, nSend, CommunicationLibrary::TCPCLIENT);
	if (len == nSend) {
		if (CommunicationLibrary::select_data(m_tcp_cli, CommunicationLibrary::TCPCLIENT)) {
			int recve_len = CommunicationLibrary::recv_data(m_tcp_cli, (char *)Frame, nRecve, CommunicationLibrary::TCPCLIENT);
			printf_hex(Frame, recve_len);
			if (recve_len == nRecve) { //解析温湿度数据
				unsigned short temp = 0, temp1 = 0;
				temp = Frame[3];
				temp = (temp << 8) + Frame[3 + 1];
				temp1 = Frame[5];
				temp1 = (temp1 << 8) + Frame[5 + 1];
				printf("温度:%0.2f\n", (float)temp / 10);
				printf("湿度:%0.2f\n", (float)temp1 / 10);
			}
		}
	}
	
}
int main()
{
	NeInitNetCommLib();
	CommunicationLibrary::SocketTcpClient * m_tcp_cli = new CommunicationLibrary::SocketTcpClient("127.0.0.1", 1001, 5, 3);
	m_tcp_cli->connect_ser();
	modbus_wsd(m_tcp_cli);
	getchar();
	delete m_tcp_cli;
}


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值