有人云4G模块WH-LTE-7S1数据上传

模块介绍

WH-LTE-7S1 是为实现串口设备与网络服务器,通过LTE Cat-1和GPRS网络相互传输数据而开发的产品,通过简单的 AT 指令进行设置,即可轻松使用本产品实现串口到网络的双向数据透明传输

在这里插入图片描述

相关资料获取

官方设置软件:https://www.usr.cn/Download/986.html

说明文档:https://www.usr.cn/Download/index/keyword/WH-LTE-7S1

在这里插入图片描述

1. 云平台设置

有人云官网:https://mp.usr.cn

1.1 添加设备

添加设备并完善自己设备的基础信息

在这里插入图片描述

将设备的基本信息填写完毕后,点击选择模板

在这里插入图片描述

选择Modbus模板,并设置名称

在这里插入图片描述

添加网关,并自动生成SN

在这里插入图片描述

设备信息全部设置完成后的界面是这样的,然后点击保存

在这里插入图片描述

1.2 添加变量

点击设备管理设备模板选项卡,找到刚才添加的Modbus模板,点击"编辑"

在这里插入图片描述

在新的界面中点击“添加变量”按钮

在这里插入图片描述

设置你要上传数据的变量

在这里插入图片描述

我根据我需要写的项目添加了多个变量,实际的项目也不会是只有一个变量的,添加完变量后别忘了点击保存

在这里插入图片描述

2. 软件配置

2.1 模块电路连接

在这里插入图片描述

2.2 配置串口

我这里使用串口1进行串口打印操作,而4G模块的收发信息是通过串口3完成的

由于该4G模块需要通过AT指令进行设置,因此我通过串口1发送AT指令,再将这些指令转发到串口3,以实现对4G模块的控制和配置

串口1配置:

/**
 * @brief 初始化打印串口1
 * USART1_TXD --- PA9
 * USART1_RXD --- PA10
 */
void Usart1_Config(void) {
	// 开启PA9,PA10,USART1时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_USART1,ENABLE);
	// 配置IO口
	GPIO_InitTypeDef GPIO_InitStruct;
	// PA9 -- TX  -- 复用推挽
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP; // 复用推挽
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9;
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&GPIO_InitStruct);
	// PA10 -- RX  -- 浮空输入
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING; // 浮空输入
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10;
	GPIO_Init(GPIOA,&GPIO_InitStruct);
	// 配置串口:
	USART_InitTypeDef USART_InitStruct ={0};
	// 配置数据8位
	USART_InitStruct.USART_WordLength = USART_WordLength_8b;
	// 配置校验位0位
	USART_InitStruct.USART_Parity = USART_Parity_No;
	// 配置停止位1位
	USART_InitStruct.USART_StopBits = USART_StopBits_1;
	// 配置波特率
	USART_InitStruct.USART_BaudRate = 115200;
	// 打开发送接收
	USART_InitStruct.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;

	USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//不使用硬件控制流
	USART_Init(USART1, &USART_InitStruct);
	// 使能串口
	USART_Cmd(USART1, ENABLE);
	// 打开串口中断
	USART1->CR1 |= 0x1<<5; // 打开接收缓存区非空中断
	USART1->CR1 |= 0x1<<4; // 打开总线空闲中断
	// NVIC配置
	NVIC_SetPriority(USART1_IRQn, 3); // 设置优先级 0101抢占:01 次级:01
	NVIC_EnableIRQ(USART1_IRQn); // 使能中断
}

/**
 * @brief 串口1中断函数
 */
void USART1_IRQHandler(void) {
	uint8_t data = 0;
	// 判断中断挂起位
	if((USART1->SR & 0x1<<5) != 0) {
		// 读数据操作,同使也是清标志操作
		data = USART1->DR;
		USART3->DR = data; // 将AT指令转发给4G模块
	}
	if((USART1->SR & 0x1<<4) != 0) {
		// 读数据操作,同使也是清空闲标志操作
		data = USART1->DR;
	}
}

