基于STM32新大陆云平台上报数据和下发指令来点亮LED

使用配置环境

1.核心板:STM32F103C8T6

2.WIFI模块:ESP-01S

3.传感器:LED灯(引脚:PA0)

4.使用云平台:新大陆云平台

列出代码中用到的全局变量:

#define REV_OK		0	//接收完成标志
#define REV_WAIT	1	//接收未完成标志
unsigned char esp8266_buf[128];//WiFi数据接收缓存区
unsigned short esp8266_cnt = 0, esp8266_cntPre = 0;

一、上报数据

1.发送数据包长度AT指令(发数据前都要进行数据包长度声明发送,然后在发送数据包)

sprintf((char *)IPDATALEN,"AT+CIPSEND=%d\r\n",datalen);

2.发送数据包格式

datatype:数据上报格式类型

说明:具体为datas属性内的 传感数据格式类型,我用的代码示例数据类型为1:列如

"datas":

{

"temperature": 23.5,

"rgb-r": "#999",

 …

}

datas:要上报的传感数据数组()

msgid:消息编号(由客户端生成的一个用于表示该条报文的编号,用于服务器下发“上报响应”时原样带回)

"{\"t\": 3,\"datatype\":1,\"datas\": {\"tmp\":%.1f,\"hum\":%.1f,\"speed\":%d,\"countnum\":%d   } ,\"msgid\": 123}"

3.数据上报发送成功返回信息格式

"{\"msgid\":123,\"status\":0,\"t\":4}"

 详情可参考官方文档:设备接入协议-MQTT.docx · newlandedu/资料下载 - Gitee.com

具体封装函数

void ESP8266_cloudSend(float tmp,float hum,int Distance_mm,uint16_t countnum)
{	
	u8 IPDATA[200];
	u8 IPDATALEN[200];
	memset(IPDATA,0x00,200);
	sprintf((char *)IPDATA,"{\"t\": 3,\"datatype\":1,\"datas\": {\"tmp\":%.1f,\"hum\":%.1f,\"speed\":%d,\"countnum\":%d   } ,\"msgid\": 123}"
		,tmp,hum,Distance_mm,countnum);
	int datalen=strlen(IPDATA);//计算数据包长度
	memset(IPDATALEN,0x00,200);
	sprintf((char *)IPDATALEN,"AT+CIPSEND=%d\r\n",datalen);
	while(ESP8266_SendCmd(IPDATALEN, "OK"))//数据包长度声明发送
	delay_ms(500);
	UsartPrintf(USART_DEBUG, "数据上报发送中...\r\n");
	
	while(ESP8266_SendCmd(IPDATA, "{\"msgid\":123,\"status\":0,\"t\":4}"))//数据上报发送
		delay_ms(500);
	
	UsartPrintf(USART_DEBUG, "数据上报发送成功\r\n");
	
}

二、云平台下发指令

1.云平台配置执行器

2.下层数据解析

数据返回:ESP8266的返回格式为    "+IPD,x:yyy"    x代表数据长度,yyy是数据内容(说明:        不同网络设备返回的格式不同,需要去调试)

1、ESP8266串口来数据后触发中断进行数据接收,将数据保存esp8266_buf

//==========================================================
//	函数名称:	USART2_IRQHandler
//
//	函数功能:	串口2收发中断
//
//	入口参数:	无
//
//	返回参数:	无
//
//	说明:		
//==========================================================
void USART2_IRQHandler(void)
{

	if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET) //接收中断
	{
		if(esp8266_cnt >= sizeof(esp8266_buf))	esp8266_cnt = 0; //防止串口被刷爆
		esp8266_buf[esp8266_cnt++] = USART2->DR;
		USART_ClearFlag(USART2, USART_FLAG_RXNE);
	}

}

2、将平台返回的数据解析,把数据内容返回


//==========================================================
//	函数名称:	ESP8266_GetIPD
//
//	函数功能:	获取平台返回的数据
//
//	入口参数:	等待的时间(乘以10ms)
//
//	返回参数:	平台返回的原始数据
//
//	说明:		不同网络设备返回的格式不同,需要去调试
//				如ESP8266的返回格式为	"+IPD,x:yyy"	x代表数据长度,yyy是数据内容
//==========================================================
unsigned char *ESP8266_GetIPD(unsigned short timeOut)
{

	char *ptrIPD = NULL;
	
	do
	{
		if(ESP8266_WaitRecive() == REV_OK)								//如果接收完成
		{
			ptrIPD = strstr((char *)esp8266_buf, "IPD,");				//搜索“IPD”头
			if(ptrIPD == NULL)											//如果没找到,可能是IPD头的延迟,还是需要等待一会,但不会超过设定的时间
			{
				//UsartPrintf(USART_DEBUG, "\"IPD\" not found\r\n");
			}
			else
			{
				ptrIPD = strchr(ptrIPD, ':');							//找到':'
				if(ptrIPD != NULL)
				{
					ptrIPD++;
					return (unsigned char *)(ptrIPD);
				}
				else
					return NULL;
				
			}
		}
		
		delay_ms(5);													//延时等待
	} while(timeOut--);
	
	return NULL;														//超时还未找到,返回空指针

}

3、再次解析提取内容,然后底层进行对应操作

//平台下发数据格式
//{"apitag":"motor02","cmdid":"aa71fefe-f363-4461-a568-bdf51c8cea7c","data":"100","t":5}
void ESP8266_cloudCtr(unsigned char *dataPtr)
{

		if(strstr((char *)dataPtr, "{\"apitag\":\"led001\","))		//搜索"led001"
		{
			if(strstr((char *)dataPtr, "\"data\":1,"))								//控制数据如果为1,代表开
			{                        
				GPIO_ResetBits(GPIOA, GPIO_Pin_0);
				delay_ms(500);
			}
			else if(strstr((char *)dataPtr, "\"data\":0,"))							//控制数据如果为0,代表关
			{
				GPIO_SetBits(GPIOA, GPIO_Pin_0);
				delay_ms(500);
			}
			ESP8266_Clear();
		}
		//{"apitag":"motor02","cmdid":"aa71fefe-f363-4461-a568-bdf51c8cea7c","data":"100","t":5}
		if(strstr((char *)dataPtr, "{\"apitag\":\"motor01\","))		//搜索"motor01"
		{
			if(strstr((char *)dataPtr, "\"data\":1,"))								//控制数据如果为1,代表开
			{
				Speed_cloud += 20;
				if (Speed_cloud > 80)
				{
				Speed_cloud = -80;
				}
				Motor_SetSpeed(Speed_cloud);
			}
			else if(strstr((char *)dataPtr, "\"data\":0,"))							//控制数据如果为0,代表关
			{
				Speed_cloud += 20;
				if (Speed_cloud > 80)
				{
				Speed_cloud = -80;
				}
				Motor_SetSpeed(Speed_cloud);
			}
			OLED_ShowSignedNum(1, 7, Speed_cloud, 3);
			ESP8266_Clear();
		}
}

三、main函数的while循环中调用

unsigned char *dataPtr = NULL;
dataPtr = ESP8266_GetIPD(0);
if(dataPtr != NULL)
{
	ESP8266_cloudCtr(dataPtr);
}
ESP8266_cloudSend(dht11_info.tempreture,dht11_info.humidity,Distance_mm,countnum);

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值