STM32通过esp8266连接WiFi接入MQTT服务器

2023-11-01

上文我们讲到如何搭建本地MQTT服务器http://t.csdn.cn/aHNcO,现在介绍如何通过stm32连接MQTT

一.首先我们初始化esp8266这里我们使用的是USART4与其通信代码如下

void UART4_Init(uint32_t bound)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;
	
	 
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART4, ENABLE);	//使能UART4,GPIOA时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
	
	USART_DeInit(UART4);  //复位串口4
	
	//UART4_TX   PC.10 
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; 
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;	//复用推挽输出
	GPIO_Init(GPIOC, &GPIO_InitStructure); //初始化PC10
   
	//UART4_RX	  PC.11
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
	GPIO_Init(GPIOC, &GPIO_InitStructure);  //初始化PC11

	//USART 初始化设置
	USART_InitStructure.USART_BaudRate = bound;	//设置波特率,一般设置为9600;
	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(UART4, &USART_InitStructure); //初始化串口
	USART_ITConfig(UART4, USART_IT_RXNE, ENABLE);//开启中断
	USART_Cmd(UART4, ENABLE);                    //使能串口 


	TIM7_Int_Init(100-1,7200-1);		//10ms 为了判断是不是一串数据后文有解释

	TIM_Cmd(TIM7,ENABLE);			//
}

二.通过数据间隔时间来判断是否是一串数据如果间隔时间大于30ms则判定为不是一串数据,接收缓冲器清零。 代码如下!

//定时器7中断服务程序		    
void TIM7_IRQHandler(void)
{ 	
	if (TIM_GetITStatus(TIM7, TIM_IT_Update) != RESET)//是更新中断
	{
	
		TIM_ClearITPendingBit(TIM7, TIM_IT_Update  );  //清除TIM7更新中断标志    
	    if(F_UART4_RX_RECEIVING)//正在接收串口数据
		{
			UART4_RX_TIMEOUT_COUNT++;//串口超时计数
			if(UART4_RX_TIMEOUT_COUNT>3)//数据接收间隔超过30ms
			{//串口接收完成或结束
				F_UART4_RX_RECEIVING=0;
				UART4_RX_TIMEOUT_COUNT=0;
				F_UART4_RX_FINISH=1;
			}
		}
	}	    
}
 

//定时器溢出时间计算方法:Tout=((arr+1)*(psc+1))/Ft us.
//Ft=定时器工作频率,单位:Mhz 
//通用定时器中断初始化
//这里始终选择为APB1的2倍,而APB1为36M
//arr:自动重装值。
//psc:时钟预分频数		 
void TIM7_Int_Init(u16 arr,u16 psc)
{	
	NVIC_InitTypeDef NVIC_InitStructure;
	TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;

	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM7, ENABLE);//TIM7时钟使能    
	
	//定时器TIM7初始化
	TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值	
	TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值
	TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割:TDTS = Tck_tim
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式
	TIM_TimeBaseInit(TIM7, &TIM_TimeBaseStructure); //根据指定的参数初始化TIMx的时间基数单位
 
	TIM_ITConfig(TIM7,TIM_IT_Update,ENABLE ); //使能指定的TIM7中断,允许更新中断
	
	TIM_Cmd(TIM7,ENABLE);//开启定时器7
	
	NVIC_InitStructure.NVIC_IRQChannel = TIM7_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0 ;//抢占优先级0
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;		//子优先级2
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;			//IRQ通道使能
	NVIC_Init(&NVIC_InitStructure);	//根据指定的参数初始化VIC寄存器
	
}

三.初始化esp8266后我们就可以连接WiFi及mqtt了

 首先我们将esp8266设置为station模式,如果返回ok则设置成功

代码如下:

#define AT_CWMODE	"AT+CWMODE=1" //设置为“station”模式
int8_t ESP8266_SetStation(void)
{
	ClrAtRxBuf();//清空缓存
	SendAtCmd((uint8_t *)AT_CWMODE,strlen(AT_CWMODE));
	delay_ms(100);
	if(strstr((const char *)AT_RX_BUF, (const char *)"OK") == NULL)
	{
		return -1;
	}
	return 0;
}

四.设置成功之后就可以连接WiFi(可以是路由器也可以是手机或电脑开热点)

代码如下:

/*******************************************************************
*函数:int8_t ESP8266_SetAP(void)
*功能:设置ESP8266要连接的热点名称和密码
*输入:char *wifi-热点名称 char *pwd-热点密码
*输出:
		return = 0 ,sucess
		return < 0 ,error
*特殊说明:
*******************************************************************/
#define WIFI_AP		"dmx"//WiFi热点名称       
#define WIFI_PWD	"88888888"	//WiFi密码

int8_t ESP8266_SetAP(void)
{
	uint8_t AtCwjap[MAX_AT_TX_LEN];
	memset(AtCwjap, 0x00, MAX_AT_TX_LEN);//清空缓存
	ClrAtRxBuf();//清空缓存
	sprintf((char *)AtCwjap,"AT+CWJAP=\"%s\",\"%s\"",WIFI_AP, WIFI_PWD	);
	SendAtCmd((uint8_t *)AtCwjap,strlen((const char *)AtCwjap));
	delay_ms(5500);
	if(strstr((const char *)AT_RX_BUF, (const char *)"OK") == NULL)
	{
		return -1;
	}
	return 0;
}

五.现在就已经成功连接WiFi了下一步连接本地mqtt服务器(上篇博客我教大家如何搭建的)

#define SERVER_PC_IP	"172.16.40.36"	//服务器IP地址
#define SERVER_PC_PORT	1883			//服务器端口号   
int8_t ESP8266_IpStart(void)
{
	uint8_t IpStart[MAX_AT_TX_LEN];
	memset(IpStart, 0x00, MAX_AT_TX_LEN);//清空缓存
	ClrAtRxBuf();//清空缓存
	
	/**************配置MQTT_USER信息***************/
	//AT+MQTTUSERCFG=0,1,"用户ID","账号","密码",0,0,""
	                       //AT+MQTTUSERCFG=0,1,\"M3\",\"\",\"\",0,0,\"\"
	sprintf((char *)IpStart,"AT+MQTTUSERCFG=0,1,\"M3\",\"\",\"\",0,0,\"\"");
	SendAtCmd((uint8_t *)IpStart,strlen((const char *)IpStart));
	delay_ms(1500);
	printf("IpStart-USER_Config: %s\r\n", (char *)AT_RX_BUF);
	if(strstr((const char *)AT_RX_BUF, (const char *)"OK") == NULL)
	{
		/******断开连接*****/
		memset(IpStart, 0x00, MAX_AT_TX_LEN);//清空缓存
		ClrAtRxBuf();//清空缓存
		
		//AT+MQTTCLEAN=0
		sprintf((char *)IpStart,"AT+MQTTCLEAN=0");
		
		SendAtCmd((uint8_t *)IpStart,strlen((const char *)IpStart));
		
		return -1;
	}
	
	/**************建立MQTT连接***************/
	memset(IpStart, 0x00, MAX_AT_TX_LEN);//清空缓存
	ClrAtRxBuf();//清空缓存
	
	//AT+MQTTCONN=0,"服务器IP",1883,0
	//AT+MQTTCONN=0,"172.16.40.36",1883,0
	sprintf((char *)IpStart,"AT+MQTTCONN=0,\"%s\",%d,0",SERVER_PC_IP, SERVER_PC_PORT	);
	
	SendAtCmd((uint8_t *)IpStart,strlen((const char *)IpStart));
	delay_ms(1500);
	printf("IpStart-MQTT_Connect: %s\r\n", (char *)AT_RX_BUF);
	if(strstr((const char *)AT_RX_BUF, (const char *)"OK") == NULL)
	{
		return -2;
	}
	
	return 0;
}

六.经过以上五步就已经成功连接mqtt服务器了。现在通过命令设置自己为订阅者

int8_t ESP8266_MQTT_Sub(char *topic) //主题自己设置
{
	int8_t error = 0;
	uint8_t IpSend[MAX_AT_TX_LEN];
	memset(IpSend, 0x00, MAX_AT_TX_LEN);//清空缓存
	ClrAtRxBuf();//清空缓存
	
	
	//AT+MQTTSUB=0,M3",0
	sprintf((char *)IpSend,"AT+MQTTSUB=0,\"%s\",1", topic);
	SendAtCmd((uint8_t *)IpSend,strlen((const char *)IpSend));
	delay_ms(1500);
	printf("MQTT_Sub_Ack: %s\r\n",AT_RX_BUF);
	if(strstr((const char *)AT_RX_BUF, (const char *)"OK") == NULL)
	{
		return -4;
	}
	
	return error;
}

在这里我们通过mqtt.fx同样连接本地搭建的服务器,作为一个发布者发送消息stm32就能收到了。不过此处还没写收到信息的代码

