欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 汽车 > 维修 > 使用STM32F103C8T6和ESP8266链接阿里云

使用STM32F103C8T6和ESP8266链接阿里云

2025/2/13 2:28:05 来源:https://blog.csdn.net/2201_75342985/article/details/140178373  浏览:    关键词:使用STM32F103C8T6和ESP8266链接阿里云

一、项目简介

        基于 STM32F103C8T6 单片机和 ESP8266 Wi-Fi 模块,旨在实现通过 Wi-Fi 连接阿里云物联网平台,进行数据上传和远程控制

  • STM32F103C8T6:作为核心控制单元,负责系统的运算、数据处理和与外设的交互。STM32F103C8T6 具有强大的计算能力、丰富的外设接口和稳定的性能,适合嵌入式系统的开发。
  • ESP8266 Wi-Fi 模块:负责与阿里云物联网平台进行网络通信。ESP8266 是一个低功耗的 Wi-Fi 模块,通过 UART 与 STM32F103C8T6 进行连接,并通过 Wi-Fi 将数据传输到阿里云。
  • 外部传感器/执行器(可选):根据应用场景,用户可以选择连接温湿度传感器、光照传感器等,并通过 STM32F103C8T6 获取数据或控制执行器进行远程操作。
  • 串口通信(UART):STM32F103C8T6 与 ESP8266 通过 UART 接口进行数据传输。STM32 发送指令给 ESP8266,ESP8266 负责通过 Wi-Fi 网络与阿里云进行通信。
  • MQTT 协议:ESP8266 使用 MQTT 协议与阿里云物联网平台进行数据交互。通过 MQTT 协议,STM32 可以将传感器数据上传到阿里云,或接收来自阿里云的指令进行远程控制。

二、阿里云设置

1.通过百度搜索阿里云IOT

2.打开后进行注册登录,然后进入控制台界面 

3.新建公共实例

新建一个公共实例,地区选择离自己近的地方即可其他默认,我这边选择的是华东2(上海) 

4.然后选择新建一个产品 

5.创建产品完成后再去添加一个设备 

6.点击查看设备

然后查看三要素,把他们复制到文本文件中,后续需要使用。 

 7.点击产品进行查看

创建两个(根据自己的需求)自定义物模型

创建完成后记录下标识符后面需要用到,然后点击发布上线即可。

三、固件烧录

1.硬件连接

我这边使用的是ESP8266的nodemcu,自带CH340所以连接电源即可,如果只是最小的模块可以通过CH340连接到电脑上方式如下:

CH340 ESP8266
3.3VVCC
RXTX
TXRX
GNDGND

2.软件获取

烧录固件需要到烧录软件和一个固件,把链接放到下面自取即可。

烧录工具:通过网盘分享的文件:flash_download_tool_3.9.2_0.zip
链接: https://pan.baidu.com/s/1J93R1XedIUha_uL-9dx2pA 提取码: va4c

烧录固件:通过网盘分享的文件:1471_esp8266-at_mqtt-1m.zip
链接: https://pan.baidu.com/s/1GfZX8YfslurIw1rKer0JTw 提取码: y5yt

3.软件设置

1.解压完成后直接点击exe文件运行即可

 2.选择ESP8266和develop

3.选择固件

选择刚才下载的固件,地址填0x0,具体设置如图所示,选择自己的串口,波特率选择最大即可

4.开始烧录

我用的nodemcu不需要按任何按键都可以下载,但有其他型号的板子下载起来可能比较复杂,如正点原子的开发板需要IO1接地才可以下载,以及一些板子需要一直按着BOOT0才可以下载。

正点原子的板子下载时IO1和GND以及VCC要连接在一个电源上不可以分开连接,否则会下载失败。

5.烧录完成

烧录完成后点击reset复位就可以进行 AT指令测试了

四、AT指令测试

AT指令集 这里列举了常用的AT指令集,具体指令的意思请自行查询。

打开XCOM或者其他的串口软件,发送AT指令

1.发送AT

复位后发送AT返回OK说明通讯没有问题

2.设置波特率 

发送AT+UART=115200,8,1,0,0设置波特率

然后发送AT+UART?查看波特率是否设置成功

3.发送AT+RESTORE重新启动模块

4.发送AT+CWMODE=1 配置WIFI模式 

5.发送AT+CWJAP="SSID","SSID_password" 连接wifi

输入自己WIFI的账号密码即可,用手机热点是注意使用2.4GHz的频段,现在的手机都是5G,但是该模块不支持5G,可能会导致连接失败。

例:AT+CWJAP="UFI-EB37","1234567890"

6.发送AT+MQTTUSERCFG=0,1,"NULL","name","password",0,0,""  

这里的name就是之前复制下来的username,password就是passwd,复制粘贴过来即可

例:AT+MQTTUSERCFG=0,1,"NULL","Test&io5xsizC2D2","0620ed20f70f7bdf05637aa1b01292c2945760119bb7dd34da0aeacef84c7529",0,0,""

7.发送AT+MQTTCLIENTID=0,"ClienID"     

