更新源碼:
? ? ? ? ?源碼已上傳至gitee:
stm32: 一些stm32模塊使用經(jīng)驗(yàn)記錄 - Gitee.comhttps://gitee.com/lrf1125962926/stm32/tree/esp8266wifi%E9%80%9A%E4%BF%A1/
設(shè)計概述:? ? ? ??
????????本實(shí)驗(yàn)采用STM32F1系列+esp8266 01s模塊,采用HAL庫開發(fā)。主控芯片哪個系列和型號都可以,只要有兩個串口(UART或者USART,以下統(tǒng)稱串口)就行。把串口配置好,? 可以直接移植使用。
????????很多博主都寫過STM32+esp8266的文章,但大部分都只講一種用法或者介紹的比較模糊,翻了很多都沒看懂到底要怎么操作這個WiFi模塊,于是就自己埋頭扒了幾天官方文檔,大致理了一個通用模型,把模塊的工作模式分為5個,WiFi狀態(tài)分為3個。
? ? ? ? ? ? ? ? ? ? ? ? ?
?至于為什么分為5種模式,是參考了官方的測試文檔:
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
?????????在開始寫代碼前,我建議各位先用esp-link(固件燒錄器,沒有就買一個,便宜,實(shí)在不想要也行,用TTL轉(zhuǎn)串口)接上模塊,連接電腦,用串口把指令熟悉一下,把這5種模式過一遍,文檔地址:
4B-ESP8266__AT Command Examples__CN (espressif.com.cn)https://www.espressif.com.cn/sites/default/files/documentation/4b-esp8266_at_command_examples_cn.pdf這樣模塊的大致工作流程就清楚了,代碼寫起來才條理清晰。
????????因?yàn)橐褂梅?wù)器和客戶端,電腦可以使用NetAssist,軟件很好找;手機(jī)端應(yīng)用商店搜TCP,大部分都能用,最好是有4個選項(xiàng),TCP的服務(wù)器和客戶端,UDP的服務(wù)器和客戶端。
????????建議大家電腦端和手機(jī)端配合使用,電腦端建服務(wù)器,手機(jī)和esp連;手機(jī)建服務(wù)器,電腦和esp連;esp建服務(wù)器,電腦和手機(jī)連。
代碼設(shè)計框架:
????????代碼整體需要對3個部分進(jìn)行編寫,串口1,串口2,esp模塊。
?串口:
由于HAL庫有回調(diào)機(jī)制,串口2的中斷回調(diào)函數(shù)就放在了串口1
串口1和2大致相同,采用正點(diǎn)原子的設(shè)計,有緩沖數(shù)組和接收完成標(biāo)志位。
串口2要做一點(diǎn)調(diào)整:
?????????將原來的部分注釋,增加新的接收條件。這個主要是因?yàn)閑sp的AT指令在末尾要加上回車換行才能生效,每次模塊返回的數(shù)據(jù)不知為啥又以回車換行開始,索性我就直接丟棄。
? ? ? ? 串口的代碼可以從正點(diǎn)原子的例程中拷貝,都一樣。注意要理解清楚接收完成標(biāo)志位的含義,這個標(biāo)志位的不同bit設(shè)計很巧妙,用好了事半功倍。
esp8266:
初始化函數(shù):
/**
* @brief esp8266wifi模塊初始化
* @param RUNmode:1為單連接TCP,esp做客戶端;
* 2為UDP傳輸;
* 3為TCP透傳;
* 4為UDP透傳;
* 5為多連接TCP,esp做服務(wù)器;
* @param wifi_mode: 1為Station 模式,連接外部wifi
* 2為SoftAP 模式,開啟熱點(diǎn)
* 3為SoftAP+Station 雙模式
* @note 檢測IP是否獲得:AT+CIFSR
* 若要更換模塊使用方式,重新調(diào)用初始化即可
* 模塊只有在RUNmode為模式5開啟服務(wù)器后才能作為服務(wù)器,其余均為Station客戶端
*
* @retval 0為錯誤,1為初始化完成
*/
uint8_t esp8266_Init(uint8_t RUNmode,uint8_t wifi_mode)
? ? ? ? ?1、就從初始化函數(shù)開始,這是這個project集成度最高的函數(shù),調(diào)用了所有底層函數(shù)。這個函數(shù)的邏輯就是按照參考手冊給的指令集,根據(jù)傳參RUNmode的值,分別對應(yīng)5種運(yùn)行模式進(jìn)行初始化。
? ? ? ? 2、 開頭定義變量,進(jìn)行常規(guī)配置,因?yàn)榭赡苊看斡玫降哪J讲煌栽陂_頭加了恢復(fù)出廠設(shè)置(復(fù)位模塊,這里用的函數(shù)調(diào)用),關(guān)閉回顯和IP顯示看個人喜好,回顯就是發(fā)送指令后,模塊會先返回收到的指令,再返回響應(yīng)值。
uint8_t ERROR_count=0;//ERROR_count用于計數(shù)錯誤時的嘗試次數(shù)
uint8_t esp_state=esp8266_OK;//獲取當(dāng)前的工作模式
char temp1[MAX_temp_array];//用于字符串連接
esp8266wifi_working_mode=RUNmode;//保存全局工作模式
printf("\r\nESP8266wifi模塊正在初始化\r\n");
esp8266wifi_reset();//復(fù)位模塊
esp8266wifi_send_cmd("ATE0",0,normal_waittime);//關(guān)閉回顯
esp8266wifi_send_cmd("AT+CIPDINFO=0",0,normal_waittime);//關(guān)閉顯示IP和端口
esp8266wifi_set_wifi_mode(wifi_mode);//設(shè)置wifi模式
????????esp8266wifi_working_mode是一個全局變量,有的函數(shù)需要用到。
????????這里的esp8266wifi_send_cmd函數(shù)先簡單介紹一下,作用是通過串口發(fā)送數(shù)據(jù),放到后面的底層調(diào)用來講。第一個傳參是要發(fā)送的字符串;第二個是要檢查的字符串,檢查模塊有沒有反回這個子串,這里給0是不檢查返回;第三個是等待時間。?
? ? ? ? 復(fù)位函數(shù):
/**
* @brief 恢復(fù)出廠設(shè)置
* @param 無
* @retval 無
*/
void esp8266wifi_reset(void)
{
printf("正在復(fù)位...\n");
esp8266wifi_send_cmd("AT+RESTORE",0,normal_waittime);
delay_ms(1000);
printf("復(fù)位完成\n");
}
????????esp8266wifi_set_wifi_mode(wifi_mode);//設(shè)置wifi模式是一個自定義函數(shù),發(fā)送AT+CWMODE指令。
/**
* @brief 設(shè)置Wi-Fi模式
* @param mode: 1為Station 模式,客戶端
* 2為SoftAP 模式,開啟熱點(diǎn)
* 3為SoftAP+Station 雙模式
* @retval 無
*/
void esp8266wifi_set_wifi_mode(uint8_t mode)
{
switch (mode)
{
case 1:
esp8266wifi_send_cmd("AT+CWMODE=1",0,normal_waittime);
break;
case 2:
esp8266wifi_send_cmd("AT+CWMODE=2",0,normal_waittime);
break;
case 3:
esp8266wifi_send_cmd("AT+CWMODE=3",0,normal_waittime);
break;
default:
break;
}
}
????????
? ? ? ??
? ? ? ? 3、接下來就是判斷WIFI模式,開啟熱點(diǎn)還是連接WIFI,sprintf的作用是合并字符串,可以百度用法,傳參用到的兩個宏定義,就是WiFi名字和密碼。
if(wifi_mode==wifi_mode_Station)//連接WIFI
{
sprintf(temp1,"AT+CWJAP=\"%s\",\"%s\"",SoftAP_WIFI_SSID,SoftAP_WIFI_PASSWORD);
ERROR_count=0;
printf("\r\n正在連接WIFI...\r\n");
do//連接WIFI
{
esp_state=esp8266wifi_send_cmd(temp1,"OK",MAX_waittime);
if(esp_state==esp8266_ERROR)
{
ERROR_count++;
delay_ms(1000);//延時1s
if(ERROR_count==esp8266_Init_Try_Time)
{
printf("\r\n連接WIFI失敗\r\n");
return esp8266_ERROR;
}
}
}while(esp_state!=esp8266_OK);
printf("\r\nWIFI連接成功\r\n");
}
????????這里用了一個do-while語句用來在連接失敗時嘗試重新連接,一定次數(shù)(esp8266_Init_Try_Time,我用的5次)后放棄并結(jié)束初始化。
????????還有下面的else部分沒有放,代碼邏輯同理,用于設(shè)置esp的WiFi名字和密碼,只要修改對應(yīng)的sprintf就行,不做講解。
????????4、接下來就是模式1,根據(jù)手冊指令,第一步配置 WiFi 模式我放到了初始化函數(shù)的開頭,因?yàn)槊總€模式都需要設(shè)置;第二部連接路由器在上一張圖做了講解;第三步查詢地址這里不需要;第四步連接服務(wù)器,也就是這里代碼所展示的。
if(RUNmode==mode_1_TCP_Client)//單連接TCP,esp做Station客戶端
{
esp8266wifi_set_trans_mode(0);//設(shè)置為普通傳輸模式,非透傳
esp8266wifi_send_cmd("AT+CIPMUX=0",0,normal_waittime);//單連接模式
sprintf(temp1,"AT+CIPSTART=\"TCP\",\"%s\",%s",esp8266wifi_TCP_IP,esp8266wifi_TCP_PORT);
ERROR_count=0;
printf("\r\n正在連接服務(wù)器...\r\n");
do//esp作為客戶端連接到服務(wù)器
{
esp_state=esp8266wifi_send_cmd(temp1,"CONNECTED",MAX_waittime);
if(esp_state==esp8266_ERROR)
{
ERROR_count++;
delay_ms(1000);
if(ERROR_count==esp8266_Init_Try_Time)
{
printf("\r\n連接到服務(wù)器失敗\r\n");
return esp8266_ERROR;
}
}
}while(esp_state!=esp8266_OK);
printf("\r\n成功連接到服務(wù)器\r\n");
}
????????其中esp8266wifi_set_trans_mode(0);//設(shè)置為普通傳輸模式是一個自定義函數(shù):
/**
* @brief 設(shè)置傳輸模式
* @param mode: 0為普通傳輸模式
* 1為透傳模式,僅?持 TCP 單連接和 UDP 固定通信對端的情況
* @retval 無
*/
void esp8266wifi_set_trans_mode(uint8_t mode)
{
switch (mode)
{
case 0:
esp8266wifi_send_cmd("AT+CIPMODE=0",0,normal_waittime);
break;
case 1:
esp8266wifi_send_cmd("AT+CIPMODE=1",0,normal_waittime);
break;
default:
break;
}
}
????????在電腦串口測試過程中,經(jīng)常會遇到某一配置未更改,以至于當(dāng)前配置失敗的問題,因?yàn)閱纹瑱C(jī)想要加入這一識別能力比較繁瑣,所以我在每種模式配置時都加入了對應(yīng)的前置條件,手冊沒寫,我這里設(shè)置一遍以防萬一。
????????后面的4種模式原理也都是一樣,可以按著我的方法,根據(jù)手冊的配置指導(dǎo)來寫。初始化時只需要配置到連接服務(wù)器,這樣esp就可以接收數(shù)據(jù)了,發(fā)送數(shù)據(jù)和接收數(shù)據(jù)作為一個單獨(dú)的模塊去調(diào)用。
esp發(fā)送數(shù)據(jù):
? ? ? ? 手冊中每種模式的發(fā)送數(shù)據(jù)部分,除了透傳,都是要先指定數(shù)據(jù)長度,再發(fā)送數(shù)據(jù)。但是單連接和多連接的指令也不太一樣,所以我寫了5種模式的發(fā)送函數(shù),再用一個封裝后的發(fā)送函數(shù),根據(jù)初始化時的設(shè)置自動調(diào)用對應(yīng)的函數(shù)。
1、模式2UDP比較有代表性:
//模式2
/**
* @brief UDP,esp發(fā)送數(shù)據(jù)到遠(yuǎn)端
* @param *data: 要發(fā)送的數(shù)據(jù)
* @retval state:返回1發(fā)送成功,0則失敗
*/
uint8_t mode_2_send_date(char *Data)
{
uint8_t state = esp8266_OK;//發(fā)送成功狀態(tài)
char str1[MAX_temp_array];
//發(fā)送數(shù)據(jù)
if(esp8266wifi_UDP_mode==0)//遠(yuǎn)端固定
{
sprintf(str1,"AT+CIPSEND=%d,%d",esp8266wifi_UDP_Link_ID,strlen(Data)+2);
}
else if(esp8266wifi_UDP_mode==2)//遠(yuǎn)端可變
{
sprintf(str1,"AT+CIPSEND=%d",strlen(Data)+2);
}
esp8266wifi_send_cmd(str1,">",normal_waittime);
state=esp8266wifi_send_cmd(Data,"SEND OK",MAX_waittime);
return state;
}
?2、封裝函數(shù):
/**
* @brief esp8266模塊發(fā)送數(shù)據(jù)
* @param *data:要發(fā)送的數(shù)據(jù)
* @param ID:要收到數(shù)據(jù)的ID號
* @retval result:返回1發(fā)送成功,0則失敗
*/
uint8_t esp8266_send_data(char *data,uint8_t ID)
{
uint8_t result=esp8266_OK, mode = esp8266wifi_working_mode;
switch (mode)
{
case 1:
result = mode_1_send_date(data);
break;
case 2:
result = mode_2_send_date(data);
break;
case 3:
case 4:
mode_3_and_4_send_date(data);
break;
case 5:
result = mode_5_send_date(data,ID);
break;
default:
break;
}
return result;
}
?3、透傳模式的發(fā)送不太一樣,需要進(jìn)入透傳發(fā)送狀態(tài),發(fā)送AT+CIPSEND后,模塊會返回一個符號“>”,這時不需要指定長度,直接輸入要發(fā)送的數(shù)據(jù)。想要退出透傳狀態(tài),需要發(fā)送“+++”,具體細(xì)節(jié)查看手冊。要使用這兩個函數(shù)時,在透傳模式初始化結(jié)束后,主函數(shù)調(diào)用即可。
/**
* @brief 開啟透傳發(fā)送
* @param 無
* @note 僅?持 TCP 單連接和 UDP 固定通信對端的情況
* @retval state:返回1成功,0則失敗
*/
void esp8266_start_trans(void)
{
esp8266wifi_send_cmd("AT+CIPSEND",">",MAX_waittime);
}
/**
* @brief 退出透傳發(fā)送
* @param 無
* @retval result:返回1發(fā)送成功,0則失敗
*/
uint8_t esp8266_quit_trans(void)
{
uint8_t result=esp8266_OK;
esp8266wifi_send_string("+++");
delay_ms(1000);
result=esp8266wifi_send_cmd("AT","OK",MAX_waittime);
if(!result)
printf("quit_trans failed!");
else
printf("quit_trans success!");
return result;
}
esp接收數(shù)據(jù):
? ? ? ? 在串口發(fā)送數(shù)據(jù)時可以看到,使用非透傳模式下的信息傳輸,esp在接收到數(shù)據(jù)后會向串口返回+IPD,<link ID>,數(shù)據(jù)長度:數(shù)據(jù)。在多連接下才有<link ID>。在透傳模式下直接取出串口緩沖數(shù)組,在其他模式下做相應(yīng)的數(shù)據(jù)截取。
/**
* @brief 接收數(shù)據(jù)處理,對esp8266返回的數(shù)據(jù)進(jìn)行解碼,并清除串口接收完成標(biāo)志位
* @param *true_data:接收到的有效數(shù)據(jù)
* @note 以下是esp8266返回數(shù)據(jù)的HEX顯示與16進(jìn)制顯示,串口接收數(shù)據(jù)時,已在串口接收中斷中濾除開頭的0D 0A
*
* +IPD,4:qq
* 0D 0A 2B 49 50 44 2C(,) 34 3A(:) 71 71 0D 0A
*
* +IPD,0,4:qq
* 0D 0A 2B 49 50 44 2C(,) 30 2C(,) 34 3A(:) 71 71 0D 0A
*
* @retval ID:發(fā)送數(shù)據(jù)的ID
*/
uint8_t esp8266_receive_data(char *true_data,uint8_t old_date[])
{
uint8_t ID=0;//多連接模式的ID號
uint8_t date_byte=5;//默認(rèn)從第一個逗號后一位開始,逗號以前的“+IPD”和逗號都不要(+IPD,)
uint8_t j,mode = esp8266wifi_working_mode;
char temp[MAX_temp_array];
if((mode==mode_3_TCP_transparent)||(mode==mode_4_UDP_transparent))
{
sprintf(true_data,"%s",(char *)old_date);
}
else
{
if(mode==mode_5_TCP_Server)//多連接模式
{
ID = old_date[5];
}
while(old_date[date_byte]!=0x3A)//冒號(:)
{
date_byte++;
}
date_byte++;//跳過冒號(:)
while(old_date[date_byte]!='\0')
{
temp[j] = old_date[date_byte];
date_byte++;
j++;
}
temp[j] = '\0';//結(jié)束符
sprintf(true_data,"%s",temp);
}
return ID;
}
底層函數(shù):
? ? ? ? 1、首先是調(diào)用率最高的stm32通過串口向esp8266發(fā)送數(shù)據(jù)函數(shù),這里需要注意的是有返回值校驗(yàn)部分,如果形參傳值0,則不進(jìn)行校驗(yàn)。waittime參數(shù)用于等待模塊返回的時間,有新數(shù)據(jù)返回則刷新等待時間。
/**
* @brief 向esp8266wifi發(fā)送指令,自動加上回車換行
* @param *cmd: 要發(fā)送的指令
* *expect: 期望指令,檢查模塊返回值,查看指令執(zhí)行情況,若不檢查,調(diào)用時給0(不帶引號)
* waittime: 等待數(shù)據(jù)接收時常(ms),等待模塊回應(yīng)的最大時間
* @retval state:應(yīng)答正確返回1,0則失敗
*/
uint8_t esp8266wifi_send_cmd(char *cmd,uint8_t *expect,int waittime)
{
uint8_t state=0;
int waittime_old=waittime;
char esp8_rx_data[MAX_temp_array];
char temp[MAX_temp_array];
esp8266wifi_rx_sta=0;
sprintf(temp,"%s\r\n",cmd);
esp8266wifi_send_string(temp);
while ((esp8266wifi_USART->SR & 0X40) == 0);
if(waittime)
{
while(--waittime)
{
delay_ms(1);
if(esp8266wifi_rx_sta&0X8000)
{
waittime=waittime_old;
sprintf(esp8_rx_data,"%s",(char *)esp8266wifi_rx_buf);
// printf("模塊返回:%s\n",esp8_rx_data);
if(expect)
{
if(esp8266wifi_check_cmd(expect,esp8_rx_data))
{
state=esp8266_OK;
printf("模塊應(yīng)答正確: %s\n",expect);
}
}
esp8266wifi_rx_sta=0;//清空接收完成標(biāo)志位
}
}
}
return state;
}
????????2、字符串校驗(yàn)
/**
* @brief 檢測應(yīng)答指令
* @param *str: 要驗(yàn)證的預(yù)期結(jié)果
* @retval *strx:與預(yù)期相同返回原字符串,不同則返回NULL
*/
uint8_t* esp8266wifi_check_cmd(uint8_t *str_target,char *str_rx)
{
str_rx=strstr((const char*)str_rx,(const char*)str_target);
return (uint8_t *)str_rx;
}
3、關(guān)閉連接函數(shù)
/**
* @brief 關(guān)閉當(dāng)前的連接
* @param ID:多連接關(guān)閉的ID,需要關(guān)閉的連接 ID 號。當(dāng) ID 為 5 時,關(guān)閉所有連接。
* (開啟 server 后 ID 為 5 ?效)
*/
void esp8266wifi_close_connect(uint8_t ID)
{
uint8_t num=esp8266wifi_working_mode;//獲取當(dāng)前的工作模式
if(num==1)//關(guān)閉單連接
{
esp8266wifi_send_cmd("AT+CIPCLOSE",0,MAX_waittime);//關(guān)閉單連接
}
else if(num==2)//關(guān)閉多連接
{
char str1[20];
sprintf(str1,"AT+CIPCLOSE=%d",ID);
esp8266wifi_send_cmd(str1,0,MAX_waittime);
}
}
esp8266.h:
#ifndef _8266wifi_H
#define _8266wifi_H
#include "sys.h"
#include "usart2.h"
/******************************************************************************************/
/* 串口更改,可以改為任意配置好的USART */
/*串口,接收完成標(biāo)志位,接收緩沖,串口發(fā)送函數(shù)*/
#define esp8266wifi_USART USART2_UX
#define esp8266wifi_rx_sta g_usart2_rx_sta
#define esp8266wifi_rx_buf g_usart2_rx_buf
#define esp8266wifi_send_string usart2_send_string
/******************************************************************************************/
/*服務(wù)器wifi 信息*/
/*名稱,密碼*/
#define SoftAP_WIFI_SSID "1111111"
#define SoftAP_WIFI_PASSWORD "11111111"
/*esp8266作為Station客戶端wifi 信息*/
/*名稱,密碼,通道,加密方式*/
/*加密方式
0:OPEN
2:WPA_PSK
3:WPA2_PSK
4:WPA_WPA2_PSK
*/
#define esp8266wifi_WIFI_SSID "NiDie"
#define esp8266wifi_WIFI_PASSWORD "12345678"
#define esp8266wifi_WIFI_channal 1
#define esp8266wifi_WIFI_encoding 4
/******************************************************************************************/
/*TCP傳輸信息*/
/*esp作為SoftAP服務(wù)器的IP和端口信息*/
#define esp8266wifi_SoftAP_IP "192.168.4.1"
#define esp8266wifi_SoftAP_PORT "8080"
/*esp作為Station客戶端,要接入的服務(wù)器IP和端口信息*/
#define esp8266wifi_TCP_IP "192.168.1.111"
#define esp8266wifi_TCP_PORT "8081"
/******************************************************************************************/
/*UDP傳輸信息*/
/*UDP遠(yuǎn)端和TCP的服務(wù)器使用同一組IP和端口,方便調(diào)試*/
/*IP,遠(yuǎn)程端口,連接ID,本地端口,端口保持*/
#define esp8266wifi_UDP_IP "192.168.1.113"
#define esp8266wifi_UDP_SoftAP_PORT "8081"
#define esp8266wifi_UDP_Link_ID 4
#define esp8266wifi_UDP_Local_PORT "1112"
#define esp8266wifi_UDP_mode 2
/*
? 0:收到數(shù)據(jù)后,不更改遠(yuǎn)端?標(biāo),默認(rèn)值為 0
? 1:收到數(shù)據(jù)后,改變?次遠(yuǎn)端?標(biāo)
? 2:收到數(shù)據(jù)后,改變遠(yuǎn)端?標(biāo)
*/
/*0 表示當(dāng)前 UDP 傳輸建?后,UDP 遠(yuǎn)端不會被其他設(shè)備更改;即使有其他設(shè)備通過 UDP 協(xié)議發(fā)數(shù)據(jù)到
ESP8266 UDP 端? 1112,ESP8266 的第 4 號 UDP 傳輸?shù)倪h(yuǎn)端也不會被替換,使?指令
“AT+CIPSEND=4, X” 發(fā)送數(shù)據(jù),仍然是當(dāng)前固定的 PC 端收到。*/
/*2 表示當(dāng)前 UDP 傳輸建?后,UDP 傳輸遠(yuǎn)端仍然會更改;UDP 傳輸遠(yuǎn)端會?動更改為最近?個與
ESP8266 UDP 通信的遠(yuǎn)端。*/
/*********************************************************************************************/
/*變量定義*/
/*數(shù)組最大值,等待回復(fù)時間,不校驗(yàn)時的等待時間*/
#define MAX_temp_array 200
#define MAX_waittime 3000
#define normal_waittime 200
/*工作模式*/
extern uint8_t esp8266wifi_working_mode;
/*初始化錯誤時的嘗試次數(shù)*/
#define esp8266_Init_Try_Time 5
/*********************************************************************************************/
/*底層函數(shù)*/
uint8_t* esp8266wifi_check_cmd(uint8_t *str_target,char *str_rx);
void esp8266wifi_reset(void);
void esp8266wifi_set_trans_mode(uint8_t mode);
void esp8266wifi_set_wifi_mode(uint8_t mode);
uint8_t esp8266wifi_send_cmd(char *cmd,uint8_t *expect,int waittime);
void esp8266wifi_close_connect(uint8_t ID);
/*5種模式發(fā)送數(shù)據(jù),可單獨(dú)調(diào)用*/
uint8_t mode_1_send_date(char *data);
uint8_t mode_2_send_date(char *Data);
uint8_t mode_2_send_date_IP(char *Data,char *SendIP,uint16_t SendPort);
void mode_3_and_4_send_date(char *data);
uint8_t mode_5_send_date(char *Data,uint8_t Link_ID);
/*********************************************************************************************/
/*用戶調(diào)用函數(shù)*/
void esp8266_start_trans(void);
uint8_t esp8266_quit_trans(void);
uint8_t esp8266_Init(uint8_t RUNmode,uint8_t wifi_mode);
uint8_t esp8266_send_data(char *data,uint8_t ID);
uint8_t esp8266_receive_data(char *true_data,uint8_t old_date[]);
/*********************************************************************************************/
/*初始化函數(shù)傳參定義*/
/*工作模式定義*/
#define mode_1_TCP_Client 1
#define mode_2_UDP 2
#define mode_3_TCP_transparent 3
#define mode_4_UDP_transparent 4
#define mode_5_TCP_Server 5
/*wifi模式:1為連接模式,2為熱點(diǎn)模式,3為雙開*/
#define wifi_mode_Station 1
#define wifi_mode_SoftAP 2
#define wifi_mode_SoftAP_Station 3
/*返回值狀態(tài)*/
#define esp8266_OK 1
#define esp8266_ERROR 0
#endif
主函數(shù)main.c:
????????目的是在于檢查信息的發(fā)送是否正確,電腦串口控制esp進(jìn)行數(shù)據(jù)的發(fā)送和讀取。
int main(void)
{
HAL_Init(); /* 初始化HAL庫 */
sys_stm32_clock_init(RCC_PLL_MUL9); /* 設(shè)置時鐘, 72Mhz */
delay_init(72); /* 延時初始化 */
usart_init(115200); /* 初始化串口 */
led_init(); /* 初始化LED */
// OLED_Init();
usart2_init(115200);
if(esp8266_Init(mode_1_TCP_Client,wifi_mode_Station)==esp8266_OK)
{
printf("\r\nesp8266 模式 %d 初始化完成!\r\n",mode_1_TCP_Client);
}
else
{
printf("\r\nesp8266初始化失敗\r\n");
while(1)
{
LED0_TOGGLE();
delay_ms(200);
}
}
char rx_data[128];
uint8_t ID=0;
while (1)
{
if(esp8266wifi_rx_sta&0X8000)//esp收到的信息通過串口一打印
{
printf("\nGot Date!\n");
ID = esp8266_receive_data(rx_data,esp8266wifi_rx_buf);
if(ID)
{
printf("ID :%d,收到的信息: %s\n",ID,rx_data);
}
else
{
printf("收到的信息: %s\n",rx_data);
}
esp8266wifi_rx_sta=0;
}
if(g_usart_rx_sta&0X8000) //串口一收到的信息發(fā)送到esp
{
while ((USART_UX->SR & 0X40) == 0); /* 等待上一個字符發(fā)送完成 */
esp8266_send_data((char *)g_usart_rx_buf,ID);
// printf("%s\n",g_usart_rx_buf);
g_usart_rx_sta = 0;
}
LED0_TOGGLE();
delay_ms(500);
}
}
實(shí)驗(yàn)現(xiàn)象:
????????開始實(shí)驗(yàn)前要打開電腦端的服務(wù)器,這里初始化用的模式1。等待初始化完成即可發(fā)送信息。網(wǎng)絡(luò)助手和esp進(jìn)行數(shù)據(jù)通信。
?文章來源:http://www.zghlxwxcb.cn/news/detail-733817.html
?總結(jié):
本次實(shí)驗(yàn)有很多可以改進(jìn)的地方,比如等待時間長,初始化時間也長。但是有點(diǎn)懶,就放著吧。讀者有什么建議都可以找我,有問題的還請指正。文章來源地址http://www.zghlxwxcb.cn/news/detail-733817.html
到了這里,關(guān)于STM32+esp8266實(shí)現(xiàn)單片機(jī)與服務(wù)器的WiFi通信的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!