串口3配置:

typedef struct{
	uint8_t RX_DataBuf[256];	//接收数据缓冲区
	uint8_t DataBuf_Count;		//接收数据缓冲区数量
	uint8_t RXDataOK_Flag;		//接收数据完成标志位
}_DATA4G;

/**
 * @brief 初始化4G模块
 * USART3_TXD --- PB10
 * USART3_RXD --- PB11
 */
void Wire4G_Config(void) { 
	// 启用 GPIOB 外设时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);

	// 启用 USART3 外设时钟
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);

	// 定义结构体变量以初始化 GPIO, USART 和 NVIC
	GPIO_InitTypeDef GPIO_InitStructure = {0}; 
	USART_InitTypeDef USART_InitStructure = {0}; 
	NVIC_InitTypeDef NVIC_InitStructure = {0}; 

	// 复位 USART3 外设
	USART_DeInit(USART3); 

	// 配置 USART3 TX (PB.10) 引脚
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;       // 设置引脚为 PB.10
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; // 设置 GPIO 速度为 50 MHz
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  // 设置模式为复用推挽输出
	GPIO_Init(GPIOB, &GPIO_InitStructure);           // 初始化 PB.10

	// 配置 USART3 RX (PB.11) 引脚
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;       // 设置引脚为 PB.11
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; // 设置模式为浮空输入
	GPIO_Init(GPIOB, &GPIO_InitStructure);           // 初始化 PB.11

	// 配置 USART3 的 NVIC(中断向量控制器)
	NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn; // 设置中断通道为 USART3
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; // 抢占优先级为 2
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2; // 子优先级为 2
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;   // 启用中断通道
	NVIC_Init(&NVIC_InitStructure);                   // 初始化 NVIC

	// 初始化 USART3
	USART_InitStructure.USART_BaudRate = 115200;      // 设置波特率为 115200
	USART_InitStructure.USART_WordLength = USART_WordLength_8b; // 设置字长为 8 位数据格式
	USART_InitStructure.USART_StopBits = USART_StopBits_1; // 设置停止位为 1
	USART_InitStructure.USART_Parity = USART_Parity_No; // 设置无奇偶校验位
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; // 设置无硬件流控制
	USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; // 设置为接收和发送模式
	USART_Init(USART3, &USART_InitStructure); // 初始化 USART3

	// 启用 USART3 的接收中断
	USART_ITConfig(USART3, USART_IT_RXNE, ENABLE); // 开启接收非空中断
	USART_ITConfig(USART3, USART_IT_IDLE, ENABLE); // 开启空闲中断

	// 使能 USART3
	USART_Cmd(USART3, ENABLE); 
}

/**
 * @brief 串口3中断函数,负责接收4G模块下发的数据请求
 */
void USART3_IRQHandler(void) {
	uint8_t data = 0;
	// 接收中断
	if(USART_GetITStatus(USART3,USART_IT_RXNE) == 1) {
		USART_ClearITPendingBit(USART3,USART_IT_RXNE);
		data = USART3->DR; // 接收数据
		USART1->DR = data; // 通过串口1回显
		GetData4G.RX_DataBuf[GetData4G.DataBuf_Count++] = data; // 将串口接收的数据存放至数组
	}
	// 空闲中断
	if(USART_GetITStatus(USART3,USART_IT_IDLE) == 1) {
		// 清理中断标志
		data = USART3->SR;
		data = USART3->DR;
		GetData4G.RXDataOK_Flag = 1; // 接收完毕模块的请求
	}
}

2.3 4G模块设置

打开设置软件,选择相应的串口,设置波特率

点击有人云中的 ”网关管理“ — ”网关列表“ 选项卡,选择添加好的网关,点击”查看“

将”网关详情“中的网管信息添加到设置软件中

在这里插入图片描述

将设备编号(SN)和密码分别填置对应的位置,(图中我只是忘了填)

