ESP8266_01和串口

ESP01的接线

ESP826601需要接五根线,TXD,RXD,GND,EN,VCC,从别人的博客拿张图用用

【常用模块】ESP8266 WIFI串口通信模块使用详解(实例:附STM32详细代码)_正点原子wifiesp8266提供代码-CSDN博客

 VCC和EN接3.3V就够了,USB转TTL跳键帽把USB_TTL的VCC和5V接在一起,3.3V接在一起就是跟3.3V的单片机通信 ,5V接在一起就是跟5V的通信,我EN和VCC都是接在面包板上,推荐购买01S,那个好像只要四根线,网上还有那种现成的调试

ESP通信个人理解

我看了几篇ESP的文档,个人觉得WIFI通信就是在WIFI连接用户这个圈子中,跟别人建立通信,ESP可以建立圈子,也就是作为热点的AP模式,也可以进别人的圈子,就好像我们是一个圈子的才有共同话题,也就是下面要说的ESP的AP模式和STA模式,在一个圈子是前提,至于是你开热点还是蹭别人的,跟通信的主次无关(跟STA和AP选择无关,跟客户端服务端选择有关),你开了热点也可以作为客户端,你蹭别人的也可以作为服务端, 下面的STA模式和AP模式只是作为示例,并不是一定就要这样子,完全根据自己需要来定,不太懂TCP,理解有限,说错了请谅解

AT指令

AT指令可以到官网查看基础 AT 命令 — ESP-AT 用户指南 文档 (readthedocs-hosted.com),里面有更详细的示例,看下面的这几个就足够了应该,当然调试还要串口调试助手和网络调试助手,野火的多功能调试助手就不错,当我使用时遇到bug,就选了NetAssist网络调试助手

(AP模式)

先发送一个AT作为测试命令,看是否响应OK,再继续往下走

1.AT+CWMODE=2,选择为AP模式,掉电效果不消失

2.AT+RST,复位,其实复位也不一定需要,我看他们是这么做的,自己配置好wifi之后可以省略,而且复位会发送一大串的字符串

3.AT+CWSAP=“WIFI名字”,“WiFi密码”,x<通道号>,x<加密方式>,这个按理来说也是掉电不消失的,但是我只发送下面两个命令不能成功,待会再试试

AT+CWLIF,可以查询有谁连接到你的热点,会显示它的IP地址和mac地址,AT+CWQIF,断开与所有连接者的联系

4.AT+CIPMUX=1,设置为多连接,在AP下,可以让多个人连接你的热点,在STA模式下,你可以连接多个人的热点(下图是官方说明,第二句话不知道对不对,没试过)

5.AT+CIPSERVER=1,<端口号>,建立服务端

别人要想跟你通信需要知道你的IP地址和端口号,端口号前面自己设置了,我也不知道有没有查找端口号的命令,AT+CIPSERVER?我试了我这个模块是报错的,没找到,查IP地址的话用AT+CWSAP?照着下图填应该就可以了

关于透传模式也就是AT+CIPMODE=1,AT+CIPSEND这两条命令先后发送(配置好前面之后),进入透传模式,之后双方发送的都将被当成数据,CIPMUX和CIPSERVER必须为0,ESP作为服务端时不能开启透传,在AP模式下,用网络调试助手的客户端可以随意发送数据给ESP,但是ESP想发送数据要用AT+CIPSEND=<端口号,这个端口号是连接的用户的顺序吧类似,0,1,2,3这样的>,<发送字节的长度>,ESP收到数据还有特别的格式

STA模式

1.AT+CWMODE=1

2.AT+RST

3.AT+CWJAP=" wifi名称","wifi密码",加入wifi,可用AT+CWLAP查看可加入的wifi,加入别人的圈子

如果想要透传就不需要发送AT+CIPMUX=1

4.AT+CIPMUX=0,AT+CIPSERVER=0,嗯。。感觉这两个其实不太需要,前面RST了嘛

