STM32f103ZET6之ESP8266模塊

一、ESP8265概述

????????官方網址:ESP8266 Wi-Fi MCU I 樂鑫科技 (espressif.com.cn)

????????ESP8266模塊---wifi模塊
????????產品特點:

ESP8266 是什么?

????????ESP8266 是由樂鑫科技(Espressif Systems)開發的一款低成本、高性能的 Wi-Fi 微控制器芯片 / 模塊,集成了 32 位 Tensilica L106 處理器、Wi-Fi 射頻(802.11 b/g/n)、TCP/IP 協議棧,以及豐富的 GPIO 引腳和外設接口(I2C、SPI、UART 等)。

????????

????????它的核心優勢是 **“低成本實現 Wi-Fi 聯網”**—— 相比傳統的 “MCU + 獨立 Wi-Fi 模塊” 方案,ESP8266 直接將處理器和 Wi-Fi 功能集成,成本可低至幾美元,且體積小巧(常見模塊如 ESP-12F 尺寸僅 24mm×16mm),因此成為物聯網(IoT)領域的 “明星產品”。

ESP8266 能干什么?

ESP8266 的核心功能是 **“讓設備接入 Wi-Fi 網絡”**,因此被廣泛用于需要聯網的場景,典型應用包括:

  • 物聯網(IoT)設備:如智能傳感器(溫濕度、光照、煙霧傳感器)的數據上傳(發送到云端服務器或手機);
  • 智能家居:控制燈光、窗簾、空調等設備(通過 Wi-Fi 接收手機 APP 指令);
  • 遠程監控:連接攝像頭或傳感器,實時向手機推送數據;
  • Wi-Fi 網關:將其他協議(如藍牙、ZigBee)的設備數據轉換為 Wi-Fi 信號轉發;
  • 簡易服務器:作為小型 Web 服務器,通過瀏覽器直接控制設備(例如網頁按鈕控制燈光開關)。

1. ESP8266中的wifi:

? ? ? ? ?ESP8266EX支持TCP/IP協議,完全遵循802.11 b/g/n WLAN MAC協議,支持分布式控制功能(DCF)下的基本服務集(BSS)STA和SoftAP操作。支持通過最小化主機交互來優化有效工作時長,以實現功耗管理。

? ? ? ? ?我們主要使用esp8266的wifi功能:

2.AT指令集的概念:

????????AT指令是應用于終端設備與PC應用之間的連接與通信的指令。AT Attention。每個AT命令行中只能 包含一條AT指令;對于AT指令的發送,除AT兩個字符外,最多可以接收1056個字符的長度(包括最后的空字符)。
????????格式: AT + CMD

3. ESP8266引腳:

?需要配置的引腳:

1. 復位:

2. 使能管腳:

3.? 電源部分:

4.? 串口

以下為單片機與ESP8266的連接方式:

啟動模式:

?????????程序正常運行,我們需要保證使能位和RST,必須拉高

二、ESP8266的聯網步驟

步驟AT 指令(串口發送)期望返回作用說明
1AT+CWMODE=1OK設為 STA 模式
2AT+RST重啟日志 +?ready?+?OK重啟生效模式
3AT+CWJAP="MyWiFi","1234"WIFI CONNECTED
WIFI GOT IP
OK
連 Wi-Fi 成功
4AT+CIPMUX=0OK設為單連接模式
5AT+CIPSTART="TCP","192.168.1.100",8888CONNECT OK連 TCP 服務器成功
6AT+CIPMODE=1OK開透傳模式
7AT+CIPSEND>進入透傳,可直接發數據
8Hello Server!(無返回,直接傳給服務器)透傳數據
9+++(發之前停 1 秒)OK退出透傳,切回 AT 指令模式

1.?AT+CWMODE=1:設置工作模式(STA 模式)

  • 作用:讓 ESP8266 作為「Station(站點)」,即像手機、電腦一樣,去連接外部 Wi-Fi 熱點。
  • 模式說明
    • Station:用作客戶端,是需要連接路由器或者熱點
      SoftAP:用作服務器端,本身可以作為熱點使用
      SoftAP+Station:混合模式。
  • 實操
    串口發送?AT+CWMODE=1,收到?OK?則設置成功。

2.?AT+RST:模塊重啟(讓工作模式生效)
  • 作用:ESP8266 是 “單片機思維”,改完模式后需重啟才能真正切換。
  • 細節
    發送?AT+RST?后,模塊會重啟,串口會打印一堆啟動日志(如?ready?等),最后回到可接收 AT 指令狀態。

