基于stm32控制的ESP8266在设备模式下通讯

news2024/9/22 23:34:15

一、文章中要用的指令

指令作用
AT+UART=115200,8,1,0,0之前的51通讯是9600,这里的321用的是115200,需要改一下波特率
AT+CWMODE=XX是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 位置为1
					UART1_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 位置为1
					UART1_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"是在单片机内部使用,\"使用的是转义字符,简单里说就是让“不要有别的意思,就让它是个引号。大家也可以自己查一下关于转义字符的使用,我就不多说了。    

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1122126.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

微信小程序之个人中心授权登录

&#x1f3ac; 艳艳耶✌️&#xff1a;个人主页 &#x1f525; 个人专栏 &#xff1a;《Spring与Mybatis集成整合》《Vue.js使用》 ⛺️ 越努力 &#xff0c;越幸运。 1.了解微信授权登录 微信登录官网&#xff1a; 小程序登录https://developers.weixin.qq.com/miniprogram/d…

YOLOv5源码中的参数超详细解析(2)— 配置文件yolov5s.yaml(包括源码+网络结构图)

前言:Hello大家好,我是小哥谈。配置文件yolov5s.yaml在YOLOv5模型训练过程中发挥着至关重要的作用,属于初学者必知必会的文件!在YOLOv5-6.0版本源码中,配置了5种不同大小的网络模型,分别是YOLOv5n、YOLOv5s、YOLOv5m、YOLOv5l、YOLOv5x,其中YOLOv5n是网络深度和宽度最小…

5G技术的飞速发展:连接未来

随着科技的日益进步&#xff0c;5G通讯技术已经成为了全球科技领域的热门话题。5G&#xff0c;即第五代移动通信技术&#xff0c;带来的不仅仅是更快的网络速度&#xff0c;它的高带宽和低延迟特性将为未来的数字世界奠定基础。 速度与效率的飞跃: 5G技术的最大亮点是它极高的下…

App分发的策略和注意事项

当今的数字化时代中&#xff0c;移动应用程序已经成为了人们生活中不可或缺的一部分。随着智能手机的普及和移动互联网的快速发展&#xff0c;应用程序的分发方式也变得越来越多样化。 App分发是指将移动应用程序通过特定的渠道传递给终端用户的过程。在应用程序开发完成后&am…

js轮转数组

给定一个整数数组 nums&#xff0c;将数组中的元素向右轮转 k 个位置&#xff0c;其中 k 是非负数。 示例 1: 输入: nums [1,2,3,4,5,6,7], k 3 输出: [5,6,7,1,2,3,4] 解释: 向右轮转 1 步: [7,1,2,3,4,5,6] 向右轮转 2 步: [6,7,1,2,3,4,5] 向右轮转 3 步: [5,6,7,1,2,3,4…

OpenCV+QT实现的数字图像处理算法合集

源码下载地址&#xff1a; 基于OpenCV和QT的图像处理源码 图像预处理 灰度处理 灰度直方图 灰度均衡 梯度锐化 Laplace锐化 边缘检测 Roberts Sobel Laplace Prewitt canny Krisch 噪声 椒盐噪声 高斯噪声 滤波 均值滤波 中值滤波 双边滤波 形态学滤波 高斯滤波 图像变…

牛客网刷题-(1)

&#x1f308;write in front&#x1f308; &#x1f9f8;大家好&#xff0c;我是Aileen&#x1f9f8;.希望你看完之后&#xff0c;能对你有所帮助&#xff0c;不足请指正&#xff01;共同学习交流. &#x1f194;本文由Aileen_0v0&#x1f9f8; 原创 CSDN首发&#x1f412; 如…

工作中几个问题的思考

对于需要并行多公司并行处理的任务&#xff0c;方案是什么&#xff1f; 多线程、并行流、并发库&#xff08;ExecutorService、Futrue、Callable&#xff09;&#xff0c;分布式计算&#xff08;1&#xff09;按照公司ID分片 &#xff08;2&#xff09;按照业务类型分片 处理…

当我让文心一言写个代码来庆祝1024程序员节,它写的代码是……

先让它写个自我介绍吧~ 大家好&#xff0c;我是一个人工智能语言模型&#xff0c;我的中文名是文心一言&#xff0c;英文名是ERNIE Bot。我可以协助您完成范围广泛的任务并提供有关各种主题的信息&#xff0c;比如回答问题&#xff0c;提供定义和解释及建议。如果您有任何问题…

单链表的实现(全注释promax版)