设置MQTT ID,要在ID信息每一个”,“前加”\“进行转义 把之前复制的clientld拿过来使用

例:

原来的ClienID为:io5xsizC2D2.Test|securemode=2,signmethod=hmacsha256,timestamp=1736230153434|需要发送的AT指令为:AT+MQTTCLIENTID=0,"io5xsizC2D2.Test|securemode=2\,signmethod=hmacsha256\,timestamp=1736216781469|"

列出两个ID请注意查看区别,方便修改自己的ID

8.发送AT+MQTTCONN=0,"域名",1883,1     

发送MQTT域名,域名获取 ,将之前的mqttHostUrl复制过来使用。

例:AT+MQTTCONN=0,"iot-06z00gjlxx4sqaa.mqtt.iothub.aliyuncs.com",1883,1

此时可以看到设备显示在线状态

9.发送AT+MQTTSUB=0,"订阅topic",1      

订阅主题,根据如图所示步骤找到订阅的topic

/io5xsizC2D2/${deviceName}/user/get,此时我们看到还需要一个devicename 

然后打开我们的设备界面就可以找到我们所需要的devicename了 

例:AT+MQTTSUB=0,"/io5xsizC2D2/Test/user/get",1

发送完成后点击设备,查看设备中的topic列表一栏,就可以看到刚才订阅的topic出现在设备上了。

10.命令下发

点击设备的topic列表 ,点击发送消息,输入123456789,然后查看我们的xcom就可以看到已经成功接收到了。

11.数据上传

发送AT+MQTTPUB=0,"发布topic","AJson格式内容",1,0    发布主题

json数据格式,{\"params\":{\"temperature\":37.5}},其中temperature为属性的标识符

例: 

 AT+MQTTPUB=0,"/sys/io5xsizC2D2/Test/thing/event/property/post","{\"params\":{\"temperature\":37.5}}",1,0

发送完成后我们可以看到阿里云成功显示温度37.5℃

12.日志查看

 选择日志服务我们可以看到所发的消息,以及可以看到发送失败时报错的代码,然后根据代码去阿里云手册中找到该错误的含义,便于排查错误。

五、串口测试

1.硬件连接

STM32F103C8T6ESP8266
5VVCC
GNDGND
PA9RX
PA10TX

使用这种小板子时记得外接电源,否则会因为电源不足而供不上电。

2. 串口文件

usart1.c

#include "sys.h"
#include "usart.h"	  #if 1
#pragma import(__use_no_semihosting)             
//标准库需要的支持函数                 
struct __FILE 
{ int handle; }; FILE __stdout;       
//定义_sys_exit()以避免使用半主机模式    
void _sys_exit(int x) 
{ x = x; 
} 
//重定义fputc函数 
int fputc(int ch, FILE *f)
{      while((USART1->SR&0X40)==0);//循环发送,直到发送完毕   USART1->DR = (u8) ch;      return ch;
}
#endif #if EN_USART1_RX   //如果使能了接收
//串口1中断服务程序
//注意,读取USARTx->SR能避免莫名其妙的错误   	
u8 USART_RX_BUF[USART_REC_LEN];     //接收缓冲,最大USART_REC_LEN个字节.
//接收状态
//bit15,	接收完成标志
//bit14,	接收到0x0d
//bit13~0,	接收到的有效字节数目
u16 USART_RX_STA=0;       //接收状态标记	  void uart_init(u32 bound){//GPIO端口设置GPIO_InitTypeDef GPIO_InitStructure;USART_InitTypeDef USART_InitStructure;NVIC_InitTypeDef NVIC_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE);	//使能USART1,GPIOA时钟//USART1_TX   GPIOA.9GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;	//复用推挽输出GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.9//USART1_RX	  GPIOA.10初始化GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//PA10GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.10  //Usart1 NVIC 配置NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;//抢占优先级3NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;		//子优先级3NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;			//IRQ通道使能NVIC_Init(&NVIC_InitStructure);	//根据指定的参数初始化VIC寄存器//USART 初始化设置USART_InitStructure.USART_BaudRate = bound;//串口波特率USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式USART_InitStructure.USART_StopBits = USART_StopBits_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(USART1, &USART_InitStructure); //初始化串口1USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启串口接受中断USART_Cmd(USART1, ENABLE);                    //使能串口1 }void USART1_IRQHandler(void)                	//串口1中断服务程序{u8 Res;if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)  //接收中断(接收到的数据必须是0x0d 0x0a结尾){Res =USART_ReceiveData(USART1);	//读取接收到的数据if((USART_RX_STA&0x8000)==0)//接收未完成{if(USART_RX_STA&0x4000)//接收到了0x0d{if(Res!=0x0a)USART_RX_STA=0;//接收错误,重新开始else USART_RX_STA|=0x8000;	//接收完成了 }else //还没收到0X0D{	if(Res==0x0d)USART_RX_STA|=0x4000;else{USART_RX_BUF[USART_RX_STA&0X3FFF]=Res ;USART_RX_STA++;if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;//接收数据错误,重新开始接收	  }		 }}   		 } 
} 
#endif	

 usart1.h

