基于stm32控制的ESP8266在设备模式下通讯
一、文章中要用的指令
| 指令 | 作用 |
| AT+UART=115200,8,1,0,0 | 之前的51通讯是9600,这里的321用的是115200,需要改一下波特率 |
| AT+CWMODE=X | X是1代表station(设备)模式 ,X是2代表AP(路由)模式 ,X是3.代表双模模式(工作模式在串口助手里已经设置为双模,掉电后自动保存,因此程序中并未体现配置工作模式,这个配置模式的指令写与不写均可以) |
| AT+CWJAP="PEI","jmgcyjs." | 第一个引号里的是wifi的名称,第二个是WiFi密码,要注意的是,使用的时候一定要确保你的电脑和wifi模块连接的是一个wifi,否则无法成功。 |
| AT+CIPSTART="TCP","192.168.1.112",8880 | 连接服务器,TCP代表客户端模式,电脑连接无线网地址192.168.1.112,8880代表端口号 |
| AT+CIPMODE=1 | 透传指令,不用受发送次数还有发送字节大小限制 |
| AT+CIPSEND | 开始发送 |
| AT+RST | 重启指令 |
有关esp8266的烧录我在之前说过,有兴趣的可以看一看,http://t.csdnimg.cn/J3Sid
二、代码部分
#include "main.h"
#include "usart.h"
#include "gpio.h"#include <string.h>
#include <stdio.h>uint8_t buf=0;//串口接收缓存(1字节)
#define UART1_REC_LEN 200//定义最大接收字节数 200,可根据需求调整
uint8_t UART1_RX_Buffer[UART1_REC_LEN];// 接收缓冲, 串口接收到的数据放在这个数组里,最大UART1_REC_LEN个字节
uint16_t UART1_RX_STA=0;// 接收状态
// bit15, 接收完成标志
// bit14, 接收到0x0d
// bit13~0, 接收到的有效字节数目void SystemClock_Config(void);void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{// 判断中断是由哪个串口触发的if(huart->Instance == USART1){// 判断接收是否完成(UART1_RX_STA bit15 位是否为1)if((UART1_RX_STA & 0x8000) == 0){// 如果已经收到了 0x0d (回车),if(UART1_RX_STA & 0x4000){// 则接着判断是否收到 0x0a (换行)if(buf == 0x0a){ // 如果 0x0a 和 0x0d 都收到,则将 bit15 位置为1UART1_RX_STA |= 0x8000;if(!strcmp((const char*)UART1_RX_Buffer,"WIFI GOT IP"))AT_Connect_Net_Flag = 1; if(!strcmp((const char*)UART1_RX_Buffer,"OK"))AT_OK_Flag = 1;if(!strcmp((const char*)UART1_RX_Buffer,"L1"))HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_RESET);if(!strcmp((const char*)UART1_RX_Buffer,"L0"))HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_SET);if(!strcmp((const char*)UART1_RX_Buffer,"FALL"))//连接网络不成功就会给单片机返回FALL{int i=0;for(i=0;i<5;i++){HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_8);HAL_Delay(1000);}}memset(UART1_RX_Buffer,0,UART1_REC_LEN);UART1_RX_STA=0;}else// 否则认为接收错误,重新开始UART1_RX_STA = 0;}else // 如果没有收到了 0x0d (回车){//则先判断收到的这个字符是否是 0x0d (回车)if(buf == 0x0d){// 是的话则将 bit14 位置为1UART1_RX_STA |= 0x4000;}else{// 否则将接收到的数据保存在缓存数组里UART1_RX_Buffer[UART1_RX_STA & 0X3FFF] = buf;UART1_RX_STA++;// 如果接收数据大于UART1_REC_LEN(200字节),则重新开始接收if(UART1_RX_STA > UART1_REC_LEN - 1)UART1_RX_STA = 0;}}}// 重新开启中断HAL_UART_Receive_IT(&huart1, &buf, 1);}
}int fputc(int ch, FILE *f)
{ unsigned char temp[1]={ch};HAL_UART_Transmit(&huart1,temp,1,0xffff); return ch;
}int main(void)
{
HAL_Init();SystemClock_Config();MX_GPIO_Init();MX_USART1_UART_Init();MX_USART2_UART_Init();/* USER CODE BEGIN 2 */
HAL_NVIC_SetPriority(SysTick_IRQn,0,0);
HAL_UART_Receive_IT(&huart1, &buf, 1);//系统滴答定时器,防止死机
HAL_UART_Transmit(&huart2,"let's go\r\n",strlen("let's go\r\n"),100);
printf("AT+CWJAP=\"PEI\",\"jmgcyjs.\"\r\n");//入网指令
while(!AT_OK_Flag)HAL_Delay(50);
HAL_UART_Transmit(&huart2,"333\r\n",strlen("333\r\n"),100);AT_OK_Flag = 0;//发送连服务器指令并等待成功printf("AT+CIPSTART=\"TCP\",\"192.168.1.105\",8880\r\n"); //连接服务器指令while(!AT_OK_Flag)HAL_Delay(100);HAL_UART_Transmit(&huart2,"433\r\n",strlen("433\r\n"),100);AT_OK_Flag = 0;//发送透传模式指令并等待成功printf("AT+CIPMODE=1\r\n"); //透传指令while(!AT_OK_Flag)HAL_Delay(50);HAL_UART_Transmit(&huart2,"533\r\n",strlen("533\r\n"),100);AT_OK_Flag = 0;//发送数据传输指令并等待成功printf("AT+CIPSEND\r\n");//数据传输开始指令while(!AT_OK_Flag)HAL_Delay(50);HAL_UART_Transmit(&huart2,"633\r\n",strlen("633\r\n"),100);/* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while (1){/* USER CODE END WHILE *//* USER CODE BEGIN 3 */HAL_UART_Transmit(&huart2,"666\r\n",strlen("666\r\n"),100);HAL_Delay(1000);}/* USER CODE END 3 */
}
三、思路分析
这里的思路和51哪里的差不多。都是通过串口将单片机中的指令发给ESP8266.但是与51不同是,51在调试中用的是一个串口单向的调试,而32的是用的双向两个串口调试。
51测试的思路

