物联网应用开发--STM32与新大陆云平台通信(云平台控制开发板上蜂鸣器、LED)

news2024/11/19 5:42:39

实现目标

1、掌握云平台执行器的创建

2、熟悉STM32 与ESP8266模块之间的通信

3、具体实现目标:(1)创建5个执行器:蜂鸣器,LED1,LED2,ED3,LED4;(2)执行器能对应控制开发板的蜂鸣器和LED。


一、项目创建

项目创建详细步骤参考:https://blog.csdn.net/luojuan198780/article/details/138766783

项目整体:创建5个执行器

1.1   执行器之蜂鸣器设置

1.2  执行器之LED设置。4个LED配置除了名称其它都一样

二、开发板连接图

开发板P7四个跳键帽接法如下图:

说明:单片机的USART1用于调试信息打印USART2用于与ESP8266模块通信。

三、STM32CubeMX 配置

1.GPIO配置

BEEP:初始电平为低电平,推挽输出;LED1-LED4:初始电平为高电平,推挽输出。

2.串口USART1配置

USART1:异步模式,波特率115200,功能:用于打印调试信息

3.串口USART2配置

USART2:异步模式,波特率115200,开启DMA,开启中断。功能:用于与ESP8266通信

四、程序设计

说明:整个工程的代码量大,下面只列出了整个工程中最主要的一些函数。

1、串口USART1重定向

#include <stdio.h>

int fputc(int ch,FILE *f)
{
	HAL_UART_Transmit (&huart1 ,(uint8_t *)&ch,1,HAL_MAX_DELAY );
	return ch;
}

2、串口USART2收发实现

uint8_t UART2_RX_BUF[255];

//开启DMA空闲接收中断,将数据存放在数组UART2_RX_BUF中
  HAL_UARTEx_ReceiveToIdle_DMA(&huart2,UART2_RX_BUF,sizeof(UART2_RX_BUF)); 


//中断回调函数:实现接收云平台发来的数据
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{
		if(huart == &huart2) //  
		{ 
			HAL_UARTEx_ReceiveToIdle_DMA(&huart2,UART2_RX_BUF,sizeof(UART2_RX_BUF));
			__HAL_DMA_DISABLE_IT(&hdma_usart2_rx,DMA_IT_HT);			
	  }
}


//功能:发送AT指令字符串
void SendAtCmd(uint8_t *string, uint8_t len)
{
	HAL_UART_Transmit(&huart2,string, len,1000);
	HAL_UART_Transmit(&huart2,(uint8_t *)"\r\n", 2,20);	
}

//清空AT串口接收缓存
void ClrAtRxBuf(void)
{
	memset(AT_RX_BUF, 0x00, MAX_AT_RX_LEN);//清空缓存
	AT_RX_COUNT = 0;
	F_AT_RX_FINISH = 0;
}

3、STM32发送AT指令主要函数

//ESP8266设置为station模式  -----1
int8_t ESP8266_SetStation(void)
{
	ClrAtRxBuf();//清空缓存
	SendAtCmd((uint8_t *)AT_CWMODE,strlen(AT_CWMODE));
	printf("AT+CWMODE_CUR=1\r\n");
	HAL_Delay(100);
	if(strstr((const char *)AT_RX_BUF, (const char *)"OK") == NULL)
	{
	    printf("AT+CWMODE_CUR=1 error\r\n");
		return -1;
	}
	else
	{
		printf("AT+CWMODE_CUR=1 ok\r\n");
	}
	return 0;
}


//设置ESP8266要连接的热点名称和密码  -----2

int8_t ESP8266_SetAP(char *wifi, char *pwd)
{
	uint8_t AtCwjap[MAX_AT_TX_LEN];
	memset(AtCwjap, 0x00, MAX_AT_TX_LEN);//清空缓存
	ClrAtRxBuf();//清空缓存
	sprintf((char *)AtCwjap,"AT+CWJAP_CUR=\"%s\",\"%s\"",wifi, pwd);
	printf("AT+CWJAP_CUR=newland-edu1,12345678 \r\n");
	SendAtCmd((uint8_t *)AtCwjap,strlen((const char *)AtCwjap));
	HAL_Delay(5500);
	if(strstr((const char *)AT_RX_BUF, (const char *)"OK") == NULL)
	{
		return -1;
	}
	return 0;
}


