使用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.3V | VCC |
| RX | TX |
| TX | RX |
| GND | GND |

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.硬件连接

|---------------|---------|
| STM32F103C8T6 | ESP8266 |
| 5V | VCC |
| GND | GND |
| PA9 | RX |
| PA10 | TX |

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

2. 串口文件

usart1.c

cpp 复制代码
#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.9
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9
  GPIO_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;//PA10
  GPIO_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 ;//抢占优先级3
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;		//子优先级3
	NVIC_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); //初始化串口1
  USART_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

cpp 复制代码
#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三要素要根据自己的阿里云进行修改。

cpp 复制代码
#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
	
	//重启ESP
	printf("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);
	//MQTTID
	printf("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

cpp 复制代码
#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

cpp 复制代码
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的原因是我还没有称重传感器~~

相关推荐
青牛科技-Allen4 分钟前
GC3910S:一款高性能双通道直流电机驱动芯片
stm32·单片机·嵌入式硬件·机器人·医疗器械·水泵、
白鱼不小白2 小时前
stm32 USART串口协议与外设(程序)——江协教程踩坑经验分享
stm32·单片机·嵌入式硬件
S,D3 小时前
MCU引脚的漏电流、灌电流、拉电流区别是什么
驱动开发·stm32·单片机·嵌入式硬件·mcu·物联网·硬件工程
芯岭技术5 小时前
PY32F002A单片机 低成本控制器解决方案,提供多种封装
单片机·嵌入式硬件
youmdt6 小时前
Arduino IDE ESP8266连接0.96寸SSD1306 IIC单色屏显示北京时间
单片机·嵌入式硬件
嘿·嘘6 小时前
第七章 STM32内部FLASH读写
stm32·单片机·嵌入式硬件
Meraki.Zhang6 小时前
【STM32实践篇】:I2C驱动编写
stm32·单片机·iic·驱动·i2c
几个几个n9 小时前
STM32-第二节-GPIO输入(按键,传感器)
单片机·嵌入式硬件
安 当 加 密11 小时前
多云密钥统一管理实战:CKMS对接阿里云/华为云密钥服务
数据库·阿里云·华为云
Despacito0o12 小时前
ESP32-s3摄像头驱动开发实战:从零搭建实时图像显示系统
人工智能·驱动开发·嵌入式硬件·音视频·嵌入式实时数据库