3.?AT+CWJAP="SSID","PASSWORD":連接 Wi-Fi 熱點

  • 作用:讓 ESP8266 接入你指定的 Wi-Fi 網絡。
  • 參數說明
    • SSID:你要連的 Wi-Fi 名稱(字符串,必須用英文雙引號包裹)
    • PASSWORD:Wi-Fi 密碼(同理,英文雙引號包裹,無密碼則填?""?)
  • 實操
    比如連名為?MyWiFi、密碼?12345678?的 Wi-Fi,發送:
    AT+CWJAP="MyWiFi","12345678"
    
    等待幾秒,收到?WIFI CONNECTED(連成功) +?WIFI GOT IP(分配到 IP) +?OK,則聯網完成。

4.?AT+CIPMUX=0:設置單路連接模式

  • 作用:告訴模塊,接下來要建立?1 對 1 的 TCP/UDP 連接(單連接模式)。
  • 模式說明
    • CIPMUX=0:單連接(同一時間只能連 1 個服務器)
    • CIPMUX=1:多連接(可同時連多個服務器,需配合?AT+CIPSERVER?等指令)
  • 何時用
    如果你只是想連一個服務器(比如傳數據到自己的云平臺),選?0?更簡單。

5.?AT+CIPSTART="TCP","IP地址",端口號:建立 TCP 連接

  • 作用:讓 ESP8266 主動連到你指定的 TCP 服務器(比如自己電腦開的 TCP 服務、云平臺)。
  • 參數說明
    • TCP:協議類型(也支持?UDP,按需換)
    • IP地址:服務器的公網 / 局域網 IP(比如本地調試填?192.168.1.100,云平臺填?47.xxx.xxx.xxx?)
    • 端口號:服務器監聽的端口(如?8080?3333,需和服務器程序對應)
  • 實操
    比如連本地電腦(IP?192.168.1.100,端口?8888)的 TCP 服務,發送:
    AT+CIPSTART="TCP","192.168.1.100",8888
    
    收到?CONNECT OK?則連接成功,失敗會返回?CONNECT FAIL(檢查 IP、端口、服務器是否開啟)。

6.?AT+CIPMODE=1:開啟透傳模式

  • 作用:進入「透傳」狀態 —— 你從串口發的所有數據,會直接透傳給 TCP/UDP 服務器,無需額外加指令頭(反之,服務器發的數據也會直接返回串口)。
  • 對比普通模式
    • 普通模式(CIPMODE=0)發數據,需先?AT+CIPSEND=長度,再發內容(麻煩);
    • 透傳模式(CIPMODE=1)發數據,直接敲內容就行(簡單,適合持續傳數據)。

7.?AT+CIPSEND:進入透傳數據發送

  • 作用:在透傳模式下,執行這條指令后,模塊進入 “數據直通” 狀態。
  • 實操
    發送?AT+CIPSEND?后,串口會返回?>,此時你輸入的任何內容(比如?Hello Server!?),都會直接通過 TCP 發給服務器,無需額外處理。

8.?+++:退出透傳模式
  • 作用:從透傳狀態切回 “AT 指令模式”,方便你發其他 AT 指令(比如斷網、改配置)。
  • 關鍵細節
    發?+++?時,必須保證串口沒有其他數據同時發送(即發?+++?前后,要等 1 秒左右無數據,否則模塊可能識別成普通數據)。
    成功退出后,串口會返回?OK,此時可繼續發?AT+CWQAP(斷開 Wi-Fi)等指令。

?

三、具體代碼案例

1.esp8266.c:

#include "esp8266.h"
#include "delay.h"
#include "stdio.h"
#include "string.h"
#include "esp_data.h"
//配置串口+ESP8266使能和復位
void usart3_Init(u32 brr)
{GPIO_InitTypeDef GPIOInitTypeDef;USART_InitTypeDef USARTInitTypeDef;//打開時鐘RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3,ENABLE);//配置PB10--TX PB11--RX//PB10--復用推挽輸出GPIOInitTypeDef.GPIO_Pin=GPIO_Pin_10;GPIOInitTypeDef.GPIO_Mode=GPIO_Mode_AF_PP;GPIOInitTypeDef.GPIO_Speed=GPIO_Speed_50MHz;GPIO_Init(GPIOB,&GPIOInitTypeDef);//PB11--浮空GPIOInitTypeDef.GPIO_Pin=GPIO_Pin_11;GPIOInitTypeDef.GPIO_Mode=GPIO_Mode_IN_FLOATING;GPIO_Init(GPIOB,&GPIOInitTypeDef);//usart3的配置USARTInitTypeDef.USART_BaudRate=brr;USARTInitTypeDef.USART_HardwareFlowControl=USART_HardwareFlowControl_None;USARTInitTypeDef.USART_Mode=USART_Mode_Rx|USART_Mode_Tx;USARTInitTypeDef.USART_Parity=USART_Parity_No;USARTInitTypeDef.USART_StopBits=USART_StopBits_1;USARTInitTypeDef.USART_WordLength=USART_WordLength_8b;USART_Init(USART3,&USARTInitTypeDef);usart3_It_Config();USART_Cmd(USART3,ENABLE);
}
//配置中斷 接收和空閑
void usart3_It_Config(void)
{//設置空閑中斷和接收中斷USART_ITConfig(USART3,USART_IT_RXNE,ENABLE);USART_ITConfig(USART3,USART_IT_IDLE,ENABLE);//NVIC_SetPriority(USART3_IRQn,0);//占先優先級:1 次級優先級:1 NVIC_EnableIRQ(USART3_IRQn);
}void ESP8266_IO_Config(void)
{GPIO_InitTypeDef gpio_initsources;//打開時鐘RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOG,ENABLE);gpio_initsources.GPIO_Pin=GPIO_Pin_13|GPIO_Pin_14;gpio_initsources.GPIO_Mode=GPIO_Mode_Out_PP;gpio_initsources.GPIO_Speed=GPIO_Speed_2MHz;//配置PB5//void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct);GPIO_Init(GPIOG,&gpio_initsources);
}
//聯網流程
u8 Esp8266_AT_test(void)
{//"AT\r\n"char count=0;GPIO_SetBits ( GPIOG, GPIO_Pin_13 );GPIO_SetBits ( GPIOG, GPIO_Pin_14 );printf("\r\nAT測試.....\r\n");delay_ms ( 2000 );while ( count < 10 ){printf("\r\nAT測試次數 %d......\r\n", count);if( ESP8266_Cmd ( "AT", "OK",NULL,500) ){printf("\r\nAT測試啟動成功 %d......\r\n", count);return 1;}//復位以下GPIO_ResetBits ( GPIOG, GPIO_Pin_14 );delay_ms ( 500 ); GPIO_SetBits ( GPIOG, GPIO_Pin_14 );++ count;}return 0;
}
//AT+CWMODE=1
bool ESP8266_SetMode(u8 mode)
{char esp_cmd[100];
//	switch(mode)
//	{
//		case 1:sprintf(esp_cmd,"AT+CWMODE=%d",mode);break;
//		case 2:sprintf(esp_cmd,"AT+CWMODE=%d",mode);break;
//		case 3:sprintf(esp_cmd,"AT+CWMODE=%d",mode);break
//	}
//	sprintf(esp_cmd,"AT+CWMODE=%d",mode);return (ESP8266_Cmd(esp_cmd,"OK",NULL,500));}
//設置聯網熱點
//AT+CWJAP="111","11111111"  
bool ESP8266_SET_HotPort(void)
{char esp_cmd[100];sprintf(esp_cmd,"AT+CWJAP=\"%s\",\"%s\"",WIFI_ID,WIFI_PW);return (ESP8266_Cmd(esp_cmd,"OK",NULL,500));}
//AT+CIPMUX=0--單鏈接
bool ESP8266_Set_CIPmux(u8 cipmux)
{char esp_cmd[100];sprintf(esp_cmd,"AT+CIPMUX=%d",cipmux);return (ESP8266_Cmd(esp_cmd,"OK",NULL,500));}bool ESP8266_Set_CIPSTART(u8 link_id)
{char esp_cmd[100];//整理需要發送的指令格式if(link_id<5){//多鏈接}else {//單鏈接//AT+CIPSTART="TCP","iot.espressif.cn",8000sprintf(esp_cmd,"AT+CIPSTART=\"%s\",\"%s\",%d","TCP",SER_IP,SER_PORT);}return (ESP8266_Cmd(esp_cmd,"OK","ALREADY	CONNECT",500));}u8 ESP8266_Send_Data(void)
{//設置透傳模式if ( ! ESP8266_Cmd ( "AT+CIPMODE=1", "OK", 0, 500 ) )return false;//開始數據傳輸return   //必須接收到  “>”,然后才可以進入透傳模式ESP8266_Cmd ( "AT+CIPSEND", "OK", ">", 500 );
}void ESP8266_NET_Config(void)
{GPIO_SetBits ( GPIOG, GPIO_Pin_13 );//使能ESP8266printf("配置ESP8266聯網流程\r\n");//聯網流程
//	Esp8266_AT_test();while(!Esp8266_AT_test());//printf("正在配置ESP8266模式\r\n");while(!ESP8266_SetMode(1));printf("正在配置WIFI熱點信息\r\n");while(!ESP8266_SET_HotPort());printf("正在配置單鏈接\r\n");while(!ESP8266_Set_CIPmux(0));//printf("正在配置服務器端信息\r\n");while(!ESP8266_Set_CIPSTART(5));//透傳模式配置printf("進入透傳模式\r\n");while(!ESP8266_Send_Data());printf("進入透傳模式成功\r\n");printf("開始傳輸數據\r\n");}

對應的.h文件:

#ifndef _ESP8266_H_
#define _ESP8266_H_
#include "stm32f10x.h"
#include <stdbool.h>//enum{
//	Station=1,
//	SoftAP,
//	SoftSta
//}Cmode;
#define WIFI_ID "iPhone010"   //熱點ID
#define WIFI_PW "66666666"   //熱點密碼#define SER_IP  ""  //連接的服務器的ip,建議為云服務器,因為有公網ip
#define SER_PORT  8000   //端口號void usart3_Init(u32 brr);
void usart3_It_Config(void);
void ESP8266_IO_Config(void);
u8 Esp8266_AT_test(void);
bool ESP8266_SetMode(u8 mode);
bool ESP8266_SET_HotPort(void);
bool ESP8266_Set_CIPmux(u8 cipmux);
bool ESP8266_Set_CIPSTART(u8 link_id);u8 ESP8266_Send_Data(void);
void ESP8266_NET_Config(void);#endif

2.esp_data.c:


#include "esp_data.h"
#include "stdarg.h"
#include "string.h"
#include <stdbool.h>
#include <delay.h>
#include <stdio.h>
#include "esp8266.h"struct  STRUCT_USARTx_Fram strEsp8266_Fram_Record = { 0 };
struct  STRUCT_USARTx_Fram strUSART_Fram_Record = { 0 };static char *itoa( int value, char * string, int radix );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 );}
}
/** 函數名:itoa* 描述  :將整形數據轉換成字符串* 輸入  :-radix =10 表示10進制,其他結果為0*         -value 要轉換的整形數*         -buf 轉換后的字符串*         -radix = 10* 輸出  :無* 返回  :無* 調用  :被USART2_printf()調用*/
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 *///1---成功   0--失敗
bool ESP8266_Cmd ( char * cmd, char * reply1, char * reply2, u32 waittime )
{    strEsp8266_Fram_Record .InfBit .FramLength = 0;               //從新開始接收新的數據包macESP8266_Usart ( "%s\r\n", cmd );if ( ( reply1 == 0 ) && ( reply2 == 0 ) )                      //不需要接收數據return true;delay_ms ( waittime );                 //延時strEsp8266_Fram_Record .Data_RX_BUF [ strEsp8266_Fram_Record .InfBit .FramLength ]  = '\0';printf("000\r\n");macPC_Usart ( "00%s", strEsp8266_Fram_Record .Data_RX_BUF );strEsp8266_Fram_Record .InfBit .FramLength = 0;                             //清除接收標志strEsp8266_Fram_Record.InfBit.FramFinishFlag = 0;                             if ( ( reply1 != 0 ) && ( reply2 != 0 ) )return ( ( bool ) strstr ( strEsp8266_Fram_Record .Data_RX_BUF, reply1 ) || ( bool ) strstr ( strEsp8266_Fram_Record .Data_RX_BUF, reply2 ) ); else if ( reply1 != 0 )return ( ( bool ) strstr ( strEsp8266_Fram_Record .Data_RX_BUF, reply1 ) );elsereturn ( ( bool ) strstr ( strEsp8266_Fram_Record .Data_RX_BUF, reply2 ) );}u8 ucTcpClosedFlag=0;
void USART1_IRQHandler(void)
{uint8_t ucCh;if ( USART_GetITStatus ( USART1, USART_IT_RXNE ) != RESET ){ucCh  = USART_ReceiveData( USART1 );if ( strUSART_Fram_Record .InfBit .FramLength < ( RX_BUF_MAX_LEN - 1 ) )                       //預留1個字節寫結束符strUSART_Fram_Record .Data_RX_BUF [ strUSART_Fram_Record .InfBit .FramLength ++ ]  = ucCh;}if ( USART_GetITStatus( USART1, USART_IT_IDLE ) == SET )                                         //數據幀接收完畢{strUSART_Fram_Record .InfBit .FramFinishFlag = 1;		ucCh = USART_ReceiveData( USART1 );                                                              //由軟件序列清除中斷標志位(先讀USART_SR,然后讀USART_DR)	}	
}/*** @brief  This function handles macESP8266_USARTx Handler.* @param  None* @retval None*/
void USART3_IRQHandler ( void )
{	uint8_t ucCh;if ( USART_GetITStatus ( USART3, USART_IT_RXNE ) != RESET ){ucCh  = USART_ReceiveData( USART3 );if ( strEsp8266_Fram_Record .InfBit .FramLength < ( RX_BUF_MAX_LEN - 1 ) )                       //預留1個字節寫結束符strEsp8266_Fram_Record .Data_RX_BUF [ strEsp8266_Fram_Record .InfBit .FramLength ++ ]  = ucCh;}if ( USART_GetITStatus( USART3, USART_IT_IDLE ) == SET )                                         //數據幀接收完畢{strEsp8266_Fram_Record .InfBit .FramFinishFlag = 1;ucCh = USART_ReceiveData( USART3 );                                                              //由軟件序列清除中斷標志位(先讀USART_SR,然后讀USART_DR)ucTcpClosedFlag = strstr ( strEsp8266_Fram_Record .Data_RX_BUF, "CLOSED\r\n" ) ? 1 : 0;                   //獲取連接狀態}	}void ESP8266_ExitUnvarnishSend ( void )
{delay_ms ( 1000 );macESP8266_Usart ( "+++" );delay_ms ( 500 ); }
uint8_t ESP8266_Get_LinkStatus ( void )
{if ( ESP8266_Cmd ( "AT+CIPSTATUS", "OK", 0, 500 ) ){if ( strstr ( strEsp8266_Fram_Record .Data_RX_BUF, "STATUS:2\r\n" ) )return 2;else if ( strstr ( strEsp8266_Fram_Record .Data_RX_BUF, "STATUS:3\r\n" ) )return 3;else if ( strstr ( strEsp8266_Fram_Record .Data_RX_BUF, "STATUS:4\r\n" ) )return 4;		}return 0;}void ESP8266_CheckRecvDataTest(void)
{uint8_t ucStatus;uint16_t i;/* 如果接收到了串口調試助手的數據 */if(strUSART_Fram_Record.InfBit.FramFinishFlag == 1){for(i = 0;i < strUSART_Fram_Record.InfBit.FramLength; i++){USART_SendData( USART3 ,strUSART_Fram_Record.Data_RX_BUF[i]); //轉發給ESP82636while(USART_GetFlagStatus(USART3,USART_FLAG_TC)==RESET){}      //等待發送完成}strUSART_Fram_Record .InfBit .FramLength = 0;                                //接收數據長度置零strUSART_Fram_Record .InfBit .FramFinishFlag = 0;                            //接收標志置零}/* 如果接收到了ESP8266的數據 */if(strEsp8266_Fram_Record.InfBit.FramFinishFlag){                                                      for(i = 0;i < strEsp8266_Fram_Record .InfBit .FramLength; i++)               {USART_SendData( USART1 ,strEsp8266_Fram_Record .Data_RX_BUF[i]);    //轉發給ESP8266while(USART_GetFlagStatus(USART1,USART_FLAG_TC)==RESET){}}strEsp8266_Fram_Record .InfBit .FramLength = 0;                             //接收數據長度置零strEsp8266_Fram_Record.InfBit.FramFinishFlag = 0;                           //接收標志置零}if ( ucTcpClosedFlag )                                             //檢測是否失去連接{ESP8266_ExitUnvarnishSend ();                                    //退出透傳模式do ucStatus = ESP8266_Get_LinkStatus ();                         //獲取連接狀態while ( ! ucStatus );if ( ucStatus == 4 )                                             //確認失去連接后重連{printf ( "\r\n正在重連熱點和服務器 ......\r\n" );while ( !ESP8266_SET_HotPort() );//0--TCPwhile ( !	ESP8266_Set_CIPSTART(5) );printf ( "\r\n重連熱點和服務器成功\r\n" );}while ( ! ESP8266_Send_Data () );		}
}

對應的.h文件:

#ifndef _ESP_DATA_H_
#define _ESP_DATA_H_
#include "stm32f10x.h"
#include <stdio.h>
#include <stdbool.h>
#pragma anon_unions#define     macESP8266_Usart( fmt, ... )           USART_printf ( USART3, fmt, ##__VA_ARGS__ )#define     macPC_Usart( fmt, ... )                printf ( fmt, ##__VA_ARGS__ )
#define RX_BUF_MAX_LEN     1024                                     //最大接收緩存字節數
extern struct  STRUCT_USARTx_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;}; } strEsp8266_Fram_Record;extern struct STRUCT_USARTx_Fram strUSART_Fram_Record;
void USART_printf ( USART_TypeDef * USARTx, char * Data, ... );
bool ESP8266_Cmd ( char * cmd, char * reply1, char * reply2, u32 waittime );
void ESP8266_CheckRecvDataTest(void);#endif

3. 監聽的服務器程序server.py:(可以運行在pc端監聽單片機wifi模塊發來的數據)

import socketserver_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 監聽所有可用接口,云服務器需用 0.0.0.0
server_socket.bind(('0.0.0.0', 8000))  
server_socket.listen(5)print('服務器已啟動,等待客戶端連接...')while True:client_socket, client_address = server_socket.accept()print(f'客戶端 {client_address} 已連接')while True:data = client_socket.recv(1024)if not data:breakprint(f'收到數據: {data.decode("utf-8")}')client_socket.send(f"服務器已收到: {data.decode('utf-8')}".encode('utf-8'))client_socket.close()print(f'客戶端 {client_address} 已斷開')

? ? ? ? 云服務器上運行:python3 server.py?

4. main.c:

#include "stm32f10x.h"
#include "esp8266.h"
#include "delay.h"int main(void)
{// 1. 系統時鐘配置(如果使用CubeMX生成則自動完成)SystemInit();// 2. 初始化延時函數(需要實現delay.c/h)delay_init();// 3. 配置USART1(用于調試信息輸出到PC)// 假設USART1已經在其他地方初始化,波特率115200// 如果沒有,需要添加USART1_Init(115200)之類的函數調用// 4. 配置USART3(用于與ESP8266通信)usart3_Init(115200);// 5. 配置ESP8266的控制引腳(EN和RST)ESP8266_IO_Config();// 6. 啟動ESP8266并完成聯網配置printf("\r\n==== ESP8266聯網測試 ====\r\n");ESP8266_NET_Config();// 7. 主循環:持續檢查并轉發數據while(1){// 檢查并處理ESP8266與PC之間的數據轉發ESP8266_CheckRecvDataTest();// 可以添加其他業務邏輯(如讀取傳感器數據等)// 適當延時,避免CPU占用過高delay_ms(10);}
}

5.步驟與現象:

1.?串口助手觀察初始化過程

打開串口助手(波特率 115200),復位 STM32 后,應看到以下輸出:

?
==== ESP8266聯網測試 ====
配置ESP8266聯網流程
AT測試.....
AT測試次數 0......
AT測試啟動成功 0......
正在配置ESP8266模式
正在配置WIFI熱點信息
正在配置單鏈接
正在配置服務器端信息
進入透傳模式
進入透傳模式成功
開始傳輸數據
2.?云服務器日志驗證連接

Python 服務器應顯示類似日志:

?
服務器已啟動,等待客戶端連接...
客戶端 ('你的ESP8266 IP', 隨機端口) 已連接
3.?數據透傳測試
  • PC→云服務器
    在串口助手發送任意消息(如?Hello, server!),云服務器日志會顯示:

    收到數據: Hello, server!
    
  • 云服務器→PC
    服務器會自動回復消息,串口助手會顯示:

    服務器已收到: Hello, server!
    
4.?斷開重連測試

手動停止云服務器上的 Python 程序,模擬斷開連接。ESP8266 會自動檢測到連接丟失,并在串口顯示:

正在重連熱點和服務器 ......

重新啟動云服務器上的 Python 程序,ESP8266 會自動重連,串口顯示:

重連熱點和服務器成功

https://github.com/0voice??

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/89250.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/89250.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/89250.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

前端設計模式應用精析

引言 設計模式是前端工程化架構的基石&#xff0c;通過抽象核心場景解法提升代碼復用性與系統可維護性。本文精析 7 個核心模式&#xff0c;結合原生 JavaScript 與框架實踐&#xff0c;揭示模式在現代前端架構中的底層映射與應用。1. 觀察者模式&#xff08;Observer&#xff…

【機器學習深度學習】Ollama vs vLLM vs LMDeploy:三大本地部署框架深度對比解析

目錄 前言 一、為什么要本地部署大語言模型&#xff1f; 二、三大主流部署方案簡介 三、核心對比維度詳解 1?? 易用性對比 2?? 性能與并發能力 3?? 模型支持與生態兼容性 4?? 部署環境與平臺支持 四、一覽對比表 五、詳細介紹與比較 ? 1. Ollama ? 2. vL…

AWS ML Specialist 考試備考指南

以下是針對AWS機器學習專家認證(AWS Certified Machine Learning - Specialty)的備考指南精簡版,涵蓋核心要點和高效備考策略: ?一、考試核心要點? ?四大核心領域?: ?數據準備(28%)?:S3數據存儲、Glue ETL、Feature Store、數據清洗與特征工程。 ?模型開發(26%…

yolo8+ASR+NLP+TTS(視覺語音助手)

&#x1f9e9; 模塊總覽&#xff1a;步驟模塊作用①麥克風錄音&#xff08;VAD支持&#xff09;獲取語音并判斷是否有人說話②Whisper語音識別把語音內容識別為文字③DeepSeek 聊天接口發送用戶提問并獲取 AI 回復④edge-tts 朗讀回答把 DeepSeek 回答讀出來⑤整合成語音助手主…

Zabbix 分布式監控系統架構設計與優化

一、概念 1.核心概念 Zabbix是一個CS(服務端/客戶端)架構的服務Zabbix-Agent獲取數據-->發送給-->Zabbix-Server服務端--- >數據會被存放在數據庫 <--- Zabbix Web 頁面展示數據 2.部署流程 部署ngxphp環境并測試部署數據庫 mariadb 10.5及以上 然后進行配置編…

QT——文件選擇對話框 QFileDialog

QFileDialog概述QFileDialog是Qt框架中提供的文件對話框類&#xff0c;用于讓用戶選擇文件或目錄。它提供了標準的文件選擇界面&#xff0c;支持文件打開、保存、多選等常見操作。基本使用方式QFileDialog提供了兩種使用方式&#xff1a;靜態方法&#xff1a;直接調用類方法快速…

Flask+LayUI開發手記(十一):選項集合的數據庫擴展類

條目較少的選項集合&#xff0c;確實可以在程序中直接定義&#xff08;其實最合適的還是存儲在一個分類別的數據庫表里&#xff09;&#xff0c;但條目較多的選項集合&#xff0c;或者是復雜的樹型結構選項集合&#xff0c;一般都是存儲在數據庫中的&#xff0c;這樣維護起來比…

AI學習筆記三十二:YOLOv8-CPP-Inference測試(Linux版本)

若該文為原創文章&#xff0c;轉載請注明原文出處。主要介紹如何在Linux系統上安裝和部署基于YOLOv8的C推理項目一、服務器準備使用AutoDL平臺租用服務器AutoDL有git加速&#xff0c;可以自行啟用二、環境配件1、檢查Opencv版本pkg-config --modversion opencv4如果版本為4.5&a…

113:路徑總和 II

題目&#xff1a;給你二叉樹的根節點 root 和一個整數目標和 targetSum &#xff0c;找出所有 從根節點到葉子節點 路徑總和等于給定目標和的路徑。葉子節點 是指沒有子節點的節點。解答&#xff1a;用 go主要坑有兩個&#xff0c;一個是二維結果切片傳遞用指針&#xff0c;一個…

Perl 數組

Perl 數組 在Perl編程語言中&#xff0c;數組是處理數據的一種強大工具。數組允許我們將多個值存儲在單個變量中&#xff0c;從而簡化了代碼并提高了效率。本文將詳細介紹Perl數組的創建、操作、遍歷以及一些高級用法。 數組的創建 在Perl中&#xff0c;創建一個數組非常簡單。…

優先隊列的實現

目錄 引言 堆的基本概念與特性 堆的插入與向上調整 堆的刪除與向下調整 優先隊列的設計思路 模板參數設計 比較器的作用 核心接口實現 push pop top 附錄(完整代碼) 引言 優先隊列&#xff08;Priority Queue&#xff09;是一種特殊的隊列數據結構&#xff0c;其中每…

現代CSS實戰:用變量與嵌套重構可維護的前端樣式

現代CSS實戰&#xff1a;用變量與嵌套重構可維護的前端樣式 引言 在傳統CSS開發中&#xff0c;我們常常陷入「樣式冗余」與「維護噩夢」的循環&#xff1a; 想調整主題色&#xff1f;得全局搜索所有 #3498db 手動替換&#xff0c;稍有不慎就漏改某個角落&#xff1b; 寫嵌套…

DHTMLX Suite 9.2 重磅發布:支持歷史記錄、類Excel交互、剪貼板、拖放增強等多項升級

全球知名的 JavaScript UI 組件庫 DHTMLX Suite 迎來 9.2 新版本&#xff01;此次更新雖為次版本號&#xff0c;卻實質性提升了 Grid 網格組件的交互能力與用戶體驗&#xff0c;引入了包括歷史記錄管理、剪貼板操作、數據選擇范圍管理、Block 區塊選擇等多項高級模塊&#xff0…

深入理解Java中的Map.Entry接口

文章目錄深入理解Java中的Map.Entry接口1. 接口定義2. 核心方法解析2.1 基本方法2.2 Java 8新增的靜態方法3. 基本使用示例3.1 遍歷Map的條目3.2 修改Map中的值3.3 使用比較器排序4. Java 8/9增強特性4.1 與Stream API結合4.2 Java 9的equals和hashCode默認方法5. 實際應用場景…

AI培訓學習2

不要打擾用戶的習慣&#xff0c;比如APP右下角的我的&#xff0c;放到第一個就不合適 先抄再超 lifeTime value NPS: 評價 Product market 平衡 ARPU&#xff1a; LT活躍時長 游戲中好友的重要性 不花錢存活率很少 如何花錢&#xff0c;1分錢買東西 聯影醫療 figma uizard…

npm 安裝時候怎么指定某一個子包的版本 overrides

有時候用 npm install 安裝的時候會報錯&#xff0c;比如 express 包依賴 "escape-html": "^1.0.2" 版本的包&#xff0c;但是因為 escape-html" 升級到 1.0.3 版本了&#xff0c;但是這個版本有問題&#xff0c;導致express 下載不下來。怎么固定下載…

python學智能算法(十九)|SVM基礎概念-超平面

引言 前序學習進程中&#xff0c;對向量相關的基本知識進行了學習&#xff0c;鏈接為&#xff1a; 向量的值和方向 向量點積 在實際的支持向量機算法使用中&#xff0c;最核心的目標是找出可以實現分類的超平面&#xff0c;超平面就是分割的點、線或者面&#xff0c;不要在這個…

python 基于 httpx 的流式請求

文章目錄1. 環境介紹2. 同步客戶端2.1. 面向過程2.1.1. 流式輸出2.1.2. 非流式輸出2.2. 面向對象3. 異步客戶端3.1. 面向過程3.2. 面向對象3.3. Attempted to call a sync iterator on an async stream.參考&#xff1a;https://www.jb51.net/article/262636.htm次要參考&#…

Python 數據建模與分析項目實戰預備 Day 4 - EDA(探索性數據分析)與可視化

? 今日目標 使用 Pandas Matplotlib/Seaborn 對簡歷數據進行探索性分析分析不同字段與目標變量的相關性通過可視化呈現簡歷篩選的潛在規律&#x1f9fe; 一、建議分析內容 &#x1f539; 分類字段分析字段圖表建議說明degree柱狀圖&#xff08;分組通過率&#xff09;分析學歷…

力扣每日一題--2025.7.17

&#x1f4da; 力扣每日一題–2025.7.17 &#x1f4da; 3202. 找出有效子序列的最大長度 II&#xff08;中等&#xff09; 今天我們要解決的是力扣上的第 3202 題——找出有效子序列的最大長度 II。這道題是昨天 3201 題的擴展&#xff0c;需要我們處理更一般化的情況。 ??…