//ESP8266建立TCP连接  -----3

int8_t ESP8266_IpStart(char *IpAddr, uint16_t port)
{
    uint8_t IpStart[MAX_AT_TX_LEN];   
    memset(IpStart, 0x00, MAX_AT_TX_LEN);//清空缓存   
    ClrAtRxBuf();//清空缓存   
    sprintf((char *)IpStart,"AT+CIPSTART=\"TCP\",\"%s\",%d",IpAddr, port);   
    printf("%s\r\n",IpStart);//
    SendAtCmd((uint8_t *)IpStart,strlen((const char *)IpStart));   
    HAL_Delay(1500);   
    if(strstr((const char *)AT_RX_BUF, (const char *)"OK") == NULL)   
    {   
        return -1;   
    }   
    return 0;  	
}


//ESP8266建立TCP连接  -----4

int8_t ESP8266_IpSend(char *IpBuf, uint8_t len)
{
  uint8_t TryGo = 0; 
  int8_t error = 0;   
  uint8_t IpSend[MAX_AT_TX_LEN];   
  memset(IpSend, 0x00, MAX_AT_TX_LEN);//清空缓存   
  ClrAtRxBuf();//清空缓存   
  sprintf((char *)IpSend,"AT+CIPSEND=%d",len);   
  printf("%s\r\n",IpSend);/
  SendAtCmd((uint8_t *)IpSend,strlen((const char *)IpSend));   
  HAL_Delay(3);   
  if(strstr((const char *)AT_RX_BUF, (const char *)"OK") == NULL)  
  {   
      return -1;   
  }   
  ClrAtRxBuf();//清空缓存   
  SendStrLen((uint8_t *)IpBuf, len);   
  printf("%s\r\n",IpBuf);//
  for(TryGo = 0; TryGo<60; TryGo++)//最多等待时间 100*60=6000ms   
 {   
     if(strstr((const char *)AT_RX_BUF, (const char *)"SEND OK") == NULL) 
     {   
         error = -2;   
     }   
     else   
     {   
         error = 0;   
         break;   
     }   
     HAL_Delay(100);   
 }   
 return error; 	
}


//连接到服务器  -----5

int8_t ConnectToServer(char *DeviceID, char *SecretKey)
{
	uint8_t TryGo = 0;
	int8_t error = 0;
	uint8_t TxetBuf[MAX_AT_TX_LEN];
	memset(TxetBuf,0x00,MAX_AT_TX_LEN);//清空缓存
	for(TryGo = 0; TryGo<3; TryGo++)
	{
		if(ESP8266_SetStation() == 0)//设置WiFi通讯模块工作模式
		{
			error = 0;
			break;
		}
		else
		{
			error = -1;
		}
	}
	if(error < 0)
	{
		return error;
	}
	for(TryGo = 0; TryGo<3; TryGo++)
	{
		if(ESP8266_SetAP((char *)WIFI_AP, (char *)WIFI_PWD) == 0)//设置热点名称和密码
		{
			error = 0;
			break;
		}
		else
		{
			error = -2;
		}
	}
	if(error < 0)
	{
		return error;
	}
	for(TryGo = 0; TryGo<3; TryGo++)
	{
		if(ESP8266_IpStart((char *)SERVER_IP,SERVER_PORT) == 0)//连接服务器IP地址,端口:120.77.58.34,8600
		{
			error = 0;
			break;
		}
		else
		{
			error = -3;
		}
	}
	if(error < 0)
	{
		return error;
	}
	
	sprintf((char *)TxetBuf,"{\"t\":1,\"device\":\"%s\",\"key\":\"%s\",\"ver\":\"v0.0.0.0\"}",DeviceID,SecretKey);
	//printf("%s\r\n",TxetBuf);
	if(ESP8266_IpSend((char *)TxetBuf, strlen((char *)TxetBuf)) < 0)
	{//发送失败
		error=-4;
	}
	else
	{//发送成功
		for(TryGo = 0; TryGo<50; TryGo++)//最多等待时间50*10=500ms
		{
			if(strstr((const char *)AT_RX_BUF, (const char *)"\"status\":0") == NULL)//检查响应状态是否为握手成功
			{
				error = -5;
			}
			else
			{
				error = 0;
				break;
			}
			HAL_Delay(10);
		}
	}
	
	return error;
}

