STM32+有人LET-7S1接入华为云IoTDA

STM32单片机接入IoTDA主要用到的就是串口透传,所以把无线模块配置为透传模式连上服务器即可,本次实验通过有人4G模块"WH-LET-7S1"接入华为云IoTDA具体流程如下图。

1. WH-LET-7S1模块配置——建立TCP连接

准备资料支持中心-济南有人物联网技术有限公司官网

模块手册见官网【说明书】WH-LTE-7S1&WH-LTE-7S1-GN 说明书-济南有人物联网技术有限公司官网

下载配置软件【设置软件】Cat-1系列 设置软件-济南有人物联网技术有限公司官网

1.1. 配置模块

依次点击下图按键进行设置

1.将模块通过串口与电脑相连,打开串口进行设置

2.获取当前参数,点击后可以收到目前模块的连接信息在图中5号位置

3.进入通讯状态,如果地址端口均正确点击后可进行通信

4.如需修改连接地址端口,点击此按键进行连接,修改后点击设置并保存参数,再点击进入通讯状态。

华为云IoTDA地址:

iot-mqtts.cn-north-4.myhuaweicloud.com,端口:1883

1.2. 设置模块特性

  • 设置模块,启用串口AT指令,后续操作中会根据连接超时发送AT指令复位模块再次连接;
  • 启动信息设置好后能够根据此信息判断模块是否进入正常工作模式。

2. STM32搭建工程

本次实验只需要用到两个串口以及一个定时器,串口均采用DMA+空闲中断接收:

  • 串口1作为调试串口打印调试信息,
  • 串口3作为与4G模块连接的通信来上报消息和解析命令,
  • 定时器TIM1作为操作失败超时处理。(通过定时器实现mqtt连接超时,发布失败等问题,避免延时造成的程序卡死问题)

2.1. CubeMX配置如下:

2.1.1配置串口1——调试串口不做接收使用

2.1.2配置串口3——DMA接收

2.1.3配置Tim1,更新中断

2.1.4配置NVIC

2.1.5配置时钟——选择外部高速时钟​​​​​​​

2.1.6SYS配置——SWD下载​​​​​​​

2.1.7时钟选择​​​​​​​

2.1.8工程生成

GENERATE CODE 生成工程

生成工程后在工程中创建User文件夹并包含在工程中用来存放用户编写的文件​​​​​​​ 

2.2. 移植MQTT库

  • 在User文件夹中创建MQTT文件夹存放MQTT库,并添加到工程目录中以及包含对应.h文件

2.3. 创建4G模块通信文件

2.3.1. 模块初始化函数
uint8_t lte_rest[10]={0x74,0x65,0x73,0x74,0x23,0x41,0x54,0x2B,0x5A,0x0D};
void LTE_Init(void)
{
    //4G模块复位模块
    HAL_UART_Transmit(LTE_UART,lte_rest,9,0xffff);
    is_mqtt_connected = 0;	//连接状态清零
    connect_overtime = 0;	//连接超时标志
    mqtt_publish_count = 0;	//发布计数清零
    publish_overtime = 0;	//发布超时清零
    ping_overtime = 0;
}

在程序初始化时调用该函数,或者在mqtt连接失败有异常情况时调用;主要目前为重启4G模块清除相关标志位。

模块复位指令在1.2设置模块特性中进行设置,模块指令为命令密码与AT+Z组合为“test#AT+Z[0D]”。

2.3.2. 4G模块连接MQTT
void LTE_Mqtt_Connect(uint8_t *ack_data)
{
	if(strstr((char *)ack_data,"LTE OK"))//判断lte模块是否启动
	{
		//mqtt 连接
		Mqtt_Connect();
	}
	if(ack_data[0]>>4 == CONNACK) //查看报文类型,判断mqtt是否连接成功
	{
		//mqtt 订阅消息
		memset(ex_mqtt_topic,0,TOPIC_LENGTH);
		sprintf(ex_mqtt_topic,Topic_CMD);
		Mqtt_Subscribe(ex_mqtt_topic);
		printf("mqtt connect success\r\n");
	}
	if(ack_data[0]>>4 == SUBACK) //查看报文类型,判断订阅消息是否成功
	{
		is_mqtt_connected = 1;//连接成功
		connect_overtime = 0;//超时计数清零
		printf("mqtt subscribe success\r\n");
	}
}

该函数入参为串口接收到的数据,在mqtt未连接成功时调用连接,如果收到4G模块启动消息说明模块启动成功进行连接,再根据收到的mqtt服务器返回的指令判断当前连接是否成功,消息订阅是否成功。

2.3.3. 封装MQTT相关函数

Mqtt连接函数,将Mqtt连接参数进行拼装后串口透传进行发送

