【毕设调试一】WiFi模块esp8266的调试

这篇具有很好参考价值的文章主要介绍了【毕设调试一】WiFi模块esp8266的调试。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

硬件说明:

提示 :主控芯片STM32F103C8T6,与WiFi通信串口为串口二,打印串口为串口三(不使用串口一是当时设计时,方便pcb走线)

说明 :因为我是使用PCB画板的方式来走线的,并不是按模块来拼接的,走线的时候需要注意WiFi模块和主控芯片串口的连接(RX-TX),如下图所示,这个是可以直接安信可的手册上查到,不需要更改。(提醒一下,很多新手可能会找不到对应的原理图,或者是移植他人的,那么我们需要注意的是,我们自己的WiFi模块实际端口,与他人原理图端口还有封装端口是否对的上如下图本人的设计解释

①要首先确定WiFi模块,我是在立创商城购买的:ESP-12F(ESP8266MOD),安信可官网给出如图外观【毕设调试一】WiFi模块esp8266的调试

②再确定原理图,电路外围可以参考安信可的手册,原理图是自己重新画的。(注意看我原理图的端口顺序,是从RST绕逆时针方向走到TX0,从1-22,电源是3.3V,C6和C8两个去耦电容与VCC端口走线尽量短【毕设调试一】WiFi模块esp8266的调试

③确定封装,可以从立创商城直接导出,但并不代表可以直接用(本人走过的坑)。第一张图是立创商城给的封装图,第二张是我自己修改过后的封装图,两图是端口号是不一样  的,需要与原理图的端口号对上,那么焊接的时候才不会出现端口错误。第三张图是pcb的效果图(需要注意天线部分不可面对元器件,并且该部分不铺地,直接露空,信号线尽量在同一层,不要相等长度,过孔虽不会影响信号传送,但尽量少打,至于是否需要隔地,因为这个传输虽说不算太过高速,也只是用来完成毕设,暂时不考虑辐射问题)

【毕设调试一】WiFi模块esp8266的调试

                                   

【毕设调试一】WiFi模块esp8266的调试

【毕设调试一】WiFi模块esp8266的调试


串口配置

说明:因为这是我第一次尝试调试WIFI模块,也参考了大量其他博主的文章,才终于勉勉强强的调试出来,接下来说的是,我在调试过程中因为不了解WiFi模块而产生的各种问题。

我的第一个坑:相信大家看到的,很多博主都是把WiFi模块的指令烧进去,然后去测试该模块是否是正常运行(因为他们的模块是可以单独出来,使用串口助手来通信)。而当我解决的板子的问题时候才发现,我的并不可以这样直接烧写,来检测模块是否正常工作,那么我就只能通过单片机来与WiFi模块通信检测是否正常工作。而我比较好运,我买的模块都是正常的,这也是我为什么在硬件准备的时候,准备多了一个串口三来帮助我打印信息,这样子方便了我的调试(个人建议,大家自己画的板子一定要留一个串口来打印,好方便自己调试的各种问题)。

调试过程:

        AT指令,我们调试的时候离不开的就是它,我建议大家在开始之前先了解熟悉一下这个WiFi模块的AT指令,这样子好方便我们调试(可以在安信可官网查到所有指令,也都有解释,当然也可以看一些大佬的博客,也是有很多大佬写的很清晰的)。

配置串口三,用于和串口打印

#if 1
//#pragma import(__use_no_semihosting)       
#pragma (__use_no_semihosting)   
//标准库需要支持的函数
struct __FILE 
{
  int handle;
};

FILE __stdout;       
//定义_sys_exit()以避免工作在半主机状态
void _sys_exit(int x) 
{ 
  x = x; 
} 
//重定义fputc函数
//这个需要根据MCU和我们希望printf从哪个串口输出来确认 __WAIT_TODO__
int fputc(int ch, FILE *f)
{
	//注意:USART_FLAG_TXE是检查发送缓冲区是否为空,这个要在发送前检查,检查这个提议提高发送效率,但是在休眠的时候可能导致最后一个字符丢失
	//USART_FLAG_TC是检查发送完成标志,这个在发送后检查,这个不会出现睡眠丢失字符问题,但是效率低(发送过程中发送缓冲区已经为空了,可以接收下一个数据了,但是因为要等待发送完成,所以效率低)
	//不要两个一起用,一起用效率最低
	
	//循环等待直到发送缓冲区为空(TX Empty)此时可以发送数据到缓冲区
  while (USART_GetFlagStatus(USART3, USART_FLAG_TXE) == RESET)
  {}
  USART_SendData(USART3, (uint8_t) ch);

  /* 循环等待直到发送结束*/
  while (USART_GetFlagStatus(USART3, USART_FLAG_TC) == RESET){}
  return ch;
}
#endif 

void uart3_Init(u32 bound)//串口3  引脚为PB10  PB11
{

    GPIO_InitTypeDef GPIO_InitStructure;
    USART_InitTypeDef USART_InitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;

	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置中断向量分组:第2组 抢先优先级:0 1 2 3 子优先级:0 1 2 3		
	
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);   

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //PB10
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //?′ó?í?íìê?3?
    GPIO_Init(GPIOB, &GPIO_InitStructure);


    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;//PB11
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
    GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化GPIO

    //Usart3 NVIC 配置
    NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0;//抢占优先级0
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;      //响应优先级0
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;         //USART_IRQn通道使能
    NVIC_Init(&NVIC_InitStructure); //初始化NVIC

    //USART3 配置
    USART_InitStructure.USART_BaudRate = bound;//波特率
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;//数据长度
    USART_InitStructure.USART_StopBits = USART_StopBits_1;//停止位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(USART3, &USART_InitStructure); //初始化串口

    USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);//配置了接收中断中断
	USART_ITConfig(USART3, USART_IT_IDLE, ENABLE);//配置了总线空闲中断

    USART_Cmd(USART3, ENABLE);      //串口外设使能 (打印的测试串口)   
}