5.AT+CIPSTART=”TCP“,"IP地址",端口号,我先用网络调试助手创建服务端,我这里的ip地址是连接手机热点的(忘记截图了不是这个地址),用电脑win+R,输入cmd进入窗口然后输入ipconfig就可以看到IPV4地址,然后端口号自定义

6.开启透传AT+CIPMODE=1,AT+CIPSEND,由此,透传开始

用串口跟ESP通信

有两种判断接收结束的标志,一个是定时器通信,一个是空闲中断,我两种都试过,定时器通信我也不知道是设置超过时间为10ms太长还是什么原因,一旦接收很长字节的数据就会让程序卡死,所以最后选用了空闲中断

以后写代码就这样写吧,原先还想给GPIO和NVIC包装一个函数,但是有时候程序会有些莫名其妙的错误,stdio和stdarg这两个头文件是给串口的printf函数装备的,还有使能中断真的要记得同时清楚标志位,不然一开启就会运行一次中断服务函数

#include "stm32f10x.h"
#include "stdarg.h"
#include "stdio.h"
#include "string.h"
#include "Delay.h"
#include "OLED.h"

void MY_UART1_Init(uint32_t baud)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);	
	
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9;
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&GPIO_InitStructure);
	
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10;
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&GPIO_InitStructure);

	USART_InitTypeDef USART_InitStructure;
	USART_InitStructure.USART_BaudRate=baud;
	USART_InitStructure.USART_HardwareFlowControl=USART_HardwareFlowControl_None;
	USART_InitStructure.USART_Mode=USART_Mode_Tx | USART_Mode_Rx;
	USART_InitStructure.USART_Parity=USART_Parity_No;
	USART_InitStructure.USART_StopBits=USART_StopBits_1;
	USART_InitStructure.USART_WordLength=USART_WordLength_8b;
	USART_Init(USART1,&USART_InitStructure);
	
	USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);
	USART_ClearFlag(USART1,USART_FLAG_RXNE);
	USART_ITConfig(USART1,USART_IT_IDLE,ENABLE);
	USART_ClearFlag(USART1,USART_FLAG_IDLE);
	

	NVIC_InitTypeDef NVIC_InitStructure;
	NVIC_InitStructure.NVIC_IRQChannel=USART1_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority=0;
	NVIC_Init(&NVIC_InitStructure);
	
    
	USART_Cmd(USART1,ENABLE);

}

USART1的printf函数,可变参不会玩 ,这个最大长度MAX_SIZE最好设大一点?,应该大一点也没关系,下面有长度的判断

#define DATA_MAX_SIZE 100

void u1_printf(char *format,...)
{
	
	char DataBuf[DATA_MAX_SIZE];
    va_list start;
    va_start(start,format);
    vsprintf(DataBuf,format,start);
    va_end(start);

    uint8_t pDataBuf=0;
    while (DataBuf[pDataBuf]!='\0')
    {
        USART_SendData(USART1,DataBuf[pDataBuf]);
        while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET);
        pDataBuf++;
        
    }
    
}

 中断服务函数,中断里接收字节,超过字节最大长度会置标志位,接收完毕也会置标志位,这里的RX_STA是记录字节数和记录接收完毕两个作用的标志位,给STA++后再给对应元素赋字符串结束标志,就不用在每个处理程序中都加结束标志位了,IDLE中断要调用一次接收数据函数,不然清除不掉标志位

#define USART1_RX_MAX_SIZE 40
uint16_t USART1_RX_STA;
uint8_t USART1_RX_BUF[USART1_RX_MAX_SIZE];

