單片機(STM32-WIFI模塊)

一、WIFI模塊介紹

1.?ESP12-F模組介紹

1.1 簡介

ESP12-F模組(安信可(Ai-Thinker)ESP8266系列模組)是一款基于樂鑫(Espressif)公司ESP8266芯片的Wi-Fi無線通信模塊,廣泛應用于物聯網(IoT)領域。它體積小巧,集成度高,內置Wi-Fi功能和32位處理器,支持802.11 b/g/n無線標準。ESP12-F模組內置4MB Flash存儲,擁有豐富的GPIO(通用輸入輸出)、UART、SPI、I2C、PWM、ADC等接口,方便與各種傳感器和外設連接。它既可以通過AT指令作為Wi-Fi串口透傳模塊使用,也可以燒錄自定義固件(如NodeMCU、MicroPython或原生SDK)實現復雜的控制和聯網功能。ESP12-F模組功耗低支持深度休眠,非常適合智能家居、遠程控制、無線傳感器、數據采集等應用場景。使用時需要注意其所有引腳電平為3.3V,不能直接接5V電源或信號,否則可能損壞芯片。

1.2 什么是固件?

ESP12-F模組本質就是集成好的一個小板子,固件就是代碼存儲的地方,這個模組能做那么多事,就是按照固件里的程序執行任務,是開發這個模組的人員提前燒錄進去的。

1.3 安信可 ESP8266 系列模組

https://docs.ai-thinker.com/esp8266

2. 原理分析

2.1 原理圖分析

三個開放引腳:

(1) GPIO0:控制WIFI模式,GPIO0為低電平是下載模式,高電平為運行模式

運行模式:此時串口為正常的通信功能

下載模式:此時串口為下載固件的功能

注意:一般買WiFi模塊的時候,一定要了解是否已經下載固件到WIFI模塊內,如果有一般都是沒有問題可以直接使用的(功能沒有問題)。

(2) 22號引腳 TXD為WIFI模組的串口發送引腳

可以切換我們的WiFi模組串口發送的消息是直接通過底板typec口和電腦通信還是發送給單片機串口通信

TXD(Transmit Data)是ESP-12F WiFi模組的串口發送端,用于將模塊內部處理后的數據通過串口發送到外部設備。在實際應用中,TXD的信號可以通過底板的電路切換,選擇發送到單片機的串口,實現與主控MCU的數據交互,也可以通過Type-C轉USB串口發送到電腦,便于調試、監控或固件下載。這樣設計的好處是,開發者可以根據需要靈活選擇通信對象:在正常運行模式下,TXD用于與單片機進行數據通信,實現物聯網數據上傳、遠程控制等功能;在調試或下載模式下,TXD則用于與電腦通信,輸出調試信息或配合下載工具燒錄固件。需要注意的是,TXD輸出的電平為3.3V,外部設備應與之匹配,避免電平不兼容導致通信異常或損壞模塊。通過合理切換TXD的連接對象,可以大大提升WiFi模組的開發效率和使用靈活性。

(3) 21號引腳 RXD為WIFI模組的串口接收引腳

RXD(Receive?Data)是ESP-12F?WiFi模組的串口接收端,用于接收外部設備(如單片機或電腦)通過串口發送過來的數據。在實際應用中,RXD可以通過底板的電路切換,實現與單片機串口或通過Type-C轉USB串口與電腦通信。這樣,WiFi模組既可以接收來自單片機的數據,實現本地控制和數據交互,也可以在調試或下載固件時接收來自電腦的指令和數據。需要注意的是,RXD引腳的電平為3.3V,不能直接接收5V電平信號,否則可能損壞模塊。實際使用時,確保信號線連接正確,避免串口信號沖突,保證數據通信的可靠性和安全性。

總結:
  • GPIO0控制啟動模式,低電平為下載模式,高電平為運行模式;
  • TXD(22腳)為串口發送,RXD(21腳)為串口接收;
  • 運行模式下串口用于數據通信,下載模式下串口用于固件燒錄;
  • 原理圖設計保證了模式切換和串口功能的靈活性與可靠性。
我們可以通過掰動三個開關調節WiFi功能,一定要注意選擇的模式和對應的圖一致。

2.2 WiFi模塊通過串口通信的兩種方式(硬件連線):

都是我從原理圖中找出來相關元器件進行連接,這是一種很好的培養思維的方式,多去嘗試一下。

(1) WiFi模塊串口直接和電腦USB口相連

1. Wi-Fi無線模塊(ESP-12F)部分

