stm32标准库基于esp8266的wife模块代码及使用(基于mqtt协议)

2023-10-30 17:31

本文主要是介绍stm32标准库基于esp8266的wife模块代码及使用(基于mqtt协议),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1.首先,你得搭建一个本地服务器,我用的是基于mqtt的,这个搜索一下就可以了,先进入bin目录下输入cmd,注意在bin目录下输入emqx start 可以进行开启,再bin目录下输入emqx stop 可以停止,在任意目录输入 emqx_ctl status可以查询是否开启,同时在任意目录下输入ipconfig可以查询ip地址,注意是最下面的IPv4 地址。

 

 2.后面用mqttx或者mqttfx搭建服务器

 点击新建连接

 端口写1883,服务器地址复制自己电脑查找到的,但这里要注意的是,如果你想用别人电脑连接不同wife,再通过wife模块操作你的板子,这需要搭建一个云服务器,你也可以直接用官网提供的免费的,把服务器地址改了就行。它这个新建默认端口就是官网提供的那个,名称随便输入一个就行。The Top 1 Free Public MQTT Broker | EMQ (emqx.com)

 

 3.首先esp8266的At固件库是必须有的,一般这个会自带,没有得通过工具去官网下载,我下的是安信可的AT固件汇总 | 安信可科技

 后面代码我用的是基于Mqtt固件库的,意思就是说把Mqtt固件库下到板子中去,这样子写的话代码会简单很多,也容易理解很多,当然如果你不想下Mqtt固件库,我推荐你可以看b站画卿师兄的【挽救小白第一季】STM32+8266+小程序智能家居毕设实战这个视频,我觉得很不错的。

 4.准备工作差不多做完了,现在可以讲代码了

 我用的是stm32zet6板子,然后我将esp8266发送和接受用串口2来进行,我这里不准备用全局变量传数据了,所以中断放esp8266.c里面去了,usart2.h我就不放了,就是对函数的声明,也没定义变量。

 usart2.c

