onenet云平台下发数据到单片机并且OLED屏显示

本篇文章记录我使用onenet云平台下发数据至单片机,并且使用OLED实时显示数据时遇到的一些问题以及解决办法。

单片机解析云平台下发的数据的解析代码如下,数据交互使用MQTT协议,json格式。在使用以下代码时,发现OLED屏幕会出现卡死现象,利用串口调试后,发现stm32程序也被卡死了。

改善前代码:

cpp 复制代码
case MQTT_PKT_PUBLISH:														//接收的Publish消息
		
			result = MQTT_UnPacketPublish(cmd, &cmdid_topic, &topic_len, &req_payload, &req_len, &qos, &pkt_id);
			if(result == 0)
			{
				UsartPrintf(USART_DEBUG, "topic: %s, topic_len: %d, payload: %s, payload_len: %d\r\n",
																	cmdid_topic, topic_len, req_payload, req_len);
				
				// 对数据包req_payload进行JSON格式解析
				json = cJSON_Parse(req_payload);
				params_json = cJSON_GetObjectItem(json,"params");	
     //   led_json=cJSON_GetObjectItem(params_json,"Led");				
			//	Alarm_json=cJSON_GetObjectItem(params_json,"alarm");	
				A_score_json=cJSON_GetObjectItem(params_json,"A_score");	
				B_score_json=cJSON_GetObjectItem(params_json,"B_score");	
				number_game_json=cJSON_GetObjectItem(params_json,"number_game");	
					if(A_score_json!=NULL)
					{
							
								A_score=A_score_json->valueint;	
							
					}	
					if(B_score_json!=NULL)
					{
							
								B_score=B_score_json->valueint;	
							
					}	
					if(number_game_json!=NULL)
					{
							
						number_game=number_game_json->valueint;	
						UsartPrintf(USART_DEBUG, "number_game:%d\r\n",number_game);
							
					}	
					
					
				
				cJSON_Delete(json);
				
			}
		break;

分析原因后,得知程序卡死的原因可能在于json解析到了空指针,所以导致硬件错误从而死机。主要修改部分就是如果解析到了空指针,就退出。

改善后代码:

cpp 复制代码
case MQTT_PKT_PUBLISH:														//接收的Publish消息

    result = MQTT_UnPacketPublish(cmd, &cmdid_topic, &topic_len, &req_payload, &req_len, &qos, &pkt_id);
    if(result == 0)
    {
        UsartPrintf(USART_DEBUG, "topic: %s, topic_len: %d, payload: %s, payload_len: %d\r\n",
                                            cmdid_topic, topic_len, req_payload, req_len);

        // ===================== 【安全区 绝对不会死机】 =====================
        req_payload[req_len] = '\0';  // 强制结束符,必加!

        json = cJSON_Parse(req_payload);

        // 关键:解析失败直接退出,绝不往下走
        if(json == NULL)
        {
            UsartPrintf(USART_DEBUG, "JSON解析失败\r\n");
        }
        else
        {
            params_json = cJSON_GetObjectItem(json, "params");

            if(params_json != NULL)
            {
                A_score_json = cJSON_GetObjectItem(params_json, "A_score");
                B_score_json = cJSON_GetObjectItem(params_json, "B_score");
                number_game_json = cJSON_GetObjectItem(params_json, "number_game");

                if(A_score_json != NULL)
                {
                    A_score = A_score_json->valueint;
                }
                if(B_score_json != NULL)
                {
                    B_score = B_score_json->valueint;
                }
                if(number_game_json != NULL)
                {
                    number_game = number_game_json->valueint;
                    UsartPrintf(USART_DEBUG, "number_game:%d\r\n", number_game);
                }
            }

            cJSON_Delete(json);
        }
    }
break;

改善代码后重新调试,发现虽然stm32虽然能正常刷新了。但是却解析不到云平台实时下发的正确的数据,短暂的获取到正确数据之后,又被错误数据给覆盖了。

分析后,发现原因可能在于解析数据时出现了问题,根据串口信息显示,单片机能够正确接收到云平台下发的数据,但是就是解析的时候出现错误,导致OLED屏不能正确显示数据。

改善前代码:

cpp 复制代码
case MQTT_PKT_PUBLISH:
    result = MQTT_UnPacketPublish(cmd, &cmdid_topic, &topic_len, &req_payload, &req_len, &qos, &pkt_id);
    if(result == 0)
    {
        UsartPrintf(USART_DEBUG, "topic: %s, payload: %s, len: %d\r\n", cmdid_topic, req_payload, req_len);
        req_payload[req_len] = '\0';
        json = cJSON_Parse(req_payload);
        if(json != NULL)
        {
            params_json = cJSON_GetObjectItem(json, "params");
            if(params_json != NULL)
            {
                // 只解析标准键值对格式,忽略嵌套格式
                A_score_json= cJSON_GetObjectItem(params_json, "A_score");
                if(A_score_json != NULL && A_score_json->type == cJSON_Number)
                {
                    A_score = A_score_json->valueint;
                }
                B_score_json= cJSON_GetObjectItem(params_json, "B_score");
                if(B_score_json != NULL && B_score_json->type == cJSON_Number)
                {
                    B_score = B_score_json->valueint;
                }
                number_game_json = cJSON_GetObjectItem(params_json, "number_game");
                if(number_game_json  != NULL && number_game_json ->type == cJSON_Number)
                {
                    number_game = number_game_json ->valueint;
                }
               UsartPrintf(USART_DEBUG, "Update: A=%d, B=%d, Game=%d\r\n", A_score, B_score, number_game);
            }
						
            cJSON_Delete(json);
        }
					else if(json == NULL)
        
						{
							 UsartPrintf(USART_DEBUG, "error!\r\n");
						}
    }
break;

因为这里的cJSON_Parse(req_payload)函数已经被破坏了,所以现在最快捷的办法就是自己写一个解析函数。

改善后代码:

cpp 复制代码
case MQTT_PKT_PUBLISH:
    result = MQTT_UnPacketPublish(cmd, &cmdid_topic, &topic_len, &req_payload, &req_len, &qos, &pkt_id);
    if(result == 0)
    {
        char temp_buf[256] = {0};
        if(req_len < 255)
        {
            memcpy(temp_buf, req_payload, req_len);
        }

        UsartPrintf(USART_DEBUG, "接收:%s\r\n", temp_buf);

        // ==============================
        // 纯手写解析,不依赖任何库!
        // ==============================
        int a_score = 0, b_score = 0, num_game = 0;

        // 提取 A_score
        char *p = strstr(temp_buf, "\"A_score\":");
        if(p != NULL)
        {
            sscanf(p, "\"A_score\":%d", &a_score);
        }

        // 提取 B_score
        p = strstr(temp_buf, "\"B_score\":");
        if(p != NULL)
        {
            sscanf(p, "\"B_score\":%d", &b_score);
        }

        // 提取 number_game
        p = strstr(temp_buf, "\"number_game\":");
        if(p != NULL)
        {
            sscanf(p, "\"number_game\":%d", &num_game);
        }

        // 赋值给全局变量
        A_score = a_score;
        B_score = b_score;
        number_game = num_game;

        UsartPrintf(USART_DEBUG, "解析成功:A=%d B=%d 局数=%d\r\n", A_score, B_score, number_game);
    }
break;

改善后代码可以正常使用,OLED屏能正常实时显示数据了。

这个示例说明了库不是完全有效的,难免会遇到解析时出现错误,即使接收到的数据是正确的,但是就是解析不出来,这个时候就要考虑是不是库坏了,才导致解析不出来数据。

相关推荐
硅农深芯3 小时前
为什么有的芯片电源pin叫VCC,有的叫VDD?
单片机·嵌入式硬件·vcc·vdd·vee·vss
d111111111d3 小时前
STM32-UART封装问题解析
笔记·stm32·单片机·嵌入式硬件·学习·算法
国产化创客4 小时前
龙芯 2K0300-- 实现工业网关监控仪表盘项目
嵌入式硬件·物联网·数据可视化
项目題供诗5 小时前
STM32-OLED显示屏(六)
stm32·单片机·嵌入式硬件
jllllyuz5 小时前
STM32F10x MQ-2烟雾传感器驱动程序
stm32·单片机·嵌入式硬件
bubiyoushang8887 小时前
STM32F030 多路ADC采样实现
stm32·单片机·嵌入式硬件
三佛科技-187366133978 小时前
LP8841SC+LP35118N (72W SiC双电源方案),全电压认证,体积直降 20%
单片机·嵌入式硬件
metaRTC8 小时前
metaRTC8 成功适配 RTOS:开启 MCU/嵌入式实时音视频新时代
单片机·嵌入式硬件·webrtc·实时音视频·rtos
d111111111d9 小时前
UAER问题+修复小bug
前端·javascript·笔记·stm32·单片机·嵌入式硬件·学习