ESP-12F模塊的TXD(發送)、RXD(接收)等引腳通過跳線和開關與外部電路相連。通過開關可以選擇WiFi模塊的串口信號是與單片機通信還是與電腦通信,實現模式切換。GPIO0等引腳用于控制模塊的啟動模式(運行/下載)。

2. 協議轉換芯片(CH340E)部分

CH340E芯片用于將USB信號轉換為串口信號,實現電腦與WiFi模塊之間的串口通信。這樣,WiFi模塊既可以和單片機通信,也可以通過CH340E與電腦直接通信,便于調試和固件下載。

3. Type-C接口部分

Type-C接口(J4)用于與電腦進行物理連接,提供數據通信和電源。通過Type-C線纜,電腦可以直接與電路板上的CH340E芯片通信,進而與WiFi模塊進行數據交互。

(2) WiFi模塊串口和單片機串口相連

1. 單片機引腳區:單片機(如STM32)通過串口引腳(如PA9、PA10或PB10、PB11等)與核心板排針接口(J2)連接,信號經過排針擴展,便于模塊化和后續維護。

2. 核心板排針接口(J2):核心板的排針接口將單片機的串口信號引出,通過排線與底板排針接口(J5)相連,實現信號的延伸和分配。

3. 底板排針接口(J5):底板排針接口接收來自核心板的信號,并將其分配到底板上的各個功能模塊,包括Wi-Fi無線模塊(ESP-12F)。

4. Wi-Fi無線模塊(ESP-12F):ESP-12F的TXD(發送)和RXD(接收)引腳分別與底板排針的UART3_RX和UART3_TX相連,實現與單片機的串口通信。同時,ESP-12F的GPIO0引腳通過電阻和插針與外部電路連接,用于切換運行模式和下載模式。

5. USB轉串口接口:底板上還設計了USB轉串口電路,可以通過Type-C接口將Wi-Fi模塊的串口信號與電腦連接,方便調試和固件下載。

6. 電源和地線:各模塊的3.3V電源和GND地線均已連接,保證電路正常供電和信號參考一致。

3.ESP8266的AT指令

3.1 AT指令集,詳細可見安信可官網

https://docs.espressif.com/projects/esp-at/zh_CN/latest/esp32/AT_Command_Set/index.html

3.2 基礎指令集大全:

官網內詳細指令集合,不是所有指令都可以使用,不同的WiFi模組可使用的不同。

3.3 ESP12-F模組連接網絡流程:

準備工作:

按照上面把三個按鍵撥到TXD和RXD模式上,連接WiFi模組所在的板子的typeC口到電腦上,一根線就可以,因為我們目前還不需要進行燒錄,先熟悉一下AT指令。

可以打開一個網絡調試助手,設置好IP和端口號,設置為服務器server,準備后面連接發送數據

(1) 復位

AT+RST

這個指令就是復位指令,也可以通過按板子上的reset復位鍵進行復位,復位后會斷開之前的連接,相當于重啟。
有亂碼是正常的。
(2) 設置WiFi模式
AT+CWMODE=
查詢/設置 Wi-Fi 模式 (Station/SoftAP/Station+SoftAP)
  • 0: 無 Wi-Fi 模式,并且關閉 Wi-Fi RF
  • 1: Station 模式---------可以連接其他熱點
  • 2: SoftAP 模式---------變身成為一個路由器,可以發射wifi信號成為一個熱點
  • 3: SoftAP+Station------模式 混合模式

這里我們要聯網,所以選擇模式1,連接熱點。

(3) 連接WiFi熱點

AT+CWJAP="熱點名字","熱點密碼"

為了保險起見,此處設置的熱點明不要出現比較另類的字符,盡量為純數字或者字母組合。
連接錯誤會回復的錯誤碼:
回復錯誤碼1:連接超時
回復錯誤碼2:密碼錯誤
回復錯誤碼3:找不到該AP
回復錯誤碼4:連接失敗
這里我們用電腦開熱點,因為大多數WiFi模組(比如我使用的ESP12-F模組)只兼容2.4GHz頻段;而且ESP12-F模組是低功耗模組,而2.4G模組功耗更低,信號穿透能力更強,覆蓋范圍更廣
,復雜環境下穩定性更高。
打開2.4G熱點:
先編輯一下網絡信息,名稱和密碼簡單一些,再設置頻段為2.4GHZ,最后打開熱點。
發送指令:
(4) 連接服務器
AT+CIPSTART="TCP","服務器IP",服務器端口

此時需要打開一個同網絡下的服務器,可以是虛擬機的用代碼寫的服務器或者在Windows上打開一個服務器模擬器

1. 網絡架構理解