32的具体的思路是这样的,基于上一篇文章的串口基础上,每当执行到UART1_RX_STA |= 0x8000时,代表着单片机的接收寄存器已经完全收到了来自单片机内部printf重映射的指令或是网络调试助手的指令。
接着从头说起,上电之后首先要输入入网指令
printf("AT+CWJAP=\"PEI\",\"jmgcyjs.\"\r\n");
输入完成后进入中断回调函数,如果你的网络名称和密码都没问题,ESP8266会通过串口1给单片机回复对应的内容
WIFI CONNECTED
WIFI GOT IP
OK
如图所示

UART1_RX_STA |= 0x8000;下面的第一个if将会判断成功,将WIFI GOT IP返回值的标志位AT_Connect_Net_Flag 变为1,接着是ESP8266返回OK指令,就可以让OK返回值的标志位变为1,同时在main函数里在printf("AT+CWJAP=\"PEI\",\"jmgcyjs.\"\r\n")下面有while循环标志位的判断来确保每一步的进行都是正确的。每当OK返回值的标志位使用完后,就把OK返回值的标志位AT_OK_Flag变为0。等到下一次ESP8266回复给单片机OK时,就进入中断将AT_OK_Flag变为1,程序可以继续正常运行。
思路就是这这样一个思路。
接着就是
连接服务器指令是否成功, 透传指令是否成功 ,数据传输开始指令是否成功 ,如果成功ESP8266就都会返回OK.如果在哪一步不成功,就会卡到哪里一直死循环。
当然了,这里还是要细说一下,失败也是分情况的。第一种失败是入网指令的失败,这个时候如果你失败,ESP8266会给单片机返回FALL,这时候我们的LED1会亮灭5次。如果你是入网成功后的失败,那你就是会一直陷入死循环。
四、其它
1.关于while后面加延时,你可以不加,只要不死机。每个while的条件后面不是直接跟;而是跟的延时函数,这样可以避免死机。
2.HAL_NVIC_SetPriority(SysTick_IRQn,0,0);滴答定时器优先级提高,中断中加入了延时函数,如果不把滴答定时器优先级提高,也会死机。
3.全部成功后,进入网络助手后拾取指令完成后,一定记得要带上回车再点击发送,因为我们的串口输入判断\r\n是一个重要的依据,不能不带上回车。
4.按照51的写法,把指令写成数组
char LJWL[] = "AT+CWJAP=\"PEI\",\"jmgcyjs.\"\r\n"; //入网指令
char LJFWQ[] = "AT+CIPSTART=\"TCP\",\" 192.168.10.206\",8880\r\n"; //连接服务器指令
char TCMS[] = "AT+CIPMODE=1\r\n"; //透传指令
char SJCS[] = "AT+CIPSEND\r\n"; //数据传输开始指令
char CQMK[] = "AT+RST\r\n"; //重启模块指令
你可以写成printf(LJWL)的形式,意思就是这个就是把数组名为LJWL的数组里的内容发出去,也就是发送入网指令。前提是你要把你的wifi模块的波特率改过来才行。你也可以像我一样使用printf("AT+CWJAP=\"PEI\",\"jmgcyjs.\"\r\n");,二选一。使用printf(LJWL)记得把这5个字符串写入数组。
5.还有一点我要补充一下,不知道大家有没有注意到一个小细节
在第一章里,入网指令写的是AT+CWJAP="PEI","jmgcyjs."但是到了printf里我写的是printf("AT+CWJAP=\"PEI\",\"jmgcyjs.\"\r\n");。\"PEI\",\"jmgcyjs.\"\r\n和"PEI","jmgcyjs."一样吗?确实不一样。使用的场景不一样AT+CWJAP="PEI","jmgcyjs."是在串口助手里使用。写完这条指令后,点击发送新行就相当于回车换行的/r/n,而"AT+CWJAP=\"PEI\",\"jmgcyjs.\"\r\n"是在单片机内部使用,\"使用的是转义字符,简单里说就是让“不要有别的意思,就让它是个引号。大家也可以自己查一下关于转义字符的使用,我就不多说了。
相关文章:
基于stm32控制的ESP8266在设备模式下通讯
一、文章中要用的指令 指令作用ATUART115200,8,1,0,0之前的51通讯是9600,这里的321用的是115200,需要改一下波特率ATCWMODEXX是1代表station(设备)模式 ,X是2代表AP(路由)模式 ,X是…...
用PHP组合数组,生成笛卡尔积。写几个例子
#创作灵感# [红色,白色,黄色,蓝色] [128G,256G,512G] [国行,港版,美版,韩版] 用PHP组合数组,生成笛卡尔积。写几个例子 你可以使用嵌套的循环来生成这些数组的笛卡尔积。以下是一些示例代码: // 示例…...
软设上午题错题知识点7
软设上午题错题知识点7 1、数据流图摆脱系统的物理内容,在逻辑上描述系统的功能、输入、输出和数据存储等,是系统逻辑模型的重要组成部分。 2、HTTPS(Secure Hypertext Transfer Protocol)安全超文本传输协议。 它是一个安全通信…...
让uniGUI支持https
今天在专家的帮助下,成功的让uniGUI支持https了。 首先,去申请个**的证书。我同事去阿里申请的,申请回是一个zip文件,里面有两个文件,一个扩展是per,一个key 然后,把这两个证书文件放到uniGUI…...
iPhone怎么导出微信聊天记录?3个值得收藏的方法
随着时间的推移,微信占用的内存空间会“膨胀”得越来越大。当手机内存不足时,清理微信中的聊天记录是一个可行的方法。但是很多小伙伴觉得有些重要的聊天记录还有用,可能以后需要进行查看。 因此,他们想将一些聊天记录进行导出或…...
【Proteus仿真】【STM32单片机】自动饲养控制系统
文章目录 一、功能简介二、软件设计三、实验现象联系作者 一、功能简介 本项目使用Proteus8仿真STM32单片机控制器,使用LCD1604显示模块、红外传感器、有害气体检测模块、PCF8591 ADC模块,蜂鸣器、DHT11温湿度、SG90舵机、风扇加热加湿等。 主要功能&a…...
【设计模式】模板方法模式
模板方法模式 1. 什么是模板方法 模板方法模式:定义一个操作中的算法骨架(父类),而将一些步骤延迟到子类中。 模板方法使得子类可以不改变一个算法的结构来重定义该算法的 2. 什么时候使用模板方法 实现一些操作时,…...
c语言进制的转换二进制转换10进制
c语言进制的转换之二进制转换10进制 c语言的进制的转换 c语言进制的转换之二进制转换10进制一、二进制转换10进制的方法二、10进制程序打印 一、二进制转换10进制的方法 二进制: 二进制逢二进一,所有的数组是0、1组成 十进制转二进制: 除二反…...
C++ 纠错题总结2
1、for循环中的判断语句: 要注意初始赋值、< 还是 < for(int i 0; i < n; i) 2、cin.getline(char[], int, char) 注意:第二个参数为不是char[]的有效元素个数,因为最后一个元素位置要用来存储 \0 3、函数形参有默认值的,有默认…...
Jmeter性能 —— 事务控制器
统计性能测试结果一定会关注TPS,TPS表示:每秒处理事务数,JMeter默认每个事务对应一个请求。我们可以用逻辑控制器中的事务控制器将多个请求统计为一个事务。 1、添加事务控制器 2、事务控制器参数说明 Generate parent sample:如…...
Android C/C++ native编程NDK开发中logcat的使用
Android C/C native编程NDK开发中logcat的使用 前言具体用法 前言 在NDK开发过程中,C/C层,需要对代码进行一些调试,日志打印是我们解决异常或崩溃的重要手段,这里我就简单介绍下日志打印三步走。 首先我们先看下官方文档关于日志…...
什么是美颜SDK?深入了解直播实时美颜SDK
美颜已经成为了现代社交媒体和直播应用中的重要元素,它使用户能够在拍摄自拍照片或进行直播时改善其外貌特征。美颜技术的普及离不开美颜SDK(软件开发工具包),特别是在直播应用中,直播实时美颜SDK正变得越来越流行。在…...
TensorFlow2从磁盘读取图片数据集的示例(tf.data.Dataset.list_files)
import os import warnings warnings.filterwarnings("ignore") import tensorflow as tf from tensorflow.keras.optimizers import Adam from tensorflow.keras.applications.resnet import ResNet50 from pathlib import Path import numpy as np#数据所在文件夹 …...
Jmeter(九):jmeter_逻辑控制器与HTTP Cookie管理器详解
Jmeter:jmeter_逻辑控制器_事务控制器 事务 性能测试中,事务指的是从端到端,一个完整的操作过程,比如一次登录、一次 筛选条件查询,一次支付等;技术上讲:事务就是由1个或多个请求组成的 事务…...
CVPR2023优秀论文 | AIGC伪造图像鉴别算法泛化性缺失问题分析
作者 | 搜索内容技术部 导读 深度伪造检测算法无法检出未知伪造算法生成的攻击数据。以往算法采取手动建模伪造特征的方式提升模型泛化性,然而这种方式限制了算法可行域,影响了模型泛化性进一步提升,同时这类方法参数量巨大,无法满…...
ISP Pipeline典型场景要点SAT、Bokeh、MFNR、HDR
目录 一、概述 二、通用流程 三、典型场景 1. SAT 2. Bokeh背景虚化 MFNR 3. HDR(DOL、DCG等) 一、概述 本文解释isp pipeline的一些非常典型的场景,不同厂商对pipeline的连接及node的port口设计可能不同,但核心的思想相同…...
计算机视觉(CV)技术
是一种将数字图像或视频进行处理和分析的技术,旨在使计算机能够模拟人类视觉系统。该领域涉及到图像处理、模式识别、机器学习等多个领域,主要涵盖以下几方面: 图像处理:对图像进行去噪、增强、分割、特征提取等处理。图像分类&a…...
vue3项目使用TypeIt打字机
官网: TypeIt | The most versatile JavaScript typewriter effect library on the planet. 下载: npm i typeit 使用方法: 正常打字 多行打字机 input输入框实现打字机效果 打字机颜色变化 删除,光标移动,最全面的打字机效果 官网最下面还可以输入你想有的打字效果,然后生…...
Linux基础命令1——Linux的命令格式与命令分类
目录 Linux命令格式 Linux命令分类 如何判断命令的类型——Type命令 内置命令 外部命令 alias命令 命令的执行效率与过程 Linux命令格式 命令格式 完整的命令格式分为三部分:命令、参数、对象 其中命令与参数、参数与参数、参数与对象之间最少要有一个空格做…...
SystemVerilog Assertions应用指南 Chapter 11.5SVA检验器的时序窗口
11.5SVA检验器的时序窗口 到目前为止,带延迟的例子使用的都是固定的正延迟。在下面几个例子中,我们将讨论几种不同的描述延迟的方法属性p12检查布尔表达式“a&&b”在任何给定的时钟上升沿为真。如果表达式为真,那么在接下去的1-~3周期内,信号“c”应该至少在一个时钟周…...
【机器视觉】单目测距——运动结构恢复
ps:图是随便找的,为了凑个封面 前言 在前面对光流法进行进一步改进,希望将2D光流推广至3D场景流时,发现2D转3D过程中存在尺度歧义问题,需要补全摄像头拍摄图像中缺失的深度信息,否则解空间不收敛…...
sqlserver 根据指定字符 解析拼接字符串
DECLARE LotNo NVARCHAR(50)A,B,C DECLARE xml XML ( SELECT <x> REPLACE(LotNo, ,, </x><x>) </x> ) DECLARE ErrorCode NVARCHAR(50) -- 提取 XML 中的值 SELECT value x.value(., VARCHAR(MAX))…...
在WSL2的Ubuntu镜像中安装Docker
Docker官网链接: https://docs.docker.com/engine/install/ubuntu/ 1、运行以下命令卸载所有冲突的软件包: for pkg in docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc; do sudo apt-get remove $pkg; done2、设置Docker…...
Linux --进程控制
本文从以下五个方面来初步认识进程控制: 目录 进程创建 进程终止 进程等待 进程替换 模拟实现一个微型shell 进程创建 在Linux系统中我们可以在一个进程使用系统调用fork()来创建子进程,创建出来的进程就是子进程,原来的进程为父进程。…...
中医有效性探讨
文章目录 西医是如何发展到以生物化学为药理基础的现代医学?传统医学奠基期(远古 - 17 世纪)近代医学转型期(17 世纪 - 19 世纪末)现代医学成熟期(20世纪至今) 中医的源远流长和一脉相承远古至…...
网站指纹识别
网站指纹识别 网站的最基本组成:服务器(操作系统)、中间件(web容器)、脚本语言、数据厍 为什么要了解这些?举个例子:发现了一个文件读取漏洞,我们需要读/etc/passwd,如…...
【p2p、分布式,区块链笔记 MESH】Bluetooth蓝牙通信 BLE Mesh协议的拓扑结构 定向转发机制
目录 节点的功能承载层(GATT/Adv)局限性: 拓扑关系定向转发机制定向转发意义 CG 节点的功能 节点的功能由节点支持的特性和功能决定。所有节点都能够发送和接收网格消息。节点还可以选择支持一个或多个附加功能,如 Configuration …...
C++--string的模拟实现
一,引言 string的模拟实现是只对string对象中给的主要功能经行模拟实现,其目的是加强对string的底层了解,以便于在以后的学习或者工作中更加熟练的使用string。本文中的代码仅供参考并不唯一。 二,默认成员函数 string主要有三个成员变量,…...
C++ 类基础:封装、继承、多态与多线程模板实现
前言 C 是一门强大的面向对象编程语言,而类(Class)作为其核心特性之一,是理解和使用 C 的关键。本文将深入探讨 C 类的基本特性,包括封装、继承和多态,同时讨论类中的权限控制,并展示如何使用类…...
篇章一 论坛系统——前置知识
目录 1.软件开发 1.1 软件的生命周期 1.2 面向对象 1.3 CS、BS架构 1.CS架构编辑 2.BS架构 1.4 软件需求 1.需求分类 2.需求获取 1.5 需求分析 1. 工作内容 1.6 面向对象分析 1.OOA的任务 2.统一建模语言UML 3. 用例模型 3.1 用例图的元素 3.2 建立用例模型 …...