//发送传感数据到服务器 -----6

int8_t ESP8266_SendSensor(uint8_t sensor, char *TimeStr)
{
	uint8_t TryGo = 0;
	int8_t error = 0;
	uint8_t TxetBuf[MAX_AT_TX_LEN];
	memset(TxetBuf,0x00,MAX_AT_TX_LEN);//清空缓存
	sprintf((char *)TxetBuf,"{\"t\":3,\"datatype\":2,\"datas\":{\"alarm\":{\"%s\":%d},\"temp\":{\"%s\":%d}},\"msgid\":001}",TimeStr,sensor,TimeStr,sensor+1);
	//printf("%s\r\n",TxetBuf);
	if(ESP8266_IpSend((char *)TxetBuf, strlen((char *)TxetBuf)) < 0)
	{//发送失败
		error=-1;
	}
	else
	{//发送成功
		for(TryGo = 0; TryGo<50; TryGo++)//最多等待时间50*10=500ms
		{
			if(strstr((const char *)AT_RX_BUF, (const char *)"\"status\":0") == NULL)//检查响应状态是否为"上报成功"
			{
				error = -1;
			}
			else
			{
				error = 0;
				break;
			}
			HAL_Delay(10);
		}
	}
	return error;
}




4、解析云平台数据函数

//解析服务器数据-----7

uint8_t ESP8266_GetIpData(uint8_t *AtRxBuf, char *GetIpData)
{
	char *Point = NULL;
	uint8_t len = 0;
	
	Point = strstr((const char *)AtRxBuf, (const char *)"+IPD,");
	if(Point != NULL)//检查模块收到TCP/IP数据包?
	{
		len=(Point[5]-'0')*10+Point[6]-'0';//这里IP数据长度不会超过100,故可以按“个位”和“十位”计算收到的IP数据长度
		Point = strstr((const char *)AtRxBuf, (const char *)":")+1;
		memcpy(GetIpData, Point, len);
		GetIpData[len]='\0';
		printf("收到IP数据:%s\r\n",GetIpData);///
		printf("收到IP数据长度=%d\r\n",len);///
	}
	
	return (len);
}