#ifndef __USART_H
#define __USART_H
#include "stdio.h"	
#include "sys.h" #define USART_REC_LEN  			200  	//定义最大接收字节数 200
#define EN_USART1_RX 			1		//使能(1)/禁止(0)串口1接收extern u8  USART_RX_BUF[USART_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.末字节为换行符 
extern u16 USART_RX_STA;         		//接收状态标记	
//如果想串口中断接收,请不要注释以下宏定义
void uart_init(u32 bound);
#endif

3.ESP8266文件

esp8266.c

里面的wifi名称密码,以及MQTT三要素要根据自己的阿里云进行修改。

#include "esp8266.h"
#include "usart.h"
#include "stm32f10x_usart.h"
#include "delay.h"
#include <stdio.h>
#include <string.h>
#include "esp8266.h"
void ESP8266_Init(void)
{
//	u16 t;  
//	u16 len;
//	u16 times=0;delay_init();       //延时函数初始化   
//NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
//uart_init(115200); //串口初始化为11520//重启ESPprintf("AT+RESTORE\r\n");delay_ms(1000);delay_ms(1000);//wifi模式设置printf("AT+CWMODE=1\r\n");delay_ms(1000);delay_ms(1000);delay_ms(1000);//wifi名称,WiFi密码printf("AT+CWJAP=\"UFI-EB37\",\"1234567890\"\r\n");delay_ms(1000);delay_ms(1000);delay_ms(1000);delay_ms(1000);delay_ms(1000);delay_ms(1000);//MQTT名称,MQTT密码printf("AT+MQTTUSERCFG=0,1,\"NULL\",\"ESP8266&io5xsNZLaxr\",\"ec2ac185df0828bd3d5f68fc840eed580ef660c88320010d71c049eeda719047\",0,0,\"\"\r\n");delay_ms(1000);delay_ms(1000);delay_ms(1000);//MQTTIDprintf("AT+MQTTCLIENTID=0,\"io5xsNZLaxr.ESP8266|securemode=2\\,signmethod=hmacsha256\\,timestamp=1735989723311|\"\r\n");delay_ms(1000);delay_ms(1000);delay_ms(1000);//MQTT域名printf("AT+MQTTCONN=0,\"iot-06z00gjlxx4sqaa.mqtt.iothub.aliyuncs.com\",1883,1\r\n");delay_ms(1000);delay_ms(1000);delay_ms(1000);//订阅消息printf("AT+MQTTSUB=0,\"/sys/io5xsNZLaxr/ESP8266/thing/deviceinfo/update\",1\r\n");delay_ms(1000);delay_ms(1000);delay_ms(1000);memset(USART_RX_BUF,0,500);USART_RX_STA=0;
}

esp8266.h

#ifndef _ESP8266_H
#define _ESP8266_H
#include "stm32f10x.h"
#include "delay.h"
#include "usart.h"void ESP8266_Init(void);
#endif

4.主函数

我这边要做一个智能秤所以上传了一个称重传感器的数据,上述连接到阿里云后上传数据只需要这句话即可:printf("AT+MQTTPUB=0,\"/sys/io5xsNZLaxr/ESP8266/thing/event/property/post\",\"{\\\"params\\\":{\\\"Weight\\\":%d}}\",1,0\r\n",weight);

main.c

int main(void)
{		NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置中断优先级分组为组2:2位抢占优先级,2位响应优先级delay_init();HX711_GPIO_Init();uart_init(115200);ESP8266_Init();		  //ESP初始化Get_Tare();OLED_Init();OLED_Clear();OLED_ShowCH(2,0,"失重-智能迷你秤");OLED_ShowCH(20,4,"重量:   0g");while(1){		Get_Weight();if(medleng == 0)                    //缓存的第1个元素,直接放入,不需要排序{ buffer[0] = weight; medleng = 1; }else                            	//插入排序算法,按从小到大的顺序排列 {  for(int i = 0; i < medleng; i ++)  {if( buffer[i] > weight) 	// 轮询到的当前元素>AD值,则交换它们的值,xd为中间变量存放位置{ xd = weight; weight = buffer[i]; buffer[i] = xd;}}buffer[medleng] = weight; 	//把轮询出较大的数放入缓存的后面.medleng++;}		if(medleng >= MEDIAN_LEN) 		    //ADC采样的数据个数达到中值滤波要求的数据个数{weight = buffer[MEDIAN];	    //最终重量取中值滤波数组的中间值medleng = 0; OLED_ShowNum(60,4,weight,4,0);printf("weight:%d g\r\n",weight);printf("AT+MQTTPUB=0,\"/sys/io5xsNZLaxr/ESP8266/thing/event/property/post\",\"{\\\"params\\\":{\\\"Weight\\\":%d}}\",1,0\r\n",weight);	delay_ms(500);}}
}

打开阿里云我们可以看到数据上传成功,都是0的原因是我还没有称重传感器~~ 

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com