當你使用電腦開熱點給WiFi模組提供網絡時,你的電腦實際上扮演了路由器的角色:

  • 電腦 = 路由器(提供網絡服務)
  • WiFi模組 = 客戶端設備(連接到電腦熱點)

2.?IP地址的區分

錯誤的做法:查看電腦連接公共網絡的IP地址

  • 使用?ipconfig?查看的是電腦連接外網的IP
  • 這個IP是電腦作為客戶端獲取的,不是路由器IP

正確的做法:查看電腦熱點網絡的IP地址

  • 需要在網絡調試助手中查看熱點網絡的主機IP
  • 這個IP才是WiFi模組能夠訪問的地址

3. 網絡層次:

公共網絡 ←→ 電腦(路由器) ←→ WiFi模組
? ? ? ? 外網IP ? ? ? ? ? ? 熱點IP

推測出電腦作為熱點主機的IP,并且使用該IP的作為服務器IP,然后打開服務器:
(5) 發送數據

AT+CIPSEND=5 ????????//發送五個字節給服務器

這種方式只能實現單次固定長度數據的發送

輸入后會出現箭頭,表示等待串口向服務器發送五個字節的數據。

發送五個字節數據:

服務器成功接收到數據。

(6)總結

通信數據走向:

3.4 透傳模式設置

之前的發送很別扭,每次都要提前發送指令告訴WiFi模塊準備發送數據,還有長度限制,十分不友好,有什么辦法解決嗎?有的兄弟有的!

(1) 什么是透傳模式

簡介:

透傳模式(Transparent Transmission)是一種數據傳輸方式,設備或系統在通信過程中不對數據內容進行解析或處理,僅作為通道將原始數據完整、無修改地傳遞給目標端。常見于串口通信、網絡協議、物聯網設備等場景。

也就是ESP8266作為一個搬運共,不去辨別串口發送過來的數據是什么,只是無腦的發送給服務器。

(2) 設置透傳

1.設置透傳模式:

AT+CIPMODE=1

2.使能透傳發送:

AT+CIPSEND

連續發送數據:

想退出透傳模式可以發送"+++",就會退出透傳模式:

4. 使用單片機控制WiFi模塊

4.1 思路梳理

  1. 核心設備

    • STM32 MCU:主控制器

    • ESP8266模塊:通過 USART1 連接 STM32(自帶固件程序)

    • PC串口調試助手:通過 UART5 連接 STM32(Type-C直連核心板)

  2. 關鍵開關設置

    • S2/S3:撥向?MCU方向(連接ESP8266與STM32)

    • S4:撥到?運行模式(使能ESP8266正常工作)

    • Type-C:插入核心板(供電+調試通信)

整體流程總結:

1. PC通過串口調試助手(UART5)發送指令給STM32。

2. STM32通過空閑中斷接收完整指令,解析指令。

3. STM32通過USART1向ESP8266發送相應的AT指令或數據。

4. ESP8266執行操作(如連接服務器、發送數據等)。

5. ESP8266將服務器返回的數據通過USART1傳給STM32。

6. STM32將結果通過UART5格式化輸出到PC串口調試助手。

4.2??cubeMX 配置

4.3 代碼編寫

1. 向uart.c添加驅動函數

(1) 兩個串口格式化輸出函數:

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(UART_HandleTypeDef * USARTx, char * Data, ... )
{const char *s;int d;   char buf[16];char singleBuff[1];va_list ap;va_start(ap, Data);while ( * Data != 0 )     // 判斷數據是否到達結束符{                                         if ( * Data == 0x5c )  //'\'{                                     switch ( *++Data ){case 'r':                                     //回車符singleBuff[0] = 0x0d;    __HAL_UART_CLEAR_FLAG(USARTx, UART_CLEAR_TCF);						HAL_UART_Transmit(USARTx, (void*)singleBuff, 1, 1);//阻塞式發送數據Data ++;break;case 'n':                                     //換行符singleBuff[0] = 0x0a;    __HAL_UART_CLEAR_FLAG(USARTx, UART_CLEAR_TCF);/* Clear the TC flag in the ICR register */HAL_UART_Transmit(USARTx, (void*)singleBuff, 1, 1);//阻塞式發送數據Data ++;break;default:Data ++;break;}            }else if ( * Data == '%'){                                     switch ( *++Data ){               case 's':                                         //字符串s = va_arg(ap, const char *);for ( ; *s; s++) {singleBuff[0] = *s;    HAL_UART_Transmit(USARTx, (void*)singleBuff, 1, 1);//阻塞式發送數據while(__HAL_UART_GET_FLAG(USARTx, UART_FLAG_TXE) == RESET);}Data++;break;case 'd':           d = va_arg(ap, int);itoa(d, buf, 10);for (s = buf; *s; s++) {singleBuff[0] = *s;    HAL_UART_Transmit(USARTx, (void*)singleBuff, 1, 1);//阻塞式發送數據while(__HAL_UART_GET_FLAG(USARTx, UART_FLAG_TXE) == RESET);}Data++;break;default:Data++;break;}        }else{singleBuff[0] = *Data++;    __HAL_UART_CLEAR_FLAG(USARTx, UART_CLEAR_TCF);/* Clear the TC flag in the ICR register */HAL_UART_Transmit(USARTx, (void*)singleBuff, 1, 1);//阻塞式發送數據}		while (__HAL_UART_GET_FLAG(USARTx, UART_FLAG_TXE) == RESET);}
}
(2) 把上述驅動函數放在uart.c文件內,這樣就可以使用這些函數:

(3) 把頭文件加入uart.c文件中,因為上面兩個函數用到這些庫

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

(4) 然后在uart.h文件中加上對兩個函數的聲明,保證導入.h文件主函數可以正常使用,后面的wifi驅動文件也會用到:

static char *itoa(int value, char *string, int radix );
void USART_printf(UART_HandleTypeDef * USARTx, char * Data, ... );

?2. 添加WiFi驅動文件

(1) 下面是ESP8266的WiFi驅動文件,導入項目后,就可以使用內置狀態機函數實現單片機代替串口發送AT指令給WiFi模塊,讓WiFi模塊進行聯網和通信。
wifi.c:

#include "wifi.h"int connect_flag = 0; // 是否連接成功的標志
int tt_flag = 0;	  // 是否有網絡發過來的透傳數據標志char WIFI_Config0(int time) // 找到ready 返回 沒有找到返回1
{memset(WiFi_RX_BUF, 0, 1024);WiFi_RxCounter = 0;while (time--){HAL_Delay(100);if (strstr((char *)WiFi_RX_BUF, "ready")){break;}// u1_USART ("WIFI_Config0:=%s",WiFi_RX_BUF);}if (time > 0)return 0;elsereturn 1;
}char WIFI_Config(int time, char *cmd, char *response) // 等待時間 發送內容 判斷返回的內容
{memset(WiFi_RX_BUF, 0, 1024);WiFi_RxCounter = 0;ESP8266_USART("%s\r\n", cmd);while (time--){HAL_Delay(100);if (strstr((char *)WiFi_RX_BUF, response)){break;}// u1_USART("%d ", time);}if (time > 0)return 0;elsereturn 1;
}char WIFI_Router(int time) // 配置WIFI名和密碼
{memset(WiFi_RX_BUF, 0, 1024);WiFi_RxCounter = 0;//	ESP8266_USART("AT+CIPMUX=0");//	HAL_Delay(100);ESP8266_USART("AT+CWJAP=\"%s\",\"%s\"\r\n", ID, PASSWORD);while (time--){HAL_Delay(1000);if (strstr((char *)WiFi_RX_BUF, "OK")){break;}u1_USART("連接路由倒計時: %d\r\n ", time);}if (time > 0)return 0;elsereturn 1;
}char WIFI_ConnectTCP(int time) // 配置TCP
{memset(WiFi_RX_BUF, 0, 1024);WiFi_RxCounter = 0;ESP8266_USART("AT+CIPSTART=\"TCP\",\"%s\",%d\r\n", ServerIP, ServerPort);while (time--){HAL_Delay(100);if (strstr((char *)WiFi_RX_BUF, "OK")){break;}u1_USART("正在建立TCP連接 :%d ", time);}if (time > 0)return 0;elsereturn 1;
}enum WIFI_STATE
{WIFI_READY = 0,WIFI_CONFIG1,WIFI_ROUTER,WIFI_CONFIG2,  //進入透傳模式WIFI_CONNECT, //連接服務器WIFI_CONFIG3,WIFI_COMPLETE	//連接完成
};#define WAIT_TIME 1000void WIFI_Connect()//狀態機
{int state = WIFI_READY;  //默認等待復位while (1){if(state == WIFI_COMPLETE){u1_USART("連接服務器完成并開啟透傳!\r\n");memset(WiFi_RX_BUF,0,1024);//WIFI_SendData("hello world");break;  //這里直接跳出while(1)循環即可}switch (state){case WIFI_READY://檢測是否手動復位了/*0、按鍵復位*/u1_USART("0、準備按鍵復位!\r\n");if (WIFI_Config0(100))//判是否收到ready{u1_USART("按鍵復位失敗!\r\n");HAL_Delay(WAIT_TIME);}else//成功了 找到了{u1_USART("按鍵復位成功!\r\n");state = WIFI_CONFIG1;}break;case WIFI_CONFIG1:/*1、配置WIFI模式*/u1_USART("1、準備配置WIFI模式!\r\n");if (WIFI_Config(50, "AT+CWMODE=1\r\n", "OK"))//發送命令 檢測OK{u1_USART("配置WIFI模式失敗!\r\n");HAL_Delay(WAIT_TIME);break;}else//成功u1_USART("配置WIFI模式成功!\r\n");u1_USART("\r\n");/*2、重啟(命令方式)*/u1_USART("2、準備復位!\r\n");if (WIFI_Config(50, "AT+RST\r\n", "ready")){u1_USART("復位失敗!\r\n");HAL_Delay(WAIT_TIME);break;}elseu1_USART("復位成功!\r\n");u1_USART("\r\n");/*3、取消自動連接*/u1_USART("3、準備取消自動連接\r\n");if (WIFI_Config(50, "AT+CWAUTOCONN=0\r\n", "OK"))//取消熱點自動連接 檢測OK{u1_USART("取消自動連接失敗!\r\n");HAL_Delay(WAIT_TIME);break;}elseu1_USART("取消自動連接成功!\r\n");WiFi_RxCounter = 0;state = WIFI_ROUTER;break;case WIFI_ROUTER:/*4、連接路由器*/u1_USART("4、準備連接路由器\r\n");if (WIFI_Router(50))//連接熱點并檢測是否連接成功{u1_USART("連接路由器失敗!\r\n");HAL_Delay(WAIT_TIME);}else{u1_USART("連接路由器成功!\r\n");state = WIFI_CONFIG2;}break;case WIFI_CONFIG2:/*5、配置單路連接模式*/u1_USART("5、準備配置單路連接模式!\r\n");if (WIFI_Config(50, "AT+CIPMUX=0\r\n", "OK"))//配置單路連接{u1_USART("配置單路連接模式失敗!\r\n");HAL_Delay(WAIT_TIME);break;}else{u1_USART("配置單路連接模式成功!\r\n");}u1_USART("\r\n");/*6、開啟透傳模式*/u1_USART("6、準備開啟透傳模式\r\n");if (WIFI_Config(50, "AT+CIPMODE=1\r\n", "OK")){u1_USART("開啟透傳模式失敗!\r\n");HAL_Delay(WAIT_TIME);break;}else{u1_USART("開啟透傳模式成功!\r\n");}state = WIFI_CONNECT;break;case WIFI_CONNECT:/*7、建立TCP連接*/u1_USART("7、準備建立TCP連接\r\n");if (WIFI_ConnectTCP(50))//連接TCP{u1_USART("建立TCP連接失敗!\r\n");HAL_Delay(WAIT_TIME);}else{u1_USART("建立TCP連接成功!\r\n");state = WIFI_CONFIG3;}break;case WIFI_CONFIG3:/*8、進入透傳模式*/u1_USART("8、準備進入透傳模式\r\n");if (WIFI_Config(50, "AT+CIPSEND\r\n", "\r\nOK\r\n\r\n>")){u1_USART("進入透傳模式失敗!\r\n");HAL_Delay(WAIT_TIME);}else{u1_USART("進入透傳模式成功!\r\n");state = WIFI_COMPLETE;connect_flag = 1;break;}default:break;}}
}//int WIFI_SendData(const char *data)
//{
//	ESP8266_USART("%s", data);
//	//u1_USART("數據發送完成\r\n");
//	return 0;
//	if (WIFI_Config(10, "AT+CIPSEND=5\r\n", ">"))
//	{
//		ESP8266_USART("%s", data);
//		u1_USART("數據發送完成\r\n");
//		return 0;
//	}
//	else
//	{
//		u1_USART("數據發送失敗!\r\n");
//		return -1;
//	}
//}

wifi.h:

#ifndef _WIFI_H
#define _WIFI_H
#include <string.h>
#include "usart.h"
extern uint8_t USART5_RxBuff[1024];
extern volatile uint8_t USART5_RxCounter;
#define WiFi_RxCounter    USART5_RxCounter    
#define WiFi_RX_BUF       USART5_RxBuff 
#define ESP8266_USART(fmt, ...)  USART_printf(&huart5, fmt, ##__VA_ARGS__) 
#define u1_USART(fmt, ...)  USART_printf(&huart1, fmt, ##__VA_ARGS__) 
#define ID   "zkm"                      //網絡名字       
#define PASSWORD   "12345611"           //網絡密碼#define ServerIP   "192.168.43.148"     //服務器IP地址       
#define ServerPort  4399                //服務器端口char WIFI_Config0(int time);
char WIFI_Config(int time,char*cmd,char*response);
char WIFI_Router(int time);
char WIFI_ConnectTCP(int time);
void WIFI_Connect(void);
void ESP8266_Clear(void);
#endif

添加外部文件的方式可以參考之前文章,在標題五下的8.2:單片機(STM32-IIC)-CSDN博客

3. 添加串口5空閑中斷

? ? ? ?上述準備工作做完,我們已經有了WiFi模組的函數WIFI_Connect(),還有直接向串口五發送數據的函數USART_printf(UART_HandleTypeDef * USARTx, char * Data, ... ),WIFI_Connect()函數是依賴于串口接收中斷函數,所以我們需要搭建串口五點空閑中斷。(推薦自己先看看wifi文件)

? ? ? ?在我們之前使用AT指令的時候,發送給ESP8266一個數據,會回復相應的消息,WIFI_Connect()函數就是依靠這個邏輯。這個函數讓單片機按順序給ESP8266發送指令,只有接收到ESP8266的ready消息才會發送下一條指令,如果沒有接收到ready消息或者接收到錯誤消息,會一直嘗試連接,由此可見這個函數是阻塞進程的,所以我們要開啟串口5的空閑接收中斷,而且必須在調用WIFI_Connect()函數前開啟一次中斷接收,再在中斷回調函數內開啟中斷接收,每接收到一次數據就開啟下一次中斷接收。

(1)?定義全局變量

uint8_t USART5_RxBuff[1024]={0};
volatile uint8_t USART5_RxCounter=0;

(2) 添加接受中斷函數(不定長)和接收中斷回調函數

細節可以看我的單片機(STM32-串口通信)_stm32串行同步通信-CSDN博客,最好是用不定長接收,因為接收長度是未知的,只要設定長度夠大就能接收并觸發中斷。

中斷函數:

 void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)

寫回調:?

extern int connect_flag;
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{if(huart == &huart5){USART5_RxCounter=1;//此變量置1,則代表wifi發過來了數據HAL_UARTEx_ReceiveToIdle_IT(&huart5,USART5_RxBuff,1024);}
}
4. 嘗試聯網:
(1) 修改wifi.h中的信息

(2)?添加頭文件

(3) 調用wifi連接函數
必須在調用WIFI_Connect()函數前開啟一次中斷接收,前面說了WIFI_Connect()函數是阻塞的,因為沒開啟接收中斷函數,單片機一直接收不到任何消息,會卡在函數出不來就會一直復位失敗。

5. 打開服務器,燒錄后復位單片機

注意:

(1) 別忘了要更換USB口到單片機的核心板,讓單片機和串口直接通信,ESP8266的模式(S3,S2)也需要切換,切換為MCU模式。

(2) 服務器和單片機連接的網絡處于一個網絡下,按照之前連接網絡和配置網絡虛擬機(服務器)的方式的方式。

(3) 串口助手顯示單片機接收信息,網絡虛擬機充當服務器發送數據到單片機,如下圖:

點擊復位后,串口會輸出下面提示信息,如果成功就說明網絡連接成功,如果卡在某一個位置就去處理響應的問題。?

6. 常見問題解決:

問題一:卡在0.復位,那就是單片機接受不到ESP8266發送的信息

(1) 查看s3,s2是否調節到mcu模式,

(2) 查看cubemx是否配置串口5的中斷

(3) 再查看是否在調用wifi_connect函數前開啟串口5的中斷接收。

(4) 最后再檢查配置流程是否和前面一致。

問題二:卡在4.連接路由器

(1) 先耐心等待幾分鐘,有時候連接時間比較長

(2) 查看網絡是否可用,是否是2.4GHZ頻段下

問題三:卡在準備6.建立TCP連接

查看服務器地址和端口號是否準確,是否按照前面配置方式確定服務器IP地址。

7. 和服務器通信

和服務器通信分兩部分:接收和發送;

(1)、接收已經有了,就是串口5接收中斷函數,只需要在中斷內判斷USART5_RxBuff[1024]字符串,執行操作就可以:

extern int connect_flag;
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{if(huart == &huart5){USART5_RxCounter=1;//此變量置1,則代表wifi發過來了數據if(connect_flag == 1){u1_USART("server:%s\n",USART5_RxBuff);if(strcmp(USART5_RxBuff,"FAN_ON") == 0)        //服務器發送FAN_ON打開風扇{HAL_GPIO_WritePin(GPIOC,GPIO_PIN_6,1);}if(strcmp(USART5_RxBuff,"FAN_OFF") == 0)        //關閉風扇{HAL_GPIO_WritePin(GPIOC,GPIO_PIN_6,0);}memset(USART5_RxBuff,0,1024);                    //清空字符數組}HAL_UARTEx_ReceiveToIdle_IT(&huart5,USART5_RxBuff,1024);}
}

(2)、發送就是uart.c函數內添加的驅動函數USART_printf函數,在wifi.c中宏定義改名為ESP8266_USART函數,導入頭文件wifi.h后,兩個函數都可以用,最好直接發送字符串,sprintf拼接字符串后發送。雖然可以“USART_printf("temp:%d",temp);”進行發送,但是對“USART_printf("temp:%f",temp);”就會發送錯誤字符串。

當可以通過串口調試助手控制單片機就大功告成。

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

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

相關文章

PyTorch 數據類型和使用

關于PyTorch的數據類型和使用的學習筆記 系統介紹了PyTorch的核心數據類型Tensor及其應用。Tensor作為多維矩陣數據容器&#xff0c;支持0-4維數據結構&#xff08;標量到批量圖像&#xff09;&#xff0c;并提供了多種數值類型&#xff08;float32/int64等&#xff09;。通過…

[python刷題模板] LogTrick

[python刷題模板] LogTrick 一、 算法&數據結構1. 描述2. 復雜度分析3. 常見應用4. 常用優化二、 模板代碼1. 特定或值的最短子數組2. 找特定值3. 找位置j的最后一次被誰更新4. 問某個或和的數量三、其他四、更多例題五、參考鏈接一、 算法&數據結構 1. 描述 LogTric…

Vim與VS Code

Vim is a clone, with additions, of Bill Joys vi text editor program for Unix. It was written by Bram Moolenaar based on source for a port of the Stevie editor to the Amiga and first released publicly in 1991.其實這個本身不是 IDE &#xff08;只有在加入和配置…

[2025CVPR-圖象分類方向]CATANet:用于輕量級圖像超分辨率的高效內容感知標記聚合

?1. 研究背景與動機? ?問題?&#xff1a;Transformer在圖像超分辨率&#xff08;SR&#xff09;中計算復雜度隨空間分辨率呈二次增長&#xff0c;現有方法&#xff08;如局部窗口、軸向條紋&#xff09;因內容無關性無法有效捕獲長距離依賴。?現有局限?&#xff1a; SPI…

課題學習筆記3——SBERT

1 引言在構建基于知識庫的問答系統時&#xff0c;"語義匹配" 是核心難題 —— 如何讓系統準確識別 "表述不同但含義相同" 的問題&#xff1f;比如用戶問 "對親人的期待是不是欲&#xff1f;"&#xff0c;系統能匹配到知識庫中 "追名逐利是欲…

在Word和WPS文字中把全角數字全部改為半角

大部分情況下我們在Word或WPS文字中使用的數字或標點符號都是半角&#xff0c;但是有時不小心按錯了快捷鍵或者點到了輸入法的全角半角切換圖標&#xff0c;就輸入了全角符號和數字。不用擔心&#xff0c;使用它們自帶的全角、半角轉換功能即可快速全部轉換回來。一、為什么會輸…

數據結構的基本知識

一、集合框架1、什么是集合框架Java集合框架(Java Collection Framework),又被稱為容器(container),是定義在java.util包下的一組接口(interfaces)和其實現類(classes).主要表現為把多個元素(element)放在一個單元中,用于對這些元素進行快速、便捷的存儲&#xff08;store&…

WebStack-Hugo | 一個靜態響應式導航主題

WebStack-Hugo | 一個靜態響應式導航主題 #10 shenweiyan announced in 1.3-折騰 WebStack-Hugo | 一個靜態響應式導航主題#10 ?編輯shenweiyan on Oct 23, 2023 6 comments 7 replies Return to top shenweiyan on Oct 23, 2023 Maintainer Via&#xff1a;我給自己…

01 基于sklearn的機械學習-機械學習的分類、sklearn的安裝、sklearn數據集、數據集的劃分、特征工程中特征提取與無量綱化

文章目錄機械學習機械學習分類1. 監督學習2. 半監督學習3. 無監督學習4. 強化學習機械學習的項目開發步驟scikit-learn1 scikit-learn安裝2 sklearn數據集1. sklearn 玩具數據集鳶尾花數據集糖尿病數據集葡萄酒數據集2. sklearn現實世界數據集20 新聞組數據集3. 數據集的劃分特…

攜全雙工語音通話大模型亮相WAIC,Soul重塑人機互動新范式

近日&#xff0c;WAIC 2025在上海隆重開幕。作為全球人工智能領域的頂級盛會&#xff0c;本屆WAIC展覽聚焦底層能力的演進與具體垂類場景的融合落地。堅持“模應一體”方向、立足“AI社交”的具體場景&#xff0c;Soul App此次攜最新升級的自研端到端全雙工語音通話大模型亮相&…

第2章 cmd命令基礎:常用基礎命令(1)

Hi~ 我是李小咖&#xff0c;主要從事網絡安全技術開發和研究。 本文取自《李小咖網安技術庫》&#xff0c;歡迎一起交流學習&#x1fae1;&#xff1a;https://imbyter.com 本節介紹的命令有目錄操作&#xff08;cd&#xff09;、清屏操作&#xff08;cls&#xff09;、設置顏色…

Java 10 新特性解析

Java 10 新特性解析 文章目錄Java 10 新特性解析1. 引言2. 本地變量類型推斷&#xff08;JEP 286&#xff09;2.1. 概述2.2. 使用場景2.3. 限制2.4. 與之前版本的對比2.5. 風格指南2.6. 示例代碼2.7. 優點與注意事項3. 應用程序類數據共享&#xff08;JEP 310&#xff09;3.1. …

【WRF工具】服務器中安裝編譯GrADS

目錄 安裝編譯 GrADS 所需的依賴庫 conda下載庫包 安裝編譯 GrADS 編譯前檢查依賴可用性 安裝編譯 GrADS 參考 安裝編譯 GrADS 所需的依賴庫 以統一方式在 $HOME/WRFDA_LIBS/grads_deps 下安裝所有依賴: # 選擇一個目錄用于安裝所有依賴庫 export DIR=$HOME/WRFDA_LIBS庫包1…

數據結構之隊列(C語言)

1.隊列的定義&#xff1a; 隊列&#xff08;Queue&#xff09;是一種基礎且重要的線性數據結構&#xff0c;遵循先進先出&#xff08;FIFO&#xff09;?? 原則&#xff0c;即最早入隊的元素最先出隊&#xff0c;與棧不同的是出隊列的順序是固定的。隊列具有以下特點&#xff…

C#開發基礎之深入理解“集合遍歷時不可修改”的異常背后的設計

前言 歡迎關注【dotnet研習社】&#xff0c;今天我們聊聊一個基礎問題“集合已修改&#xff1a;可能無法執行枚舉操作”背后的設計。 在日常 C# 開發中&#xff0c;我們常常會操作集合&#xff08;如 List<T>、Dictionary<K,V> 等&#xff09;。一個新手開發者極…

【工具】圖床完全指南:從選擇到搭建的全方位解決方案

前言 在數字化內容創作的時代&#xff0c;圖片已經成為博客、文檔、社交媒體等平臺不可或缺的元素。然而&#xff0c;如何高效、穩定地存儲和分發圖片資源&#xff0c;一直是內容創作者面臨的重要問題。圖床&#xff08;Image Hosting&#xff09;作為專門的圖片存儲和分發服務…

深度學習篇---PaddleDetection模型選擇

PaddleDetection 是百度飛槳推出的目標檢測開發套件&#xff0c;提供了豐富的模型庫和工具鏈&#xff0c;覆蓋從輕量級移動端到高性能服務器的全場景需求。以下是核心模型分類、適用場景及大小選擇建議&#xff08;通俗易懂版&#xff09;&#xff1a;一、主流模型分類及適用場…

cmseasy靶機密碼爆破通關教程

靶場安裝1.首先我們需要下載一個cms靶場CmsEasy_7.6.3.2_UTF-8_20200422,下載后解壓在phpstudy_pro的網站根目錄下。2.然后我們去訪問一下安裝好的網站&#xff0c;然后注冊和鏈接數據庫3.不知道自己數據庫密碼的可以去小皮面板里面查看4.安裝好后就可以了來到后臺就可以了。練…

【C語言】指針深度剖析(一)

文章目錄一、內存和地址1.1 內存的基本概念1.2 編址的原理二、指針變量和地址2.1 取地址操作符&#xff08;&&#xff09;2.2 指針變量和解引用操作符&#xff08;*&#xff09;2.2.1 指針變量2.2.2 指針類型的解讀2.2.3 解引用操作符2.3 指針變量的大小三、指針變量類型的…

半導體企業選用的跨網文件交換系統到底應該具備什么功能?

在半導體行業的數字化轉型過程中&#xff0c;跨網文件交換已成為連接研發、生產、供應鏈的關鍵紐帶。半導體企業的跨網文件交換不僅涉及設計圖紙、工藝參數等核心知識產權&#xff0c;還需要滿足跨國協同、合規審計等復雜需求。那么&#xff0c;一款適合半導體行業的跨網文件交…