void USART3_IRQHandler( void )
{   
    u8 ucCh;

    if(USART_GetITStatus( USART3, USART_IT_RXNE ) != RESET ) //如果接收
    {
        ucCh  = USART_ReceiveData( USART3 );                                    
    }

    if( USART_GetITStatus( USART3, USART_IT_IDLE ) == SET )  //如果总线空闲
    {
        ucCh = USART_ReceiveData( USART3 );                                                             
    }   

}

配置串口二,用于和WiFi模块通信

void uart2_Init(u32 bound)//串口2  引脚为PA2  PA3
{
	USART_InitTypeDef USART_InitStructure;
	GPIO_InitTypeDef  GPIO_InitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;
	
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置中断向量分组:第2组 抢先优先级:0 1 2 3 子优先级:0 1 2 3		
	
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);	    //使能指定端口时钟
	
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;//复用推挽输出
	GPIO_Init(GPIOA, &GPIO_InitStructure);	//初始化GPIO
	
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;
	GPIO_Init(GPIOA, &GPIO_InitStructure);	//初始化GPIO
	
	//Usart2 NVIC 配置
	NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;      
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;         
    NVIC_Init(&NVIC_InitStructure); 

	
	//USART2配置
	USART_InitStructure.USART_BaudRate = bound;	                //设置串口波特率
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;	//字长为8
	USART_InitStructure.USART_StopBits = USART_StopBits_1;	    //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_ITConfig(USART2, USART_IT_RXNE, ENABLE);//配置了接收中断中断
	USART_ITConfig(USART2, USART_IT_IDLE, ENABLE);//配置了总线空闲中断
	
	USART_Init(USART2, &USART_InitStructure);     //配置USART参数
	USART_Cmd(USART2, ENABLE);                    //使能USART
}


void USART2_IRQHandler(void)
{   
    u8 ucCh;

    if(USART_GetITStatus( USART2, USART_IT_RXNE ) != RESET )
    {
        ucCh  = USART_ReceiveData( USART2 );	  
	    USART_SendData(USART3,ucCh); /需配置了串口三方可打印

        /**下面这一部分用于接收WiFi模块传回的信息存储**/
        if(ESP8266_Fram_Record_Struct .InfBit .FramLength < ( RX_BUF_MAX_LEN - 1 ) ) 
        {           
            ESP8266_Fram_Record_Struct .Data_RX_BUF[ ESP8266_Fram_Record_Struct .InfBit .FramLength ++ ]  = ucCh;   
        }                			
    }

    if( USART_GetITStatus( USART2, USART_IT_IDLE ) == SET ) //如果总线空闲
    {
	    u8 temp = 0;

		/**接收WiFi传输完成的标志位**/
        ESP8266_Fram_Record_Struct .InfBit .FramFinishFlag = 1;	

        ucCh = USART_ReceiveData( USART2 );                  //由软件序列清除中断标志位(先读USART_SR,然后读USART_DR),作用等同下面清除IDLE中断标志位的方式,只要读一次字节就能清除			  
		//USART_SendData(USART3,ucCh);                         //输出最后一个字节,测试时用于检测,可删除			
	    //USART_ClearFlag(USART2,USART_FLAG_IDLE);                //清除串口空闲中断标志位(两者选一)
	    //temp = USART2->SR;
        //temp = USART2->DR;
			
        /**作为AT指令设置过程中的一个检测手段**/
        TcpClosedFlag = strstr ( ESP8266_Fram_Record_Struct .Data_RX_BUF, "CLOSED\r\n" ) ? 1 : 0;
    } 
}

串口配置说明一下:无论是串口二还是串口三的配置,在网上都是已成熟的模板,我的只是其中一小个例子,大家也可以参考其他博主的配置,我需要解释一下就是空闲中断和接收中断。