七.stm32作为发布者者代码,这边你可以开一个mqtt.fx订阅相同的主题就能收到消息了

int8_t ESP8266_MQTT_Pub(char *IpBuf, uint8_t len, uint8_t qos)//信息 消息长度 以及qos(百度)
{
	uint8_t TryGo = 0;
	int8_t error = 0;
	uint8_t IpSend[MAX_AT_TX_LEN];
	memset(IpSend, 0x00, MAX_AT_TX_LEN);//清空缓存
	ClrAtRxBuf();//清空缓存
	/************设置为MQTT_Binary发送模式************/
/*   注意----------dmx为发布的主题-----------*/
	sprintf((char *)IpSend,"AT+MQTTPUBRAW=0,\"dmx\",%d,%d,0", len, qos);
	//printf("%s\r\n",IpSend);
	SendAtCmd((uint8_t *)IpSend,strlen((const char *)IpSend));
	delay_ms(100);
	//注意--如果断开连接或者怎么样,这一步ESP8266就会返回ERROR
	if(strstr((const char *)AT_RX_BUF, (const char *)"OK") == NULL)
	{
		printf("MQTT_Pub Fail:%s\r\n", AT_RX_BUF);
		MQTTSendErrorTimes++;
		return -1;
	}
	
	ClrAtRxBuf();//清空缓存
	
	//以二进制数据形式发送字符串
	SendAtCmd((uint8_t *)IpBuf, len);
	printf("MQTT_Pub: %s\r\n", IpBuf);
	if(qos == 0){
		return 0;
	}
	
	//等待qos回执处理
	delay_ms(100);
	if(strstr((const char *)AT_RX_BUF, (const char *)"OK") == NULL)
	{
		MQTTSendErrorTimes++;
		return -2;
	}
	return error;
}

八.到这里,完成的步骤已经完成,由于篇幅有限,很多细节也讲不完,如果有什么问题可以评论区留言,最后我附一个搭建好的mqtt的一个简易智能家居!可以读取各种传感器器数据,如温湿度,光照,烟雾溶度等上传给服务器,风扇 PWM灯也可以被服务器传来的数据控制。

 源码在博主的资源中可以免费下载,点点关注就行,谢谢大家!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

STM32通过esp8266连接WiFi接入MQTT服务器 的相关文章