目录 前言&#xff1a; 哨兵位&#xff1a; 链表的概念 链表的相关操作&#xff1a; 链表的创建&#xff1a; 打印链表&#xff1a; 申请新节点&#xff1a; 链表的尾插&#xff1a; &#xff01;&#xff01;&#xff01;对于传参中二级指针的解释&#xff1a; 链表的…

解决使用WebTestClient访问接口报[185c31bb] 500 Server Error for HTTP GET “/**“

解决使用WebTestClient访问接口报[185c31bb] 500 Server Error for HTTP GET "/**" 问题发现问题解决 问题发现 WebTestClient 是 Spring WebFlux 框架中提供的用于测试 Web 请求的客户端工具。它可以不用启动服务器&#xff0c;模拟发送 HTTP 请求并验证服务器的响…

【UCAS自然语言处理作业一】利用BeautifulSoup爬取中英文数据,计算熵,验证齐夫定律

文章目录 前言中文数据爬取爬取界面爬取代码 数据清洗数据分析实验结果 英文数据爬取爬取界面动态爬取 数据清洗数据分析实验结果 结论 前言 本文分别针对中文&#xff0c;英文语料进行爬虫&#xff0c;并在两种语言上计算其对应的熵&#xff0c;验证齐夫定律github: ShiyuNee…

Java Static关键字 单例设计模式

类变量 类变量&#xff08;静态变量&#xff09;&#xff1a;有static修饰&#xff0c;属于类&#xff0c;在计算机中只有一份&#xff0c;被类的所有对象共享 可以通过类名访问&#xff0c;也可以通过对象名访问&#xff0c;但是推荐用类名访问类变量一般用public修饰&#xf…

Maven 生命周期clean default size含义

clean 负责清理工作&#xff0c;清理上一次项目构建产生的一些文件&#xff0c;如编译后的字节码文件&#xff0c;打包后的jar包文件 default 整一个项目构建的核心工作&#xff0c;如编译&#xff0c;测试&#xff0c;打包&#xff0c;安装&#xff0c;部署等等 size 生成报告…

springBoot--web--函数式web

函数式web 前言场景给容器中放一个Bean&#xff1a;类型是 RouterFunction<ServerResponse>每个业务准备一个自己的handler使用集合的时候加注解请求的效果 前言 springmvc5.2 以后允许我们使用函数式的方式&#xff0c;定义web的请求处理流程 函数式接口 web请求处理的…

Docker开箱即用,开发码农加分项部署技术拿下!

目录 Docker概述 效果呈现 镜像 & 镜像仓库 & 容器 镜像 DockerHub 配置国内源加速 容器 简单的命令解读 Docker基础 常用命令 案例演示 数据卷 什么是数据卷 数据卷命令 演示环节 匿名数据卷 案例演示 自定义挂载位置 案例演示 自定义镜像 镜像结构 Dockerfile …

Python —— UI自动化之Page Object模式

1、Page Object模式简介 1、二层模型 Page Object Model&#xff08;页面对象模型&#xff09;, 或者也可称之为POM。在UI自动化测试广泛使用的一种分层设计 模式。核心是通过页面层封装所有的页面元素及操作&#xff0c;测试用例层通过调用页面层操作组装业务逻辑。 1、实战 …

Kafka简单入门01

目录 Kafka的核心组件 Kafka的分区有序 Kafka的多副本机制 Kafka的安装部署 Kafka的基本操作 Apache Kafka 是一个高吞吐量的分布式流数据平台&#xff0c;通常用于构建实时数据流处理应用程序。 Kafka的核心组件 主题&#xff08;Topic&#xff09;&#xff1a;主题是 K…

【vSphere 8 自签名 VMCA 证书】企业 CA 签名证书替换 vSphere VMCA CA 证书Ⅰ—— 生成 CSR

目录 替换拓扑图证书关系示意图说明 & 关联博文1. 默认证书截图2. 使用 certificate-manager 生成CSR2.1 创建存放CSR的目录2.2 记录PNID和IP2.3 生成CSR2.4 验证CSR 参考资料 替换拓扑图 证书关系示意图 本系列博文要实现的拓扑是 说明 & 关联博文 因为使用企业 …

为什么不建议使用Python自带的logging?

B站|公众号&#xff1a;啥都会一点的研究生 包括我在内的大多数人&#xff0c;当编写小型脚本时&#xff0c;习惯使用print来debug&#xff0c;肥肠方便&#xff0c;这没问题&#xff0c;但随着代码不断完善&#xff0c;日志功能一定是不可或缺的&#xff0c;极大程度方便问题…