①接收中断(作为信息开始的标志):因为串口的传输是按位传输的,所以我们的开始就是只要接收到就进入中断,然后每一次都存储在数组里(涉及到后面提取上位机通讯的信息)。

②空闲中断(作为信息结束的标志):因为要涉及到处理上位机的信息,那么什么时候处理,这时候就是空闲的时候出去标志位,然后返回到对应的处理函数去处理,可以保证信息接收的完整性和及时性。

注意:USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);//配置了接收中断中断
           USART_ITConfig(USART2, USART_IT_IDLE, ENABLE);//配置了总线空闲中断

           这两个家伙不可以这样子写:

           USART_ITConfig(USART2, USART_IT_RXNE|USART_ IT_IDLE, ENABLE),否则会出现导致空闲中断没有打开,当然大家可以尝试一下。

当配置完了,就可以进行AT指令的测试了,我们今天只需要测试到WiFi模块是否可以正常执行!


AT测试

我们可以了解到WiFi模块有三个模式:STA、AP、STA+AP,以STA来一步步演示测试。

首先解释下STA模式,这是个需要联网的,我们以电脑作为主机服务器,单片机作为客机服务器。

我先上代码,需要四个代码,这是基本配置,代码并非我所原创,已经是很久以前的了,不知道当时是哪位博主大大分享的,大家也可以参考其他大佬的代码。

esp8266.h

#ifndef __ESP8266_H
#define __ESP8266_H 			   
#include "stm32f10x.h"

#include <stdio.h>
#include <string.h>
#include <stdbool.h>

#if defined ( __CC_ARM   )
#pragma anon_unions
#endif

//ESP8266模式选择
typedef enum
{
    STA,
    AP,
    STA_AP  
}ENUM_Net_ModeTypeDef;

//网络传输层协议,枚举类型
typedef enum{
     enumTCP,
     enumUDP,
} ENUM_NetPro_TypeDef;
//连接号,指定为该连接号可以防止其他计算机访问同一端口而发生错误
typedef enum{
    Multiple_ID_0 = 0,
    Multiple_ID_1 = 1,
    Multiple_ID_2 = 2,
    Multiple_ID_3 = 3,
    Multiple_ID_4 = 4,
    Single_ID_0 = 5,
} ENUM_ID_NO_TypeDef;

#define ESP8266_RST_Pin          GPIO_Pin_4    //复位管脚
#define ESP8266_RST_Pin_Port     GPIOA    //复位 
#define ESP8266_RST_Pin_Periph_Clock  RCC_APB2Periph_GPIOA       //复位时钟

#define ESP8266_CH_PD_Pin     GPIO_Pin_5   //使能管脚
#define ESP8266_CH_PD_Pin_Port     GPIOA   //使能端口
#define ESP8266_CH_PD_Pin_Periph_Clock  RCC_APB2Periph_GPIOA                     //使能时钟


#define ESP8266_RST_Pin_SetH     GPIO_SetBits(ESP8266_RST_Pin_Port,ESP8266_RST_Pin)
#define ESP8266_RST_Pin_SetL     GPIO_ResetBits(ESP8266_RST_Pin_Port,ESP8266_RST_Pin)


#define ESP8266_CH_PD_Pin_SetH     GPIO_SetBits(ESP8266_CH_PD_Pin_Port,ESP8266_CH_PD_Pin)
#define ESP8266_CH_PD_Pin_SetL     GPIO_ResetBits(ESP8266_CH_PD_Pin_Port,ESP8266_CH_PD_Pin)


#define ESP8266_USART(fmt, ...)  USART_printf (USART2, fmt, ##__VA_ARGS__)    
#define PC_USART(fmt, ...)       printf(fmt, ##__VA_ARGS__)       //这是串口打印函数,串口1,执行printf后会自动执行fput函数,重定向了printf。



#define RX_BUF_MAX_LEN 1024       //最大字节数
extern struct STRUCT_USART_Fram   //数据帧结构体
{
    char Data_RX_BUF[RX_BUF_MAX_LEN];
    union 
    {
        __IO u16 InfAll;
        struct 
        {
            __IO u16 FramLength       :15;                               // 14:0 
            __IO u16 FramFinishFlag   :1;                                // 15 
        }InfBit;
    }; 
	
}ESP8266_Fram_Record_Struct;