随机推荐

  • Android Studio 新建drawable-hdpi、drawable-mdpi等

    Android Studio 新建drawable hdpi drawable mdpi 在不同的模式 Project Android 的文件夹中查看文件夹 如果文件夹丢失 您可以轻松添加它们 1 在 res 文件夹上右键 New gt A
  • C++ VScode配置libtorch,并调用PyTorch模型

    C VS配置libtorch 调用TorchScript模型 获取pytorch模型 转成C 模型 下载配置libtorch库 VS 1 首先是下载libtorch库 2 VS中配置 C 调用模型 获取pytorch模型 将训练好的模型保存
  • discuz手机客户端java,Discuz 触屏手机版支持视频播放的方法

    if defined IN MOBILE if strpos msglower media FALSE message preg replace media w s url message if strpos msglower audio
  • WEB安全之:Oracle 数据库 SQL 注入

    郑重声明 本笔记编写目的只用于安全知识提升 并与更多人共享安全知识 切勿使用笔记中的技术进行违法活动 利用笔记中的技术造成的后果与作者本人无关 倡导维护网络安全人人有责 共同维护网络文明和谐 SQL 注入 Oracle 数据库 1 Orac
  • as汇编命令(来自 深入理解Linux内核)

    as汇编命令 来自 深入理解Linux内核 as汇编命令 汇编命令是指示汇编器操作方式的伪指令 汇编命令用于要求汇编器为变量分配空间 确定程序开始地址 指定当前汇编的区 修改位置计数器值等 所有汇编命令的名称都以 开始 其余是字符 并且大小
  • 基于R语言的数据可视化:平行坐标轴图

    基于R语言的数据可视化 平行坐标轴图 数据可视化是数据分析过程中重要的一环 它能够帮助我们更直观地理解数据之间的关系 趋势和模式 在R语言中 有许多包可以用于实现不同类型的数据可视化 其中 GGally包提供了丰富的功能 可以用来绘制多变量
  • 工业机器人三点工具定位法图文_工业机器人工具坐标系的设置

    何淼 摘要 该文以FANUC工业机器人为例 从工具坐标系设置的意义出发 分析了不同机器人设置工具坐标系的方法 成功建立了机器人新的工具坐标系 为机器人精确的运动控制奠定基础 关键词 工业机器人 坐标系 TCP 中图分类号 TP319 文献标
  • 垂直同步

    vblank时间 显示器显示一帧的时间 显卡或芯片输出的图像数据写在后缓存里 屏幕读取前缓存的图像数据并显示 后缓存数据写入完毕后 前后缓存进行交换 如果前缓存的图片写入速度与屏幕读取图像的刷新率不匹配会发生画面撕裂 解决办法 垂直同步 当
  • JAVA中那些令人眼花缭乱的锁

    一 开局一张图带你了解java相关的锁 二 乐观锁和悲观锁 1 悲观锁 悲观锁对应于生活中悲观的人 悲观的人总是想着事情往坏的方向发展 举个生活中的例子 假设厕所只有一个坑位了 悲观锁上厕所会第一时间把门反锁上 这样其他人上厕所只能在门外等
  • mysql 优化杂记

    慢日志分析 SELECT user id AS userId charm AS num FROM db charm WHERE user id NOT IN ORDER BY num DESC userId LIMIT 性能分析 not i
  • Python 爬虫逆向

    Python 爬虫逆向是指使用 Python 语言来编写爬虫程序 用于爬取网站的信息 爬虫逆向一般指的是通过分析网站的网页代码和加载流程 来确定网站信息获取的方式 并使用爬虫程序来模拟这种方式 从而获取网站的信息 爬虫逆向的主要目的是通过自
  • 为什么spark读取本地的json文件会自动去hdfs上去找?读取不到本地的文件

    问题描述 遇到的问题如上图所示 我在spark中读取的json文件明明是集群本地的文件 可是他偏偏就自作聪明去了hdfs上面去找我的文件 那肯定会报错啊 我hdfs上怎么可能有这个文件嘛 原因 我在spark中的运行环境配置了yarn关联
  • 协调器是如何获取终端的IEEE地址并自动对其分配网络短地址呢

    协调器是如何获取终端的IEEE地址并自动对其分配网络短地址呢 字号 订阅 协调器是如何获取终端的IEEE地址并自动对其分配网络短地址呢 猜想如下 终端上电后稳定后就开始寻找周围是否存在网络 向周围发射广播 该广播内容包含自己的身份信息 即M
  • Koa2框架中使用bcrypt实现密码加密

    bcrypt是一个用于密码哈希的库 它使用了单向哈希函数 因此即使在数据库中存储了哈希后的密码 也不容易还原出原始密码 下面是在Koa 2中使用bcrypt的基本步骤 使用npm npm install bcrypt 使用yarn yarn
  • 手把手教你mysql基本操作

    MySQL的基本操作 首先我们要知道怎么打开Mysql客户端 打开开始界面 这两个都是Mysql的客户端 随便打开哪个都可以 如果设置了密码的就输入自己的密码 没有设置密码的则不需要输入 直接就可以进行操作 输入密码正确后界面如下 接下来我
  • java 简述类的封装性、继承性、多态性

    一 什么是封装性 继承性 多态性 封装性 通俗说就是一个盒子 多个对象 功能 组件等装在一个盒子里 内部具体是什么不知道 用到它时 使用特定方法或功能去调用它 即声明一个变量 其属性值是private 不能给其变量直接赋值 但可以通过方法构
  • 利用尾插法建立单链表

    PTA 5 3本题目要求利用尾插法建立单链表 输入格式 输入数据为若干正整数 最后以 1表示结尾 1不算在序列内 不要处理 所有数据之间用空格分隔 输入样例 1 2 3 4 5 6 7 8 9 1 输出样例 1 2 3 4 5 6 7 8
  • ❤️UNITY实战进阶-三维AABB包围盒详解-6

    前言 碰撞检测问题在虚拟现实 计算机辅助设计与制造 游戏 机器人等方面都有着广泛的应用 而包围盒算法是进行碰撞检测的重要方法之一 而常见的包围盒有 AABB包围盒 Axis aligned bounding box 包围球 Sphere O
  • 小程序创建公共js获取接口数据,全局调用

    新建一个js文件 let app getApp function getImageurl return new Promise function resolve reject wx request url 接口地址 method get d
  • STM32通过esp8266连接WiFi接入MQTT服务器

    上文我们讲到如何搭建本地MQTT服务器http t csdn cn aHNcO 现在介绍如何通过stm32连接MQTT 一 首先我们初始化esp8266这里我们使用的是USART4与其通信代码如下 void UART4 Init uint3