在这里插入图片描述

确定设置好串口工作后,将程序烧录置开发板中,随后点击图中指引的操作对4G模块进行配置

首先进入配置状态,当返回”执行完毕“后表示成功进入了配置状态 (图中的设备编号和密码我只是忘了填)

在这里插入图片描述

随后点击”设置并保存所有参数“,这时候软件会执行多条AT指令对4G模块进行设置,并且会出现进度条(图中的设备编号和密码我只是忘了填)

在这里插入图片描述

最后将设备重启,将软件中的打印格式显示为Hex,重启完成后等待1分钟左右,模块会下发数据收集指令(图中的设备编号和密码我只是忘了填)

在这里插入图片描述

3. Modbus通信协议 [重要]

此部分内容几乎完全照搬,大家可以直接去查看这个原文章连接,作者讲的很好我就不详细写了:https://blog.csdn.net/tiandiren111/article/details/118347661

Modbus是一种主从方式的通信协议,这意味着通信不能同步进行。总线上每次只能传输一个数据包,即由主机发送数据,从机进行应答。如果主机不发送数据,总线上将没有数据通信。

例如,当主机需要读取从机的温度数据时,主机首先发送一个读取温度的请求指令到总线上。从机接收到请求后,会回复温度数据给主机。整个过程中,总线上每次只有一个数据包在传输。

查看4G模块给我们发送过来的请求,图中画圈的部分就是Modbus格式的数据,先解释这一段数据:

在这里插入图片描述

这段数据的格式为:

帧结构 = 地址 + 功能码+ 数据 + 校验

  • 地址: 占用一个字节,范围0-255,其中有效范围是1-247,其他有特殊用途,比如255是广播地址(广播地址就是应答所有地址,正常的需要两个设备的地址一样才能进行查询和回复)。
  • 功能码:占用一个字节,功能码的意义就是,知道这个指令是干啥的,比如你可以查询从机的数据,也可以修改数据,所以不同功能码对应不同功能。
  • 数据:根据功能码不同,有不同结构,在下面的实例中有说明。
  • 校验:为了保证数据不错误,增加这个,然后再把前面的数据进行计算看数据是否一致,如果一致,就说明这帧数据是正确的,我再回复;如果不一样,说明你这个数据在传输的时候出了问题,数据不对的,所以就抛弃了

在这里插入图片描述

在这里插入图片描述

4. 相关协议和数据格式

4.1 模块回复内容

2.3步骤中可以看到模块下发的信息收集指令,这个指令的各个部分代表着什么呢?

可以查看相关的文档,通过文档提供的实例我们可以看到:

在这里插入图片描述

其中:

  • 包头固定为 0xAA 0xFD 0x55
  • 长度是指整个数据包中的有效数据的长度,从参数区(包含参数区)开始到和校验之前(不包含和校验)的所有字节数的总和,其实际数值相当于数据字节长度+2,即 n+2
  • 常用参数区为 Socket 编码,采用 0x61 开始的编码进行表示,若序号为 0x61,代表数据发向 Socket A;若为 0x62,代表数据发向 Socket B 的连接对象,其他 Socket 编号依次类推,即 0x63、0x64 代表 Socket C、Socket D
  • 这里的数据只是抽象为了0xCC,实际上这个数据为Modbus的格式,上文中已经对Modbus进行了解释
  • CheckSum 校验和,从参数区(包含参数区)开始算起,到校验字节之前,加和取最后一个字节作为校验字节

4.2 如何发送数据[关键]

官方文档给我们提供的例子上有固定的格式:

在这里插入图片描述

因此我们只需要确定我们想要上传的数据即可

通过第三步了解Modbus协议后才可以很顺利的写出数据的上传格式,我这里给个例子进行演示:

目标是将有人云上的8个变量相应的设置为:

室内温度:32℃ ;室内湿度:56%

大气压:5120Pa ; 二氧化碳:652PPM ; 光照强度:152LUX