//对服务器下发的命令进行判断处理-----8
void USER_DataAnalysisProcess(char *RxBuf)
{
	char *cmdid = NULL;
	uint8_t TxetBuf[128];
	if(strstr((const char *)RxBuf, (const char *)PING_REQ) != NULL)//心跳请求?
	{
		if(ESP8266_IpSend((char *)PING_RSP, strlen((const char *)PING_RSP)) < 0)//响应心跳
		{//发送失败
			printf("发送心跳包失败!\r\n");
		}
		else
		{
			printf("心跳包!\r\n");
		}
	}
	else if(strstr((const char *)RxBuf, (const char *)"\"t\":5") != NULL)//命令请求?
	{
		if(strstr((const char *)RxBuf, (const char *)"\"apitag\":\"defense\"") != NULL)//布防/撤防请求
		{
			memset(TxetBuf,0x00,128);//清空缓存
			if((strstr((const char *)RxBuf, (const char *)"\"data\":1") != NULL))//布防
			{
				printf("布防!\r\n");
				;//...
				;//...
				;//...
				cmdid = USER_GetJsonValue((char *)RxBuf, (char *)"cmdid");
				sprintf((char *)TxetBuf,"{\"t\":6,\"cmdid\":%s,\"status\":0,\"data\":1}",cmdid);
				//printf("%s\r\n",TxetBuf);
				if(ESP8266_IpSend((char *)TxetBuf, strlen((char *)TxetBuf)) < 0)
				{//发送失败
					printf("发送响应失败!\r\n");
				}
			}
			else if((strstr((const char *)RxBuf, (const char *)"\"data\":0") != NULL))//撤防
			{
				printf("撤防!\r\n");
				;//...
				;//...
				;//...
				cmdid = USER_GetJsonValue((char *)RxBuf, (char *)"cmdid");
				sprintf((char *)TxetBuf,"{\"t\":6,\"cmdid\":%s,\"status\":0,\"data\":0}",cmdid);
				//printf("%s\r\n",TxetBuf);
				if(ESP8266_IpSend((char *)TxetBuf, strlen((char *)TxetBuf)) < 0)
				{//发送失败
					printf("发送响应失败!\r\n");
				}
			}
		}
		else if(strstr((const char *)RxBuf, (const char *)"\"apitag\":\"ctrl\"") != NULL)//开锁/关锁请求
		{
			memset(TxetBuf,0x00,128);//清空缓存
			if((strstr((const char *)RxBuf, (const char *)"\"data\":1") != NULL))//开锁
			{
				printf("开锁!\r\n");
				;//...
				;//...
				;//...
				cmdid = USER_GetJsonValue((char *)RxBuf, (char *)"cmdid");
				sprintf((char *)TxetBuf,"{\"t\":6,\"cmdid\":%s,\"status\":0,\"data\":1}",cmdid);
				//printf("%s\r\n",TxetBuf);
				if(ESP8266_IpSend((char *)TxetBuf, strlen((char *)TxetBuf)) < 0)
				{//发送失败
					printf("发送响应失败!\r\n");
				}
				lock=1;
			}
			else if((strstr((const char *)RxBuf, (const char *)"\"data\":0") != NULL))//关锁
			{
				printf("关锁!\r\n");
				;//...
				;//...
				;//...
				cmdid = USER_GetJsonValue((char *)RxBuf, (char *)"cmdid");
				sprintf((char *)TxetBuf,"{\"t\":6,\"cmdid\":%s,\"status\":0,\"data\":0}",cmdid);
				//printf("%s\r\n",TxetBuf);
				if(ESP8266_IpSend((char *)TxetBuf, strlen((char *)TxetBuf)) < 0)
				{//发送失败
					printf("发送响应失败!\r\n");
				}
			}
		}
	}
}

五、工程修改

由于代码量大,作为上课学生,只需要按照下面教程在我下发的工程基础上进行修改程序即可。

1、在CloudReference.h  修改wifi名称和密码

2、对云平台下发命令进行处理

    在stm32App.c 文件void USER_DataAnalysisProcess(char *RxBuf)函数中对下发命令做相应处理

方法:上面代码段是对云平台LED1下发的指令进行相应的处理:当云平台点击"开",则它会下发数据{"apitag":"LED1","cmdid":"96c80b17-a9d9-4169-9a22-a7ad07fd8e2f","data":1,"t":5} ,单片机收到后作打开开发板LED1操作;当云平台点击"关",则它会下发数据{"apitag":"LED1","cmdid":"3b698d9a-34fc-4448-b707-fec5de1da636","data":0,"t":5},单片机收到后作熄灭开发板LED1操作。如果对其它3个LED灯的命令解析,我们可以复制一份“else if”代码块,接在这代码块后。

五、实验效果

六、仿真实现


总结

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1675607.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

VLAN 综合实验

一、实验拓扑 二、实验需求 1.PC1和PC3所在接口为access&#xff0c;属于vlan2&#xff1b; PC2/4/5/6处于同一网段&#xff0c;其中PC2可以访问PC4/5/6; 2.PC5不能访问PC6; 3.PC1/3与PC2/4/5/6不在同一网段&#xff1b; 4.所有PC通过DHCP获取IP地址&#xff0c;且PC1/3可以…