#include "stm32f10x.h"
#include "usart2.h"
/*
************************************************************
*	函数名称:	Usart2_Init
*
*	函数功能:	串口2初始化
*
*	入口参数:	baud:设定的波特率
*
*	返回参数:	无
*
*	说明:		TX-PA2		RX-PA3
************************************************************
*/
void Usart2_Init(unsigned int baud)
{GPIO_InitTypeDef gpioInitStruct;USART_InitTypeDef usartInitStruct;NVIC_InitTypeDef nvicInitStruct;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);//PA2	TXDgpioInitStruct.GPIO_Mode = GPIO_Mode_AF_PP;gpioInitStruct.GPIO_Pin = GPIO_Pin_2;gpioInitStruct.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &gpioInitStruct);//PA3	RXDgpioInitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;gpioInitStruct.GPIO_Pin = GPIO_Pin_3;gpioInitStruct.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &gpioInitStruct);usartInitStruct.USART_BaudRate = baud;usartInitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;		//无硬件流控usartInitStruct.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;						//接收和发送usartInitStruct.USART_Parity = USART_Parity_No;									//无校验usartInitStruct.USART_StopBits = USART_StopBits_1;								//1位停止位usartInitStruct.USART_WordLength = USART_WordLength_8b;							//8位数据位USART_Init(USART2, &usartInitStruct);USART_Cmd(USART2, ENABLE);														//使能串口USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);									//使能接收中断nvicInitStruct.NVIC_IRQChannel = USART2_IRQn;nvicInitStruct.NVIC_IRQChannelCmd = ENABLE;nvicInitStruct.NVIC_IRQChannelPreemptionPriority = 0;nvicInitStruct.NVIC_IRQChannelSubPriority = 0;NVIC_Init(&nvicInitStruct);}/*
************************************************************
*	函数名称:	Usart_SendString
*
*	函数功能:	串口数据发送
*
*	入口参数:	USARTx:串口组
*				str:要发送的数据
*				len:数据长度
*
*	返回参数:	无
*
*	说明:		
************************************************************
*/
void Usart_SendString(USART_TypeDef *USARTx, unsigned char *str, unsigned short len)
{unsigned short count = 0;for(; count < len; count++){USART_SendData(USARTx, *str++);									//发送数据while(USART_GetFlagStatus(USARTx, USART_FLAG_TC) == RESET);		//等待发送完成}}

esp8266.c 

 这个我先把AT+Mqtt指令的作用列举一下吧

AT\r\n 返回ok表示有AT固件

AT+RST\r\n 复位

AT+CWMODE=1\r\n  设置为Station模式

 AT+CWJAP=\"1234\",\"abc\"\r\n 连接wifi 1234是wifi名字 abc是密码

AT+MQTTUSERCFG=0,1,\"12\",\"34\",\"56\",0,0,\"\"\r\n 这个说是连接服务器id(12),密码(34),名字(56),但是id必须有一个东西,随便写啥都行,不能空着,其他我没设置,直接空都行。

AT+MQTTCONN=0,\"123\",1883,0\r\n 连接服务器地址和端口 123是地址 1883是端口

AT+MQTTSUB=0,\"hello\",0\r\n 连接服务器话题 hello是话题,不连接话题串口2不能接受到数据

 AT+MQTTPUB=0,\"hello\",\"123\",0,0\r\n  向对应话题发送数据,123是发送过去的数据

 我这里的USER_GetJsonValue(char *cJson, char *Tag)是对发来的数据进行处理,但是这个发送格式必须是{ "msg":"123456"},中间也不能有空格,它会将:后面的数据提取出来,但我觉得其实你自己可以将收到数据的串口2数组打印出来,比如发个123,后面自己看如何处理这个数据其实更好。delay.c与usart1.c可以去这里找(3条消息) 基于stm32标准库的正点原子lora模块通信(超详细)_abc123sdc的博客-CSDN博客

//单片机头文件
#include "stm32f10x.h"//网络设备驱动
#include "esp8266.h"//硬件驱动
#include "delay.h"//这个可以我用的正点原子的delay,要用的话去我上篇那lora会告诉你如何弄
#include "usart2.h"
#include "usart1.h"//这个我也用的正点原子的,也可以去看我上篇文章,这是用于printf函数的,可以打印到电脑的串口
//C库
#include <string.h>
#include <stdio.h>#define ESP8266_WIFI_INFO		"AT+CWJAP=\"TP-LINK_FDDB\",\"fategrandorder\"\r\n"#define ESP8266_ONENET_INFO	"AT+MQTTCONN=0,\"172.16.40.64\",1883,0\r\n"#define MQTT_CLIENT_ID "clientidc801"//
#define MQTT_USERNAME  "admin"//名字
#define MQTT_PASSWORD  "public"//密码unsigned char esp8266_buf[128];
unsigned short esp8266_cnt = 0, esp8266_cntPre = 0;//==========================================================
//	函数名称:	ESP8266_Clear
//
//	函数功能:	清空缓存
//
//	入口参数:	无
//
//	返回参数:	无
//
//	说明:		
//==========================================================
void ESP8266_Clear(void)
{memset(esp8266_buf, 0, sizeof(esp8266_buf));esp8266_cnt = 0;}//==========================================================
//	函数名称:	ESP8266_WaitRecive
//
//	函数功能:	等待接收完成
//
//	入口参数:	无
//
//	返回参数:	REV_OK-接收完成		REV_WAIT-接收超时未完成
//
//	说明:		循环调用检测是否接收完成
//==========================================================
_Bool ESP8266_WaitRecive(void)
{if(esp8266_cnt == 0) 							//如果接收计数为0 则说明没有处于接收数据中,所以直接跳出,结束函数return REV_WAIT;if(esp8266_cnt == esp8266_cntPre)				//如果上一次的值和这次相同,则说明接收完毕{esp8266_cnt = 0;							//清0接收计数return REV_OK;								//返回接收完成标志}esp8266_cntPre = esp8266_cnt;					//置为相同return REV_WAIT;								//返回接收未完成标志}//==========================================================
//	函数名称:	ESP8266_SendCmd
//
//	函数功能:	发送命令
//
//	入口参数:	cmd:命令
//				res:需要检查的返回指令
//
//	返回参数:	0-成功	1-失败
//
//	说明:		
//==========================================================
_Bool ESP8266_SendCmd(char *cmd, char *res)
{unsigned char timeOut = 200;Usart_SendString(USART2, (unsigned char *)cmd, strlen((const char *)cmd));while(timeOut--){if(ESP8266_WaitRecive() == REV_OK)							//如果收到数据{if(strstr((const char *)esp8266_buf, res) != NULL)		//如果检索到关键词{printf("%s\r\n",esp8266_buf); ESP8266_Clear();									//清空缓存return 0;}}delay_ms(10);}return 1;}//==========================================================
//	函数名称:	ESP8266_SendData
//
//	函数功能:	发送数据
//
//	入口参数:	data:数据
//				len:长度
//
//	返回参数:	无
//
//	说明:		
//==========================================================
void ESP8266_SendData(char *data)
{char cmdBuf[100];sprintf(cmdBuf,"AT+MQTTPUB=0,\"hello\",\"%s\",0,0\r\n",data);Usart_SendString(USART2, (unsigned char *)cmdBuf, strlen((const char *)cmdBuf));
}//==========================================================
//	函数名称:	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);}elsereturn NULL;}}delay_ms(5);													//延时等待} while(timeOut--);return NULL;														//超时还未找到,返回空指针}//==========================================================
//	函数名称:	ESP8266_Init
//
//	函数功能:	初始化ESP8266
//
//	入口参数:	无
//
//	返回参数:	无
//
//	说明:		
//==========================================================
void ESP8266_Init(void)
{char str123[100]={0};GPIO_InitTypeDef GPIO_Initure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//ESP8266复位引脚,这个其实也没啥必要,因为后面我通过AT给他复位了GPIO_Initure.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_Initure.GPIO_Pin = GPIO_Pin_14;					//GPIOC14-复位GPIO_Initure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOC, &GPIO_Initure);GPIO_WriteBit(GPIOC, GPIO_Pin_14, Bit_RESET);delay_ms(250);GPIO_WriteBit(GPIOC, GPIO_Pin_14, Bit_SET);delay_ms(500);ESP8266_Clear();printf("0. AT\r\n");while(ESP8266_SendCmd("AT\r\n", "OK"))delay_ms(500);printf("1.RST\r\n");ESP8266_SendCmd("AT+RST\r\n","");delay_ms(500);printf("2. CWMODE\r\n");while(ESP8266_SendCmd("AT+CWMODE=1\r\n", "OK"))delay_ms(500);printf("3. CWJAP\r\n");while(ESP8266_SendCmd(ESP8266_WIFI_INFO, "GOT IP"))delay_ms(500);printf("4. nsend USERCFG\r\n");sprintf(str123, "AT+MQTTUSERCFG=0,1,\"%s\",\"%s\",\"%s\",0,0,\"\"\r\n",MQTT_CLIENT_ID, MQTT_USERNAME, MQTT_PASSWORD);while(ESP8266_SendCmd(str123, "OK"))delay_ms(500);printf("5. nsend MQTTCONN\r\n");while(ESP8266_SendCmd(ESP8266_ONENET_INFO, "OK"))delay_ms(500);printf("5. nsend topic\r\n");while(ESP8266_SendCmd("AT+MQTTSUB=0,\"hello\",0\r\n", "OK"))delay_ms(500);printf("6. ESP8266 Init OK\r\n");}/*******************************************************************
*函数:char *USER_GetJsonValue(char *cJson, char *Tag)
*功能:json为字符串序列,将json格式中的目标对象Tag对应的值字符串提取出来
*输入:char *cJson json字符串char *Tag 要操作的对象标签
*输出:返回数值的字符串形式的启始地址
*特殊说明:用户可以在此基础上改造和扩展该函数,这里只是个简单的DEMO
*******************************************************************/
char temp[100];
uint8_t USER_GetJsonValue(char *cJson, char *Tag)
{char *target = NULL;int8_t i=0;//int flagX = 0;memset(temp, 0x00, 128);sprintf(temp,"\"%s\":",Tag);target=strstr((const char *)cJson, (const char *)temp);if(target == NULL){//printf("空字符!\r\n");return 0;}i=strlen((const char *)temp);target=target+i;memset(temp, 0x00, 128);if(*target == '"')// 如果是字符型{i = 0;target++;while(1){if(*target != '\\' && *(target + 1) == '"'){temp[i] = *target;break;}temp[i] = *target;target++;i++;if(i >= 99)break;}}else {for(i=0; i<10; i++, target++)//数值超过10个位为非法,由于2^32=4294967296{if((*target<='9')&&(*target>='0')){temp[i]=*target;}else{break;}}}temp[i+1] = '\0';//printf("数值=%s\r\n",temp);return 1;
}//==========================================================
//	函数名称:	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);}}

 esp8266.h

#ifndef _ESP8266_H_
#define _ESP8266_H_#define REV_OK		0	//接收完成标志
#define REV_WAIT	1	//接收未完成标志void ESP8266_Init(void);void ESP8266_Clear(void);void ESP8266_SendData(char *data);unsigned char *ESP8266_GetIPD(unsigned short timeOut);_Bool ESP8266_WaitRecive(void);uint8_t USER_GetJsonValue(char *cJson, char *Tag);#endif

 main.c

最后说一下main.c,我的串口中断优先级配置分组直接写到主函数里去了。

#include "stm32f10x.h"                  // Device header
#include <stdio.h>
#include "Delay.h"
#include "string.h"
#include "stdio.h"
#include "Delay.h"//这个函数看我上篇文章
#include "usart1.h"
#include "usart2.h"
#include "esp8266.h"
extern u8 USART_RX_BUF[USART_REC_LEN];
extern unsigned char esp8266_buf[128];
extern unsigned short esp8266_cnt;
extern 	char temp[100];
int main(){char msg[100]="20hello";int time_three=3;NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);delay_init();uart_init(115200);Usart2_Init(115200);ESP8266_Init();while(1){while(time_three--){if(ESP8266_WaitRecive() == REV_OK)							//如果收到数据{if(USER_GetJsonValue((char*)esp8266_buf,"msg")) //读取出msg后面:后的数据printf("Send:%s",temp);//显示发送的数据	ESP8266_Clear();									//清空缓存}delay_ms(5);}time_three=3;delay_ms(1000);}
}

这篇关于stm32标准库基于esp8266的wife模块代码及使用(基于mqtt协议)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/309507

相关文章

中文分词jieba库的使用与实景应用(一)

知识星球:https://articles.zsxq.com/id_fxvgc803qmr2.html 目录 一.定义: 精确模式(默认模式): 全模式: 搜索引擎模式: paddle 模式(基于深度学习的分词模式): 二 自定义词典 三.文本解析   调整词出现的频率 四. 关键词提取 A. 基于TF-IDF算法的关键词提取 B. 基于TextRank算法的关键词提取

python: 多模块(.py)中全局变量的导入

文章目录 global关键字可变类型和不可变类型数据的内存地址单模块(单个py文件)的全局变量示例总结 多模块(多个py文件)的全局变量from x import x导入全局变量示例 import x导入全局变量示例 总结 global关键字 global 的作用范围是模块(.py)级别: 当你在一个模块(文件)中使用 global 声明变量时,这个变量只在该模块的全局命名空

使用SecondaryNameNode恢复NameNode的数据

1)需求: NameNode进程挂了并且存储的数据也丢失了,如何恢复NameNode 此种方式恢复的数据可能存在小部分数据的丢失。 2)故障模拟 (1)kill -9 NameNode进程 [lytfly@hadoop102 current]$ kill -9 19886 (2)删除NameNode存储的数据(/opt/module/hadoop-3.1.4/data/tmp/dfs/na

Hadoop数据压缩使用介绍

一、压缩原则 (1)运算密集型的Job,少用压缩 (2)IO密集型的Job,多用压缩 二、压缩算法比较 三、压缩位置选择 四、压缩参数配置 1)为了支持多种压缩/解压缩算法,Hadoop引入了编码/解码器 2)要在Hadoop中启用压缩,可以配置如下参数

Makefile简明使用教程

文章目录 规则makefile文件的基本语法:加在命令前的特殊符号:.PHONY伪目标: Makefilev1 直观写法v2 加上中间过程v3 伪目标v4 变量 make 选项-f-n-C Make 是一种流行的构建工具,常用于将源代码转换成可执行文件或者其他形式的输出文件(如库文件、文档等)。Make 可以自动化地执行编译、链接等一系列操作。 规则 makefile文件

深入探索协同过滤:从原理到推荐模块案例

文章目录 前言一、协同过滤1. 基于用户的协同过滤(UserCF)2. 基于物品的协同过滤(ItemCF)3. 相似度计算方法 二、相似度计算方法1. 欧氏距离2. 皮尔逊相关系数3. 杰卡德相似系数4. 余弦相似度 三、推荐模块案例1.基于文章的协同过滤推荐功能2.基于用户的协同过滤推荐功能 前言     在信息过载的时代,推荐系统成为连接用户与内容的桥梁。本文聚焦于

使用opencv优化图片(画面变清晰)

文章目录 需求影响照片清晰度的因素 实现降噪测试代码 锐化空间锐化Unsharp Masking频率域锐化对比测试 对比度增强常用算法对比测试 需求 对图像进行优化,使其看起来更清晰,同时保持尺寸不变,通常涉及到图像处理技术如锐化、降噪、对比度增强等 影响照片清晰度的因素 影响照片清晰度的因素有很多,主要可以从以下几个方面来分析 1. 拍摄设备 相机传感器:相机传

活用c4d官方开发文档查询代码

当你问AI助手比如豆包,如何用python禁止掉xpresso标签时候,它会提示到 这时候要用到两个东西。https://developers.maxon.net/论坛搜索和开发文档 比如这里我就在官方找到正确的id描述 然后我就把参数标签换过来

pdfmake生成pdf的使用

实际项目中有时会有根据填写的表单数据或者其他格式的数据,将数据自动填充到pdf文件中根据固定模板生成pdf文件的需求 文章目录 利用pdfmake生成pdf文件1.下载安装pdfmake第三方包2.封装生成pdf文件的共用配置3.生成pdf文件的文件模板内容4.调用方法生成pdf 利用pdfmake生成pdf文件 1.下载安装pdfmake第三方包 npm i pdfma

零基础学习Redis(10) -- zset类型命令使用

zset是有序集合,内部除了存储元素外,还会存储一个score,存储在zset中的元素会按照score的大小升序排列,不同元素的score可以重复,score相同的元素会按照元素的字典序排列。 1. zset常用命令 1.1 zadd  zadd key [NX | XX] [GT | LT]   [CH] [INCR] score member [score member ...]