氮:4mg/kg ; 磷:6mg/kg ; 钾:13mg/kg

将这些数值分别转换为16进制的数:

32(十进制) — 0X20(十六进制)— 00 20

56(十进制) — 0X38(十六进制)— 00 38

剩下的数我就不举例子了…

将这些数据转换为十六进制后按照Modbus的形式进行拼接:

01 03 数据长度 00 20 00 38 14 00 02 8C 00 99 00 04 00 06 00 0D 校验位

数据长度是如何计算的: 需要上传的数据个数 + 2,本文章的例子中数据长度就是8 + 2 = 10

校验位是如何计算的: 将数据长度计算完成后,通过CRC算法进行计算,也可以通过点击在线CRC计算,将校验位计算出后,最后的数据也就是:(注意低位在左 高位在右)

01 03 10 00 20 00 38 14 00 02 8C 00 99 00 04 00 06 00 0D E6 C8

CRC在线计算链接::http://www.ip33.com/crc.html

在这里插入图片描述

最后别忘了加上有人云的数据格式,包头和校验位

55 FD AA 00 数据长度 61 00 01 03 10 00 20 00 38 14 00 02 8C 00 99 00 04 00 06 00 0D E6 C8 校验位

数据长度是如何计算的: 从数据长度这一位开始数,一直数到校验位,也就是23位

61 00 01 03 10 00 20 00 38 14 00 02 8C 00 99 00 04 00 06 00 0D E6 C8

一共是23位,23的十六进制表示为17,因此数据长度这一位应该填写17

校验位是如何计算的: 从61开始一直到校验位之前的所有值相加

61+00+01+03+10+00+20+00+38+14+00+02+8C+00+99+00+04+00+06+00+0D+E6+C8=3CD

发现计算出来是3位数,只需要保留后2位就行了,也就是3CD只需要保留CD这两位

最终发送的数据格式为:

55 FD AA 00 17 61 00 01 03 10 00 20 00 38 14 00 02 8C 00 99 00 04 00 06 00 0D E6 C8 CD

4.3 数据上报

将上一步手动计算出的数据帧通过串口1发送至串口3,实现数据主动上报

数据上报成功: 发送成功是不会有任何回复的,可以看到数据成功被上传至有人云

在这里插入图片描述

数据上报失败: 数据发送失败则会返回消息

在这里插入图片描述

4.4 通过代码上报

如果你明白了4.3的内容,这个代码对你来说是没什么问题的

注意: CRC校验函数省略,网上搜索一大堆

uint8_t tem = 32;
uint8_t hum = 56;
uint16_t atmos = 5120;
uint16_t co2 = 652;
uint8_t light = 153;
uint8_t n = 4;
uint8_t p = 6;
uint8_t k = 13;

/**
 * @brief 将需要上传的数据进行拼接回复给4G模块
 */