《Python编程从入门到实践》day28

# 昨日知识点回顾 安装Matplotlib 绘制简单的折线图 # 今日知识点学习 15.2.1 修改标签文字和线条粗细 # module backend_interagg has no attribute FigureCanvas. Did you mean: FigureCanvasAgg? # 解决办法&#xff1a;matplotlib切换图形界面显示终端TkAgg。 #…

SpringBoot自动装配(二)

近日&#xff0c;余溺于先贤古哲之文无法自拔。虽未明其中真意&#xff0c;但总觉有理。遂抄录一篇以供诸君品鉴——公孙鞅曰&#xff1a;“臣闻之&#xff1a;‘疑行无名&#xff0c;疑事无功。’君亟定变法之虑&#xff0c;殆无顾天下之议之也。且夫有高人之行者&#xff0c;…

游戏数值策划关卡策划文案策划系统策划及游戏运营干货

1.《游戏新手村》免费电子书 我2007年开始做网络游戏&#xff0c;后面又做过网页游戏和手机游戏。当时市面上关于游戏策划和运营的书籍屈指可数&#xff0c;于是我就想着要不我写一本吧&#xff0c;然后2014年10月开始撰写。关于本书的更多信息可查看这篇文章>> 游戏新手…

45.WEB渗透测试-信息收集-域名、指纹收集(7)

免责声明&#xff1a;内容仅供学习参考&#xff0c;请合法利用知识&#xff0c;禁止进行违法犯罪活动&#xff01; 内容参考于&#xff1a; 易锦网校会员专享课 上一个内容&#xff1a;计算机王-CSDN博客 WEB指纹&#xff1a;Web指纹也叫web应用指纹。由于所使用的工具、技术…

蓝鹏测控:扩大出口,勇拓海外市场

蓝鹏测控自2012年成立以来&#xff0c;始终专注于工业测量仪器的研发、生产与销售。公司坚持经验与创新并存&#xff0c;长期与华北电力大学、河北大学等多所知名院校深度合作&#xff0c;拥有一支技术力量雄厚的研发团队。经过多年的努力&#xff0c;蓝鹏测控已研发出多款具有…

MYSQL中的DQL

语法&#xff1a; select 字段列表 from 表名列表 where 条件列表 group by 分组字段列表 having 分组后条件列表 order by 排序字段 limit 分页参数 条件查询 语法&#xff1a; 查询多个字段&#xff1a;select 字段1&#xff0c;字段2 from表名 查询所有字段&#xff1a…

【计算机毕业设计】基于SSM+Vue的线上旅行信息管理系统【源码+lw+部署文档+讲解】

目录 1 绪论 1.1 研究背景 1.2 设计原则 1.3 论文组织结构 2 系统关键技术 2.1JSP技术 2.2 JAVA技术 2.3 B/S结构 2.4 MYSQL数据库 3 系统分析 3.1 可行性分析 3.1.1 技术可行性 3.1.2 操作可行性 3.1.3 经济可行性 3.1.4 法律可行性 3.2系统功能分析 3.2.1管理员功能分析 3.2.…

PCie协议之-TLP Header详解(一)

✨前言&#xff1a; 在PCIe通信过程中&#xff0c;事务层数据包&#xff08;Transaction Layer Packets&#xff0c;简称TLP&#xff09;扮演着非常重要的角色。TLP用于在设备之间传递数据和控制信息&#xff0c;它们是PCIe的基本信息传输单元。 TLP可分为几个部分&#xff0c…

【平衡二叉树】AVL树(双旋)

&#x1f389;博主首页&#xff1a; 有趣的中国人 &#x1f389;专栏首页&#xff1a; C进阶 &#x1f389;其它专栏&#xff1a; C初阶 | Linux | 初阶数据结构 小伙伴们大家好&#xff0c;本片文章将会讲解AVL树的左双选和右双旋的相关内容。 如果看到最后您觉得这篇文章写…