void Mqtt_Connect(void)
{
	MQTTPacket_connectData data = MQTTPacket_connectData_initializer;
	int buflen = sizeof(mqtt_parse_buf);
	data.keepAliveInterval = 120;	//(S)会话时长,超过下线
	data.cleansession = 1;
	data.clientID.cstring = MYclientID;
	data.username.cstring = MYusername;
	data.password.cstring = MYpassword;
	/*拼接MQTT连接语句*/
	memset(mqtt_parse_buf,0,buflen);
	int len = MQTTSerialize_connect(mqtt_parse_buf, buflen, &data);//拼装mqtt内容
	HAL_UART_Transmit(LTE_UART, mqtt_parse_buf, len, 0xffff);
}

Mqtt主题订阅,入参为订阅主题


void Mqtt_Subscribe(char * subtopic_buf)
{
	static uint16_t picket_id = 1;
	
	MQTTString topicString = MQTTString_initializer;
	int req_qos = 0, len = 0;
	int buflen = sizeof(mqtt_parse_buf);
	
	topicString.cstring = subtopic_buf;
	memset(mqtt_parse_buf,0,buflen);
	len = MQTTSerialize_subscribe(mqtt_parse_buf, buflen, 0, ++picket_id, 1, &topicString, &req_qos);
	HAL_UART_Transmit(LTE_UART, mqtt_parse_buf, len, 0xffff);
}

Mqtt发布,发布完成后有相应的计数,再收到回复后进行消除,如发布失败一定时间后将重启模块

/**
  * @brief  mqtt 发布
  * @param  topic:主题  payload:内容
  * @retval 
  */
void Mqtt_Publish(char * topic, unsigned char * payload) 
{
	MQTTString topicString = MQTTString_initializer;
	topicString.cstring = topic;
	int buflen = sizeof(mqtt_parse_buf);
	uint8_t dup = 0;//重复
	int qos =1;
	uint8_t retain = 0;
	uint16_t packetid = 3;
	uint8_t ret =0;
	memset(mqtt_parse_buf,0,buflen);
	int len = MQTTSerialize_publish(mqtt_parse_buf, buflen, dup, qos, retain, packetid, topicString, payload, strlen((char *)payload));
	ret = HAL_UART_Transmit(LTE_UART, mqtt_parse_buf, len, 0xffff);
	printf("send_ret:%d\r\n",ret);
	//发布消息数量标志自加用于判断是否发布成功
	mqtt_publish_count++;
}

Mqtt Ping消息

void Mqtt_ping(void)
{
    int buflen = sizeof(mqtt_parse_buf);
    int len = MQTTSerialize_pingreq(mqtt_parse_buf, buflen);
    HAL_UART_Transmit(LTE_UART, mqtt_parse_buf, len, 0xffff);
	mqtt_ping_count++;
}

Mqtt通信异常处理

void Mqtt_Err_Deal(void)
{
	//mqtt 异常处理
	if(is_mqtt_connected==0)//mqtt 未连接成功
	{
		if(connect_overtime > 30)//30s 超时
		{
			printf("mqtt connect error\r\n");
			printf("LTE reset\r\n");
			LTE_Init();
		}
	}else{
		//mqtt 连接成功 发布失败
		if(publish_overtime > 30)//30s 超时
		{
			printf("mqtt publish error\r\n");
			printf("LTE reset\r\n");
			LTE_Init();
		}
		//ping失败
		if(ping_overtime > 130)//130s 超时
		{
			printf("mqtt ping error\r\n");
			printf("LTE reset\r\n");
			LTE_Init();
		}
		//发送 ping信息
		if(ping_timecount > 60)//60s发送一次ping消息
		{
			ping_timecount = 0;
			Mqtt_ping();
			printf("ping send end\r\n");
		}
	}
}

该异常信息是通过定时器计数实现,需要配合定时器使用,定时器回调函数如下:

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
	if(htim == &htim1)
	{
		count_100ms++;
		if((count_100ms%10) == 0)
		{
			/*1s*/
			count_100ms = 0;
			if(is_mqtt_connected == 0)//MQTT未连接成功
			{
				connect_overtime++;	//mqtt连接超时计数
				ping_timecount = 0;
			}else{
				ping_timecount++;//连接成功mqtt心跳包开始计数
			}
			if(mqtt_publish_count>0)//mqtt发布超时计数
			{
				publish_overtime++;
			}
			if(mqtt_ping_count>0)//mqtt 心跳超时计数
			{
				ping_overtime++;
			}
		}
		if(count_100ms > 10)
		{
			count_100ms = 0;
		}
	}
} 	

至此能够实现利用Mqtt协议接入华为云订阅主题以及异常解决,后续将实现华为云的属性上报,命令解析等

  • 17
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值