void USART1_IRQHandler(void)
{
	
    if (USART_GetITStatus(USART1,USART_IT_RXNE)==SET)
    {
        if (!(USART1_RX_STA & (1<<15)))
		{
            USART1_RX_BUF[(USART1_RX_STA&0x7FFF)]=USART_ReceiveData(USART1);
			USART1_RX_STA++;
			USART1_RX_BUF[USART1_RX_STA&0x7FFF]='\0';
			if ((USART1_RX_STA&0x7FFF)>=USART1_RX_MAX_SIZE-1)
			{
				USART1_RX_STA |= (1<<15);				
			}	
		}
    	USART_ClearITPendingBit(USART1,USART_IT_RXNE);
    }
	if (USART_GetITStatus(USART1,USART_IT_IDLE)==SET)
	{
		USART1_RX_STA |= (1<<15);
		USART_ReceiveData(USART1);
		USART_ClearFlag(USART1,USART_FLAG_IDLE);
	}
	
	
}

 这是测试的函数,在while循环中不断调用,会把接收到的数据返还,不过现在被我注释掉了,因为ESP和单片机连接的话没法看串口,就用oled来显示信息了

void USART_RE_Deal(void)
{
	if ((USART1_RX_STA&(1<<15)))
	{
		USART1_RX_BUF[USART1_RX_STA&0x7FFF]='\0';
		OLED_ShowString(3,1,USART1_RX_BUF);
		// u1_printf("%s\r\n",USART1_RX_BUF);
        USART1_RX_STA=0;
	}
	
}

以上就是串口的相关部分,下面用串口来向ESP发送数据配置ESP

用串口写命令

这个是用来查找ESP响应信息的,strstr函数在string.h中,会查找第二个字符串在第一个字符串中第一次出现的位置,没找到则返回空指针

char *USART1_check_cmd(char * str)
{
	char *str_return=NULL;
	if (USART1_RX_STA&(1<<15))
	{
		str_return=strstr(USART1_RX_BUF,str);
       
	}
	return str_return;
}

 发送命令,记得在printf后面加上\r\n

uint8_t USART1_send_cmd(char *cmd,char *call,uint8_t wait_time)
{
	u1_printf("%s\r\n",cmd);
	if (call&&wait_time)
	{
		while (wait_time--)
		{
			Delay_ms(10);
			if (USART1_check_cmd(call)!=NULL)
			{
				
				return 1;
			}
		}
	}
    USART1_RX_STA=0;
	return 0;
}

 注意转义字符的使用,有些命令格式要接受字符串,RST后有个几秒的延时,如果先前配置好了前面几句可以注释掉的,AT+CWSAP应该也可以不用第二次配置,但我注释掉的话,能连接到WiFi,但不能通信,很奇怪

2024.3.30

像这种跟串口通信的模块,好像指令不能发的太快,每条指令之间最好间隔一段时间,我没测试,就选了0.5s,效果还行

void USART1_WIFI_START_Trans(void)
{
	//下面这些内容在调试的时候配置好了可以删除
   	//USART1_send_cmd("AT+CWMODE=2","OK",50);
	//USART1_send_cmd("AT+RST","ready",20);
	
	//Delay_ms(1000);
	//Delay_ms(1000);
	//Delay_ms(1000);
	USART1_send_cmd("AT+CWSAP=\"ABC\",\"12345678\",11,2","OK",100);
    Delay_ms(500);
	USART1_send_cmd("AT+CIPMUX=1","OK",20);
    Delay_ms(500);
	USART1_send_cmd("AT+CIPSERVER=1,8080","OK",50);
	
}

用ESP作为热点,客户端给ESP发消息,ESP的接受格式类似于+IPD,<用户端口号>,<字节长度>:<内容>,我想用ESP作为一个密码锁,当客户端给他发送数据,他能判断数据的对错

#define PWSD "20210909"

void USART1_check_pwsd(void)
{
	if (USART1_RX_STA&(1<<15))
	{
		char * temp;
		temp = strstr(USART1_RX_BUF,PWSD);
		if (temp)
		{
			if (strcmp(temp,PWSD)==0)
			{
				OLED_ShowString(1,1,"SUCCESS");
			}
			else
			{
				OLED_ShowString(2,1,temp);
				OLED_ShowString(1,1,"ERROR  ");
			}
		}
		USART1_RX_STA=0;
	}
	
}

完整代码

附上我git仓库的链接git@gitee.com:tang-yan-handsome-guy/esp8266-as-the-server.git

  • 17
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值