Qt学习笔记1.3.3QtCore-隐式共享

文章目录 概述隐式共享细节类列表 Qt中的许多c类使用隐式数据共享来最大化资源使用并最小化复制。隐式共享类作为参数传递时既安全又高效&#xff0c;因为只传递指向数据的指针&#xff0c;并且只有当函数写入数据时才会复制数据&#xff0c;即写时复制(copy-on-write)。 概述 …

keepalived双机热备超详细入门介绍

keepalived 一、keepalived入门介绍 1.keepalived简介 2.keepalived服务的三个重要功能 2.1.管理LVS负载均衡软件 2.2.实现对LVS集群节点健康检查功能 2.3.作为系统网络服务的高可用功能 3.keepalived高可用故障切换转移原理 4.keepalived安装及主配置文件介绍 …

[BJDCTF 2020]easy_md5、[HNCTF 2022 Week1]Interesting_include、[GDOUCTF 2023]泄露的伪装

目录 [BJDCTF 2020]easy_md5 ffifdyop [SWPUCTF 2021 新生赛]crypto8 [HNCTF 2022 Week1]Interesting_include php://filter协议 [GDOUCTF 2023]泄露的伪装 [BJDCTF 2020]easy_md5 尝试输入一个1&#xff0c;发现输入的内容会通过get传递但是没有其他回显 观察一下响应…

【经验总结】超算互联网服务器 transformers 加载本地模型

1. 背景 使用 超算互联网 的云服务&#xff0c;不能连接外网&#xff0c;只能把模型下载到本地&#xff0c;再上传上去到云服务。 2. 模型下载 在 模型中 https://huggingface.co/models 找到所需的模型后 点击下载 config.json pytorch_model.bin vocab.txt 3. 上传模型文…

【数据可视化01】matplotlib实例3之数据统计

目录 一、引言二、实例介绍1.百分位数为横条形图2.箱线图定制化3.带有自定义填充颜色的箱线图4.箱线图5.箱线图和小提琴图6.二维数据集的置信椭圆 一、引言 matplotlib库 可以用来创建各种静态、动态、交互式的图形&#xff0c;并广泛应用于数据分析和数据可视化领域。 二、实…

C#中json数据序列化和反序列化的最简单方法(C#对象和字符串的相互转换)

文章目录 将C#对象转换为json字符串Newtonsoft模块的安装用Newtonsoft将对象转换为json字符串 将json字符串转换为C#对象 将C#对象转换为json字符串 本介绍将基于C#中的第三方库Newtonsoft进行&#xff0c;因此将分为Newtonsoft模块的安装和使用两部分。该模块的优势在于只需要…

STL----push,insert,empalce

push_back和emplace_back的区别 #include <iostream> #include <vector>using namespace std; class testDemo { public:testDemo(int n) :num(n) {cout << "构造函数" << endl;}testDemo(const testDemo& other) :num(other.num) {cou…

C# 下载安装,使用OfficeOpenXml

下载安装OfficeOpenXml模块 using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.IO; using System.Linq; using System.Reflection.Emit; using System.Text; using System.Text.RegularEx…

智能EDM邮件群发工具哪个好?

企业之间的竞争日益激烈&#xff0c;如何高效、精准地触达目标客户&#xff0c;成为每个市场战略家必须面对的挑战。在此背景下&#xff0c;云衔科技凭借其前沿的AI技术和深厚的行业洞察&#xff0c;匠心推出了全方位一站式智能EDM邮件营销服务平台&#xff0c;重新定义了邮件营…

Docker 使用 Fedora 镜像

Fedora 在 Docker 中的使用也非常简单&#xff0c;直接使用命令 docker run -it fedora:latest bash 就可以 pull 到本地的容器中并且运行。 C:\Users\yhu>docker run -it fedora:latest bash Unable to find image fedora:latest locally latest: Pulling from library/fed…