void Wire4G_Anser03Data(void) {
	// 初始化发送缓冲区
	uint8_t Answer_buf[32] = {0x55, 0xFD, 0xAA, 0x00, 0x17, 0x61, 0x00, 0x01, 0x03, 0x10};
	// 初始化计数器和数据帧长度
	uint8_t buf_count = 10;
    uint16_t CRC_send = 0;
	
	// 将各个数据值拆分为高位和低位,并添加到发送缓冲区中
	Answer_buf[buf_count++] = tem >> 8;
	Answer_buf[buf_count++] = tem & 0XFF;
	
	Answer_buf[buf_count++] = hum >> 8;
	Answer_buf[buf_count++] = hum & 0XFF;
	
	Answer_buf[buf_count++] = atmos >> 8;
	Answer_buf[buf_count++] = atmos & 0XFF;
	
	Answer_buf[buf_count++] = co2 >> 8;
	Answer_buf[buf_count++] = co2 & 0XFF;
	
	Answer_buf[buf_count++] = light >> 8;
	Answer_buf[buf_count++] = light & 0XFF;
	
	Answer_buf[buf_count++] = n >> 8;
	Answer_buf[buf_count++] = n & 0XFF;
	
	Answer_buf[buf_count++] = p >> 8;
	Answer_buf[buf_count++] = p & 0XFF;
	
	Answer_buf[buf_count++] = k >> 8;
	Answer_buf[buf_count++] = k & 0XFF;

	// 计算 CRC 校验值并添加到发送缓冲区中
	uint16_t crc_ = ModBus_crc16_list(&Answer_buf[7], 19);
	Answer_buf[buf_count++] = crc_ >> 8;
	Answer_buf[buf_count++] = crc_ & 0XFF;
	
	// 计算校验和并添加到发送缓冲区中
	uint16_t sum = 0;
	for(uint8_t i = 5; i < buf_count; i++) {
		sum += Answer_buf[i];
	}
	Answer_buf[buf_count++] = sum & 0XFF;
	
    // 通过串口3发送数据帧
    Wire4G_SendStr(Answer_buf, buf_count);
}
### 智慧农业中的关键技术 #### 4G通信 在智慧农业环境中,4G通信模块用于远程数据输和监控。通过集成4G扩展模块,设备能够实现与端服务器或其他远程终端的数据交换[^1]。这种连接方式使得农民可以随时随地访问农田感器收集到的信息,如土壤湿度、气象条件等。 #### RS485接口 RS485是一种常用的工业级串行总线标准,在智慧农业里主要用于构建多节点网络来采集现场仪表读数或控制执行器动作。该接口具备良好的抗干扰能力和较长距离输特性,适合户外复杂环境下的稳定工作需求。具体来说,它支持多达32台设备接入同一总线上,并可通过增加中继器进一步扩大规模至数百甚至上千个节点。 #### Modbus协议 作为最广泛使用的SCADA(监控与数据获取)系统底层通讯规约之一,Modbus被大量应用于自动化控制系统之间以及这些系统同计算机之间的信息交互过程之中。对于智慧农业而言,无论是灌溉系统的启停操作还是温室内部温控装置的状态查询都可以借助于这一开放式的请求-响应机制完成高效而可靠的任务处理。此外,还存在两种主要版本——RTU(基于二进制编码)适用于硬件资源有限的小型嵌入式平台;TCP/IP则更适合大型分布式架构下跨网段互连互通场景的需求。 #### 串口屏 为了简化人机界面设计并提高用户体验感,许多现代农业装备都会配备带有触摸功能的液晶显示屏即所谓的“串口屏”。这类产品通常内置RTOS操作系统并且预装图形化开发工具包以便快速定制个性化的UI布局方案。更重要的是它们可以直接挂载到上述提到过的RS485链路上成为整个网络不可或缺的一部分参与整体业务逻辑运算流程当中去[^3]。 #### APM32的应用 APM32系列微控制器凭借其高性能ARM Cortex-M内核加上丰富的外设接口选项成为了众多农业科技企业打造创新型解决方案的理想选择对象。举例来讲,当涉及到精密播种机械的设计时就可以利用MCU精确调节电机转速从而确保种子播撒均匀度达到最佳效果;而在水质净化站项目里面同样也能发挥重要作用比如实时监测pH值变化趋势并通过PID算法自动调整加药泵流量大小维持目标区间范围内等等。 ```c++ // 示例代码展示如何初始化一个典型的RS485通信端口配置 void setup_rs485() { UART_HandleTypeDef huart; /* 配置UART参数 */ huart.Instance = USARTx; // 替换成实际使用的USART实例 huart.Init.BaudRate = 9600; // 设置波特率为9600bps huart.Init.WordLength = UART_WORDLENGTH_8B;// 字符长度为8位 huart.Init.StopBits = UART_STOPBITS_1; // 停止位数量为1 huart.Init.Parity = UART_PARITY_NONE; // 不启用校验位 HAL_UART_Init(&huart); // 初始化UART外设 } ```
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值