//初始化和TCP功能函数
void ESP8266_Init(u32 bound);
void ESP8266_AT_Test(void);
bool ESP8266_Send_AT_Cmd(char *cmd,char *ack1,char *ack2,u32 time);
void ESP8266_Rst(void);
bool ESP8266_Net_Mode_Choose(ENUM_Net_ModeTypeDef enumMode);
bool ESP8266_JoinAP( char * pSSID, char * pPassWord );
bool ESP8266_Enable_MultipleId ( FunctionalState enumEnUnvarnishTx );
bool ESP8266_Link_Server(ENUM_NetPro_TypeDef enumE, char * ip, char * ComNum, ENUM_ID_NO_TypeDef id);
bool ESP8266_SendString(FunctionalState enumEnUnvarnishTx, char * pStr, u32 ulStrLength, ENUM_ID_NO_TypeDef ucId );
bool ESP8266_UnvarnishSend ( void );
void ESP8266_ExitUnvarnishSend ( void );
u8 ESP8266_Get_LinkStatus ( void );
void USART_printf( USART_TypeDef * USARTx, char * Data, ... );

#endif

esp8266.c

#include "esp8266.h"
#include "usart.h"
#include "delay.h"
#include <stdarg.h>

struct STRUCT_USART_Fram ESP8266_Fram_Record_Struct = { 0 };  //定义了一个数据帧结构体
void ESP8266_Init(u32 bound)
{
    GPIO_InitTypeDef GPIO_InitStructure;

    RCC_APB2PeriphClockCmd(ESP8266_RST_Pin_Periph_Clock|ESP8266_CH_PD_Pin_Periph_Clock, ENABLE);

    GPIO_InitStructure.GPIO_Pin = ESP8266_RST_Pin;             
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;     //复用推挽输出
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;    
    GPIO_Init(ESP8266_RST_Pin_Port, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin = ESP8266_CH_PD_Pin;               
    GPIO_Init(ESP8266_CH_PD_Pin_Port, &GPIO_InitStructure);

    uart2_Init(bound); 
	  ESP8266_Rst();
}
//对ESP8266模块发送AT指令
// cmd 待发送的指令
// ack1,ack2;期待的响应,为NULL表不需响应,两者为或逻辑关系
// time 等待响应时间
//返回1发送成功, 0失败
bool ESP8266_Send_AT_Cmd(char *cmd,char *ack1,char *ack2,u32 time)
{ 
    ESP8266_Fram_Record_Struct .InfBit .FramLength = 0; //重新接收新的数据包
    ESP8266_USART("%s\r\n", cmd);
    if(ack1==0&&ack2==0)     //不需要接收数据
    {
    return true;
    }
    delay_ms(time);   //延时
		delay_ms(1000);
    ESP8266_Fram_Record_Struct.Data_RX_BUF[ESP8266_Fram_Record_Struct.InfBit.FramLength ] = '\0';
		
    printf("%s",ESP8266_Fram_Record_Struct .Data_RX_BUF);
    if(ack1!=0&&ack2!=0)
    {
        return ( ( bool ) strstr ( ESP8266_Fram_Record_Struct .Data_RX_BUF, ack1 ) || 
                         ( bool ) strstr ( ESP8266_Fram_Record_Struct .Data_RX_BUF, ack2 ) );
    }
    else if( ack1 != 0 )  //strstr(s1,s2);检测s2是否为s1的一部分,是返回该位置,否则返回false,它强制转换为bool类型了
        return ( ( bool ) strstr ( ESP8266_Fram_Record_Struct .Data_RX_BUF, ack1 ) );

    else
        return ( ( bool ) strstr ( ESP8266_Fram_Record_Struct .Data_RX_BUF, ack2 ) );

}


//复位重启
void ESP8266_Rst(void)
{
    ESP8266_RST_Pin_SetL;
    delay_ms(500); 
    ESP8266_RST_Pin_SetH;
}


//发送恢复出厂默认设置指令将模块恢复成出厂设置
void ESP8266_AT_Test(void)
{
    char count=0;
    delay_ms(1000); 
    while(count < 10)
    {
        if(ESP8266_Send_AT_Cmd("AT+RESTORE","OK",NULL,500)) 
        {
            printf("OK\r\n");
            return;
        }
        ++ count;
    }
}


//选择ESP8266的工作模式
// enumMode 模式类型
//成功返回true,失败返回false
bool ESP8266_Net_Mode_Choose(ENUM_Net_ModeTypeDef enumMode)
{
    switch ( enumMode )
    {
        case STA:
            return ESP8266_Send_AT_Cmd ( "AT+CWMODE=1", "OK", "no change", 2500 ); 

        case AP:
            return ESP8266_Send_AT_Cmd ( "AT+CWMODE=2", "OK", "no change", 2500 ); 

        case STA_AP:
            return ESP8266_Send_AT_Cmd ( "AT+CWMODE=3", "OK", "no change", 2500 ); 

        default:
          return false;
    }       
}


//ESP8266连接外部的WIFI
//pSSID WiFi帐号
//pPassWord WiFi密码
//设置成功返回true 反之false
bool ESP8266_JoinAP( char * pSSID, char * pPassWord)
{
    char cCmd [120];
	
    sprintf ( cCmd, "AT+CWJAP=\"%s\",\"%s\"", pSSID, pPassWord );
    return ESP8266_Send_AT_Cmd( cCmd, "OK", NULL, 5000 );
}

//ESP8266 多人连接使能
//enumEnUnvarnishTx  是否多连接,bool类型
//设置成功返回true,反之false
bool ESP8266_Enable_MultipleId (FunctionalState enumEnUnvarnishTx )
{
    char cStr [20];

    sprintf ( cStr, "AT+CIPMUX=%d", ( enumEnUnvarnishTx ? 1 : 0 ) );

    return ESP8266_Send_AT_Cmd ( cStr, "OK", 0, 500 );

}


//ESP8266 连接服务器
//enumE  网络类型
//ip ,服务器IP
//ComNum  服务器端口
//id,连接号,确保通信不受外界干扰
//设置成功返回true,反之fasle
bool ESP8266_Link_Server(ENUM_NetPro_TypeDef enumE, char * ip, char * ComNum, ENUM_ID_NO_TypeDef id)
{
    char cStr [100] = { 0 }, cCmd [120];

    switch (  enumE )
    {
        case enumTCP:
          sprintf ( cStr, "\"%s\",\"%s\",%s", "TCP", ip, ComNum );
          break;

        case enumUDP:
          sprintf ( cStr, "\"%s\",\"%s\",%s", "UDP", ip, ComNum );
          break;

        default:
            break;
    }

    if ( id < 5 )
        sprintf ( cCmd, "AT+CIPSTART=%d,%s", id, cStr);

    else
        sprintf ( cCmd, "AT+CIPSTART=%s", cStr );

    return ESP8266_Send_AT_Cmd ( cCmd, "OK", "ALREAY CONNECT", 4000 );

}


//透传使能
//设置成功返回true, 反之false
bool ESP8266_UnvarnishSend ( void )
{
    if (!ESP8266_Send_AT_Cmd ( "AT+CIPMODE=1", "OK", 0, 500 ))
        return false;

    return 
        ESP8266_Send_AT_Cmd( "AT+CIPSEND", "OK", ">", 500 );

}


//ESP8266发送字符串
//enumEnUnvarnishTx是否使能透传模式
//pStr字符串
//ulStrLength字符串长度
//ucId 连接号
//设置成功返回true, 反之false
bool ESP8266_SendString(FunctionalState enumEnUnvarnishTx, char * pStr, u32 ulStrLength, ENUM_ID_NO_TypeDef ucId )
{
    char cStr [20];
    bool bRet = false;


    if ( enumEnUnvarnishTx )
    {
        ESP8266_USART ( "%s", pStr );

        bRet = true;

    }

    else
    {
        if ( ucId < 5 )
            sprintf ( cStr, "AT+CIPSEND=%d,%d", ucId, ulStrLength + 2 );

        else
            sprintf ( cStr, "AT+CIPSEND=%d", ulStrLength + 2 );

        ESP8266_Send_AT_Cmd ( cStr, "> ", 0, 1000 );

        bRet = ESP8266_Send_AT_Cmd ( pStr, "SEND OK", 0, 1000 );
  }

    return bRet;

}


//ESP8266退出透传模式
void ESP8266_ExitUnvarnishSend ( void )
{
    delay_ms(1000);
    ESP8266_USART( "+++" );
    delay_ms( 500 );    
}


//ESP8266 检测连接状态
//返回0:获取状态失败
//返回2:获得ip
//返回3:建立连接 
//返回4:失去连接 
u8 ESP8266_Get_LinkStatus ( void )
{
    if (ESP8266_Send_AT_Cmd( "AT+CIPSTATUS", "OK", 0, 500 ) )
    {
        if ( strstr ( ESP8266_Fram_Record_Struct .Data_RX_BUF, "STATUS:2\r\n" ) )
            return 2;

        else if ( strstr ( ESP8266_Fram_Record_Struct .Data_RX_BUF, "STATUS:3\r\n" ) )
            return 3;

        else if ( strstr ( ESP8266_Fram_Record_Struct .Data_RX_BUF, "STATUS:4\r\n" ) )
            return 4;       

    }

    return 0;
}

static char *itoa( int value, char *string, int radix )
{
    int     i, d;
    int     flag = 0;
    char    *ptr = string;

    /* This implementation only works for decimal numbers. */
    if (radix != 10)
    {
        *ptr = 0;
        return string;
    }

    if (!value)
    {
        *ptr++ = 0x30;
        *ptr = 0;
        return string;
    }

    /* if this is a negative value insert the minus sign. */
    if (value < 0)
    {
        *ptr++ = '-';

        /* Make the value positive. */
        value *= -1;

    }

    for (i = 10000; i > 0; i /= 10)
    {
        d = value / i;

        if (d || flag)
        {
            *ptr++ = (char)(d + 0x30);
            value -= (d * i);
            flag = 1;
        }
    }

    /* Null terminate the string. */
    *ptr = 0;

    return string;

} /* NCL_Itoa */


void USART_printf ( USART_TypeDef * USARTx, char * Data, ... )
{
    const char *s;
    int d;   
    char buf[16];


    va_list ap;
    va_start(ap, Data);

    while ( * Data != 0 )     // 判断数据是否到达结束符
    {                                         
        if ( * Data == 0x5c )  //'\'
        {                                     
            switch ( *++Data )
            {
                case 'r':                                     //回车符
                USART_SendData(USARTx, 0x0d);
                Data ++;
                break;

                case 'n':                                     //换行符
                USART_SendData(USARTx, 0x0a);   
                Data ++;
                break;

                default:
                Data ++;
                break;
            }            
        }

        else if ( * Data == '%')
        {                                     
            switch ( *++Data )
            {               
                case 's':                                         //字符串
                s = va_arg(ap, const char *);
                for ( ; *s; s++) 
                {
                    USART_SendData(USARTx,*s);
                    while( USART_GetFlagStatus(USARTx, USART_FLAG_TXE) == RESET );
                }
                Data++;
                break;

                case 'd':           
                    //十进制
                d = va_arg(ap, int);
                itoa(d, buf, 10);
                for (s = buf; *s; s++) 
                {
                    USART_SendData(USARTx,*s);
                    while( USART_GetFlagStatus(USARTx, USART_FLAG_TXE) == RESET );
                }
                     Data++;
                     break;
                default:
                     Data++;
                     break;
            }        
        }
        else USART_SendData(USARTx, *Data++);
        while ( USART_GetFlagStatus ( USARTx, USART_FLAG_TXE ) == RESET );

    }
}

tcp.h

#ifndef __TCP_H
#define __TCP_H 	

#include "stm32f10x.h"


/*
*以下参数需要用户自行修改才能测试用过
*/

#define User_ESP8266_SSID     "219"          //wifi名
#define User_ESP8266_PWD      "219219219"      //wifi密码

#define User_ESP8266_TCPServer_IP     "10.60.106.165"     //服务器IP
#define User_ESP8266_TCPServer_PORT   "8888"      //服务器端口号


extern volatile uint8_t TcpClosedFlag;  //连接状态标志
extern u8 connect_flag;
extern u8 res;
extern char str[100];
void ESP8266_STA_TCPClient_Test(void);


#endif

tcp.c

#include "tcp.h"
#include "usart.h"
#include "esp8266.h"
#include "delay.h"
#include "stdio.h"
#include "string.h"
#include "stm32f10x.h"

volatile u8 TcpClosedFlag = 0;
u8 connect_flag = 0;
u8 rv_buff = 0;
u8 res = 0;
char str[100]= {0};

void ESP8266_STA_TCPClient_Test(void)
{   
    ESP8266_AT_Test();
    printf("正在设置 ESP8266\r\n");
    ESP8266_Net_Mode_Choose(STA);
    while(!ESP8266_JoinAP(User_ESP8266_SSID, User_ESP8266_PWD));
    ESP8266_Enable_MultipleId ( DISABLE );
    while(!ESP8266_Link_Server(enumTCP, User_ESP8266_TCPServer_IP,     User_ESP8266_TCPServer_PORT, Single_ID_0));
    while(!ESP8266_UnvarnishSend());
    printf("\r\nTCP 设置完成");	
	  
	ESP8266_Fram_Record_Struct .InfBit .FramLength = 0;
    ESP8266_Fram_Record_Struct .InfBit .FramFinishFlag = 0;	
	
    sprintf (str,"HALLE WORLD" );//格式化发送字符串到TCP服务器
    ESP8266_SendString ( ENABLE, str, 0, Single_ID_0 ); 
    // USART_Cmd(USART3, DISABLE);//关闭打印测试端口,避免占用资源
	connect_flag = 2;	 	
	
    GPIO_SetBits(GPIOB,GPIO_Pin_0);
	delay_ms(1000);	
	GPIO_ResetBits(GPIOB,GPIO_Pin_0);
}

说明一下:延迟函数我没有上传,因为大家的配置都不一样!!

主要是以这一份代码,来梳理一下STA模式,以及后续MQTT需要连接服务器做准备。

①先看esp8266.h里面的两个宏定义:

#define ESP8266_USART(fmt, ...)    USART_printf (USART2, fmt, ##__VA_ARGS__)    
#define PC_USART(fmt, ...)               printf(fmt, ##__VA_ARGS__)     

第一个是串口二输出函数重定义,使得我们只需要通过ESP8266_USART(fmt, ...)即可通过串口二发送数据给WiFi模块,这个函数每一个人的写法都不一样(在esp8266.c中)。

第二个是串口三的重定向,简单来说我们只要执行printf就会自动执行fput函数,从而可以通过串口助手查看输出的信息(具体的重定向,大家可以看看其他博主的解释,因为keil版本的更替,在这个重定向上面,由于内核不同,每一次移植都会出现不同的bug)

②ESP8266_Send_AT_Cmd(...);该函数是执行单片机发送信息到WiFi模块功能,每个指令的发送都经过,该函数的每一个参数都有注释在代码里。

**①②两者缺一不可,写的方式可以有多种,但必须要有!!!

接下来那么我们开始尝试配置。

1.  ESP8266_AT_Test();这个函数是WiFi模块恢复出厂设置的函数,我们也可以用其检测esp8266是否正常工作。发送的指令是“AT+RESTORE”,WiFi模块的回复是“OK”。下面是串口打印出来数据,可以看到模块的信息,那证明可以没有问题。

【毕设调试一】WiFi模块esp8266的调试  

2. ESP8266_Net_Mode_Choose(STA);该函数用于选择模式,这里我们选择STA模式。

    AT+CWMODE=1,WiFi模块的回复是“OK”。(1:STA,2:AP,3:STA+AP)

【毕设调试一】WiFi模块esp8266的调试

3. 开始进入正戏: while(!ESP8266_JoinAP(User_ESP8266_SSID, User_ESP8266_PWD));

   解释:  User_ESP8266_SSID wifi或热点的名字

             User_ESP8266_PWD wifi或热点的密码

   这一步是加入网络:AT+CWJAP=\"%s\",\"%s\",两个%s就是名字和密码。

   失败就不断的识别,一直不成功就一直识别:

【毕设调试一】WiFi模块esp8266的调试             成功,返回OK:【毕设调试一】WiFi模块esp8266的调试

4. ESP8266_Enable_MultipleId ( DISABLE );这一步是设置多人连接,简单直白就是,只能我自  己连。发送指令 AT+CIPMUX= (1或者0),WiFi模块的回复是“OK”。【毕设调试一】WiFi模块esp8266的调试

5. 这一步就是重中之重了,连接服务器。

while(!ESP8266_Link_Server(enumTCP, User_ESP8266_TCPServer_IP, User_ESP8266_TCPServer_PORT, Single_ID_0));

解释:     enumTCP     网络传输层协议

             User_ESP8266_TCPServer_IP   IP地址

             User_ESP8266_TCPServer_PORT    端口号

             Single_ID_0   连接号

我们使用电脑的网络调试助手来模拟这个服务器

【毕设调试一】WiFi模块esp8266的调试

协议同样是TCP Server ,本地主机地址是大家自己电脑联网后的IPV4地址,端口号自行设置。

这三个分别就对应到代码里面的TCP,User_ESP8266_TCPServer_IP,User_ESP8266_TCPServer_PORT

只有IP是需要更改的,因为每一个用户都不同。

发送指令是AT+CIPSTART=%s,因为在代码里面已经将这三个都整合一起了

如图示:【毕设调试一】WiFi模块esp8266的调试

当然同时要打开网络调试助手,否则无法连接上就会一直打印:【毕设调试一】WiFi模块esp8266的调试

当然你打开了,同样也会连不上!!!(咆哮!!!!草!!!!)

它需要关闭你电脑的防火墙!!!!!!!!!!!!!!!!!!

我也解释不了为啥,当时调了N久,也是查看了很多博主,看到的一条留言说如果关掉了就可以连接上了!!

成功打印:【毕设调试一】WiFi模块esp8266的调试

同时助手显示:【毕设调试一】WiFi模块esp8266的调试

6. while(!ESP8266_UnvarnishSend());打开透传模式,简答来说就是网络调试助手发送什么就所 接收什么打印什么(固定的模式)。

成功:【毕设调试一】WiFi模块esp8266的调试

随后就是TCP配置完成,从单片机发送一个"HELLO WORLD"到助手:【毕设调试一】WiFi模块esp8266的调试

 同时也可以从网络调试助手发送信息到单片机并打印:

【毕设调试一】WiFi模块esp8266的调试

STA的设置基本到这里就已经完成了,如果需要到物联网连接云服务器,我们还需要很多的工作,而我最开始并没想使用物联网控制的,因为我并不需要提取信息,我只需要到上位机的控制信息,所以我最开始完成调试的版本是使用AP模式(热点模式)来控制的,因此接下来下一篇我会讲到我调试AP模式,以及使用可视化网站来制作一个简单的APP来控制单片机。

我只是个小白,此文只是想分享下自己在毕设调试过程中遇到的坑,仅供参考,如有错误,请各位大佬不吝赐教!!!

 文章来源地址https://www.toymoban.com/news/detail-445537.html

 

 

 

 

 

 

到了这里,关于【毕设调试一】WiFi模块esp8266的调试的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • ESP8266 WIFI 模块和手机通信

    随着物联网智能化的不断发展,越来越多人选择了无线通信设备,比如WiFi、蓝牙、Lora、zigbee、2G/4G模块等物联网无线通信模块,从而可以更好地达到无线控制目的。 1.这款调试助手支持的功能比较齐全,可以自行到手机应用市场下载。 2.串口调试助手用的是正点原子提供的

    2024年02月06日
    浏览(44)
  • STM32-连接wifi模块(esp8266)

    目录 1. ESP8266模块介绍 1.1. 系统结构图 1.2. 功能介绍  1.3. AT指令说明  2. STM32连接ESP8266 3. ESP8266示例 3.1. ESP8266透传模式  3.2. ESP8266上传数据例程 乐鑫智能互联平台——ESP8266 拥有高性能无线 SOC,是一个完整且自成体系的 WiFi 网络解决方案,能够独立运行,也可以作为 slave 搭

    2024年01月16日
    浏览(63)
  • 物联网智能网关(ESP8266WIFI模块)

    一、温湿度和光敏数据采集。要求:采集ESP8266平台中温湿度传感器与光敏电阻的数据并传输至网页端显示。 (1)分别对应温湿度传感器及光敏传感器的功能绘制或展示硬件连接原理图并简单说明。   光敏电路:光敏电路,实现感光效果   温湿度(DHT11)电路:测量温湿度

    2023年04月22日
    浏览(51)
  • <ESP8266>WIFI模块AT指令浅学

    人生如逆旅,我亦是行人。 缩写 意思 AT(automatic transmission) 自动变速器 WiFi 无线网 AP(Access Point) 无线访问接入点,无线路由器等类设备的统称 AP 模式 无线接入点模式 RST(TCP协议的 6 个标志之一) 表示重置连接、复位连接 TCP 传输控制协议 UDP 用户数据报协议 SSL 安全套

    2024年02月04日
    浏览(60)
  • esp8266WiFi模块通过MQTT连接华为云

    最近 突然想做物联网的项目,做一个类似远程控制家里的设备,比如控制灯,电视机,空调这样的,同时能够将家里的温湿度等信息可以实时上传到手机里。 刚开始认为这个不就是一个很简单的项目嘛, 几个小时 之内就能做出来,可是没想到诸事不顺,遇到各种各样的bu

    2023年04月20日
    浏览(57)
  • stm32 的 ESP8266 wifi 模块 (ESP - 12s) 的使用

    1. ESP8266 的器件介绍 2. ESP2866外设  的引脚  3. 我所用的的ESP2866 的引脚图 4. 代码 编程的串口 5.wifi 的指令 1. AT     测试指令 2. AT+RST   重启模块 3. AT+GMR  查看版本信息 4. AT+RESTORE   恢复出厂设置 5.  AT+UART=115200,8,1,0,0   串口设置  串口号, 数据位, 停止位,  6. 

    2024年02月02日
    浏览(54)
  • ESP8266WIFI模块(ESP01)上云端(OneNet平台,HTTP)

    1.注册账号并登录 Onenet平台 2.打开控制台 3.在控制台点击全部产品,选择基础服务的多协议接入 4.选择·HTTP并点击添加产品。 5.填写产品信息,名称随便起,行业任选一个,类别也任选,联网方式选择wifi 6.添加设备 并填写设备名称,随便起名个字,随便输入编号,但是同一

    2024年02月04日
    浏览(53)
  • 【STM32训练—WiFi模块】第二篇、STM32驱动ESP8266WiFi模块获取天气

    目录 第一部分、前言 1、获取心知天气API接口 2、硬件准备 第二部分、电脑串口助手调试WIFI模块获取天气 1、ESP8266获取天气的流程 2、具体步骤 第三部分、STM32驱动ESP8266模块获取天气数据 1、天气数据的解析 1.1、什么函数来解析天气数据? 2.1、解析后的数据如何使用?  2、

    2024年02月09日
    浏览(44)
  • 基于stm32 ESP8266WiFi模块的基本通信

    本篇涉及到的模块与工具为: 1. ATK-ESP8266wifi模块 2. USB-UART模块 3. 串口调试助手 提取链接:https://pan.baidu.com/s/17xRlpnjp8j-VvyD2VDxNXw?pwd=ufms 提取码:ufms 4. 网络调试助手 提取链接:https://pan.baidu.com/s/10spxZmwMGI70USlzkOzdxg?pwd=fmxe 提取码:fmxe 程序源码提取连接放置文章底部,需者自提

    2024年02月02日
    浏览(88)
  • esp8266WIFI模块教程:ATK-ESP8266——TCP网络通讯和服务器连接

      ATK-MW8266D 模块是正点原子推出的一款高性能 UART-WIFI(串口-无线)模块,ATK-MW8266D 模块板载了正点原子公司自主研发的 ATK-ESP-01 模块,该模块通过 FCC、CE 认证,可直接用于出口欧美地区的产品。   ATK-MW8266D 模块采用串口(LVTTL)与 MCU(或其他串口设备)通讯,且内置

    2024年04月15日
    浏览(45)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包