一、固件庫模板
見博客:stm32f103c8t6新建固件庫模板(可自?。?/p>
二、準(zhǔn)備資料
-
固件庫模板
-
MDK5開發(fā)環(huán)境
-
stm32參考手冊
-
UART串口協(xié)議
-
stm32中斷概念
-
ESP8266模塊資料
-
利用固件庫模板點燈工程(下面第三行,手動狗頭)
-
CH340 USB→TTL模塊
-
ESP8266模塊
-
手機軟件
實驗程序已經(jīng)發(fā)布到百度網(wǎng)盤,本文末有鏈接可以自取
stm32參考手冊
串口協(xié)議查看這篇博客USART串口協(xié)議
stm32中斷概念STM32中斷應(yīng)用概括
ESP8266模塊資料:ESP8266
串口調(diào)試工具 :https://pan.baidu.com/s/1V-jRJzb0INDXDLo9I4CJ6A 提取碼:0000
網(wǎng)絡(luò)助手(PC):https://pan.baidu.com/s/1EeDtr7eW-mIuOEZa1_4BWA 提取碼:0000
網(wǎng)絡(luò)調(diào)試助手(安卓)鏈接: https://pan.baidu.com/s/1uDGpyGt8VyUzcZXmWfTqhw 提取碼: 0000
三、簡介
ESP8266
是一款超低功耗的UART-WiFi 透傳模塊,擁有業(yè)內(nèi)極富競爭力的封裝尺寸和超低能耗技術(shù),專為移動設(shè)備和物聯(lián)網(wǎng)應(yīng)用設(shè)計,可將用戶的物理設(shè)備連接到Wi-Fi 無線網(wǎng)絡(luò)上
,進行互聯(lián)網(wǎng)或局域網(wǎng)通信,實現(xiàn)萬物互聯(lián)功能。
- 支持STA/AP/STA+AP 三種工作模式
- 內(nèi)置TCP/IP協(xié)議棧,支持多路TCP Client連接
- 支持UART/GPIO數(shù)據(jù)通信接口
- 支持Smart Link 智能聯(lián)網(wǎng)功能
- 內(nèi)置32位MCU,可兼作應(yīng)用處理器
- 3.3V 單電源供電
- 支持豐富的Socket AT指令
1. 引腳
標(biāo)號 | PIN | 引腳說明 |
---|---|---|
1 | 3V3 | 模塊供電正極 |
2 | RST | 低電平復(fù)位,高電平工作(默認(rèn)高) |
3 | EN | 使能端,需要進入命令模式時接3.3V |
4 | TX | 發(fā)送端 |
5 | RX | 接收端 |
6 | IO0 | 工作模式選擇:懸空:FlashBoot,工作模式;下拉:UARTDownload,下載模式 |
7 | IO2 | (1)開機上電時必須為高電平,禁止硬件下拉;(2)內(nèi)部默認(rèn)已拉高 |
8 | GND | 模塊供電負(fù)極 |
本模塊使用USART協(xié)議,具體請看下面兩個博客,這里就不繼續(xù)講解了
USART串口協(xié)議
四、stm32-USART串口通訊(重定向、接發(fā)通信、控制LED亮滅)
2. 無線組網(wǎng)
ESP8266 支持 softAP 模式, station 模式, softAP + station 共存模式三種。
利用 ESP8266 可以實現(xiàn)十分靈活的組網(wǎng)方式和網(wǎng)絡(luò)拓?fù)洹?/p>
- SoftAP: 即無線接入點, 是一個無線網(wǎng)絡(luò)的中心節(jié)點。通常使用的無線路由器就是一個無線接入點。
- Station:即無線終端, 是一個無線網(wǎng)絡(luò)的終端。
2.1 ESP8266 在 SoftAP 模式
ESP8266 作為 softAP(熱點
),手機、 電腦、 用戶設(shè)備、 其他 ESP8266 station 接口等均可以作為 station(終端用戶
) 連入ESP8266, 組建成一個局域網(wǎng)。
2.2 ESP8266 在 station 模式
ESP8266 作為 station,通過路由器(AP) 連入 internet ,可向云端服務(wù)器上傳、 下載數(shù)據(jù)。用戶可隨時使用移動終端(手機、 筆記本等) ,通過云端監(jiān)控 ESP8266 模塊的狀況, 向 ESP8266 模塊發(fā)送控制指令。
簡單的來說就是ESP連接熱點(可以上網(wǎng)),也可以手機上網(wǎng),此時手機可以控制ESP8266
2.3 ESP8266 在 SoftAP + station 共存模式
ESP8266 支持 softAP+station 共存的模式,用戶設(shè)備、 手機等可以作為station 連入 ESP8266 的 softAP 接口,同時, 可以控制 ESP8266 的 station接口通過路由器(AP) 連入 internet。
3、透傳功能
透傳, 即透明傳輸功能
。 Host 通過 uart 將數(shù)據(jù)發(fā)給ESP8266, ESP8266 再通過無線網(wǎng)絡(luò)將數(shù)據(jù)傳出去;ESP8266 通過無線網(wǎng)絡(luò)接收到的數(shù)據(jù),同理通過uart 傳到 Host。 ESP8266 只負(fù)責(zé)將數(shù)據(jù)傳到目標(biāo)地址,不對數(shù)據(jù)進行處理,發(fā)送方和接收方的數(shù)據(jù)內(nèi)容、 長度完全一致,傳輸過程就好像透明一樣。
透傳需要先建立連接:
Q: 什么是透傳模式?
A: 透傳模式影響發(fā)送數(shù)據(jù)的方式。
如果不開啟透傳模式,發(fā)送數(shù)據(jù)前都必須先發(fā)送指令A(yù)T+CIPSEND=,例如:
AT+CIPSEND=4
OK
> //在 > 后面輸入要上傳的數(shù)據(jù)
開啟了透傳模式:
AT+CIPMODE=1 進入透傳模式
AT+CIPSEND 之后發(fā)送的所有內(nèi)容將全部當(dāng)成數(shù)據(jù)
退出透傳模式: 發(fā)送數(shù)據(jù)"+++
"就可以了。注意:此時“+++”后面,不接發(fā)送新行
!
注意:透傳只能在單連接模式下進行,所以在建立連接之前一定要用(AT+CIPMUX=0 設(shè)置單連接)
> AT+CIPMODE=1
> CIPMUX and CIPSERVER must be 0
4. 基本配置(所有AT指令都必須換行)
命令 | 描述 |
---|---|
基礎(chǔ)指令 | |
AT | 測試 AT 啟動 |
AT+RST | 重啟模塊 |
AT+GMR | 查看版本信息 |
wifi 功能指令 | |
AT+CWMODE | 選擇 WIFI 應(yīng)用模式 |
AT+CWJAP | 加入 AP |
AT+CWLAP | 列出當(dāng)前可用 AP |
AT+CWQAP | 退出與 AP 的連接 |
AT+CWSAP | 設(shè)置 AP 模式下的參數(shù) |
AT+ CWLIF | 查看已接入設(shè)備的 IP |
TCP/IP 指令 | |
AT+CIPSTATUS | 獲得連接狀態(tài) |
AT+CIPSTART | 建立 TCP 連接或注冊 UDP 端口號 |
AT+CIPSEND | 發(fā)送數(shù)據(jù) |
AT+CIPCLOSE | 關(guān)閉 TCP 或 UDP |
AT+CIFSR | 獲取本地 IP 地址 |
AT+CIPMUX | 啟動多連接 |
AT+CIPSERVER | 配置為服務(wù)器 |
AT+CIPMODE | 設(shè)置模塊傳輸模式 |
AT+CIPSTO | 設(shè)置服務(wù)器超時時間 |
+IPD | 接收到的數(shù)據(jù) |
AT命令的詳細說明在ESP8266這里面什么都有
4. 模式配置
4.1 STA 模式
STA 模式: ESP8266模塊通過路由器連接互聯(lián)網(wǎng),手機或電腦通過互聯(lián)網(wǎng)實現(xiàn)對設(shè)備的遠程控制。
配置步驟:
1. AT+CWMODE=1 設(shè)置模組為STA模式。(串口助手)
2. AT+CWLAP 查詢附近 WIFI(串口助手)
3. AT+CWJAP="1202","12345678" 連接 WIFI(串口助手)
4. AT+CIPMUX=0 打開單連接(串口助手)
5. AT+CIPSTART="TCP","192.168.2.6",808 (自己對應(yīng)的ip地址,端口號隨便,只要沒有被占用都行)
6. AT+CIPMODE=1 使用透傳模式
7. AT+CIPSEND
4.2 AP 模式
AP 模式: ESP8266模塊作為熱點,實現(xiàn)手機或電腦直接與模塊通信,實現(xiàn)局域網(wǎng)無線控制。
配置步驟:
1. AT+CWMODE=2
2. AT+CIPAP="192.168.4.1"
3. AT+CWSAP="ESP8266","12345678",1,0
4. AT+CIPMUX=1
5. AT+CIPSERVER=1,8888
6. AT+CIPSTO=1800
7. AT+CIFSR
四、實驗
1.硬件設(shè)計
- ESP8266與串口通信
GND接GND
VCC接3.3
RXD—CH340的TXD
TXD—CH340的RXD - 用ESP8266控制MCU
CH340的TXD-----USART1的RX引腳相連(c8t6 的PA10)
CH340的RXD-----USART1的TX引腳相連(c8t6 的PA9)
ESP8266的TXD-----USART2的RX引腳相連(c8t6 的PA3)
ESP8266的RXD-----USART2的TX引腳相連(c8t6 的PA2)
2.軟件設(shè)計
-
使能 RX 和 TX 引腳 GPIO 時鐘和 USART 時鐘;
-
初始化 GPIO,并將 GPIO 復(fù)用到 USART 上;
-
配置 USART 參數(shù);
-
配置中斷控制器并使能 USART 接收中斷;
-
使能 USART;
-
在 USART 接收中斷服務(wù)函數(shù)實現(xiàn)數(shù)據(jù)接收和發(fā)送。
2.1 復(fù)制工程 (復(fù)制stm32-USART串口通訊工程)
四、stm32-USART串口通訊(重定向、接發(fā)通信、控制LED亮滅)
2.2 新建hc_05文件(打開工程)
2.3 編寫代碼
1. 使用串口助手和網(wǎng)絡(luò)助手實現(xiàn)ESP8266通信
ESP8266的波特率為115200,8位數(shù)據(jù)位、1位停止位、無奇偶校驗的通信格式。
-
發(fā)送
AT
,回復(fù)OK -
AT+CWMODE=1 設(shè)置模組為STA模式。
-
AT+CWLAP 查詢附近 WIFI
-
AT+CWJAP=“XXX”,“XXXX” 連接 WIFI(必須為第3步能查找到的)
-
AT+CIPMUX=0 打開單連接(否則不能透傳)
-
AT+CIPSTART=“TCP”,“192.168.2.6”,808 (自己對應(yīng)的ip地址,端口號隨便,只要沒有被占用都行)
-
AT+CIPMODE=1 使用透傳模式
-
AT+CIPSEND
2. 使用ESP8266 STA模式實現(xiàn)透傳功能
2.1 復(fù)制工程 (復(fù)制stm32-USART串口通訊工程)
四、stm32-USART串口通訊(重定向、接發(fā)通信、控制LED亮滅)
2.2 新建文件,打開工程,添加路徑
usart.c
在USART1_IRQHandler方法下面添加 usart2的初始化和中斷
struct STRUCT_USARTx_Fram strEsp8266_Fram_Record = { 0 };
volatile uint8_t ucTcpClosedFlag = 0;
void uart2_init(u32 bound) {
//GPIO端口設(shè)置
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //使能USART1,GPIOA時鐘
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2,ENABLE);
//USART2_TX GPIOA.2
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; //PA2
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //復(fù)用推挽輸出
GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA2
//USART2_RX GPIOA.3初始化
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;//PA3
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空輸入
GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.3
//Usart2 NVIC 配置
NVIC_PriorityGroupConfig(macNVIC_PriorityGroup_x);
NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0 ;//搶占優(yōu)先級3
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //子優(yōu)先級3
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
NVIC_Init(&NVIC_InitStructure); //根據(jù)指定的參數(shù)初始化VIC寄存器
//USART 初始化設(shè)置
USART_InitStructure.USART_BaudRate = bound;//串口波特率
USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字長為8位數(shù)據(jù)格式
USART_InitStructure.USART_StopBits = USART_StopBits_1;//一個停止位
USART_InitStructure.USART_Parity = USART_Parity_No;//無奇偶校驗位
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//無硬件數(shù)據(jù)流控制
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //收發(fā)模式
USART_Init(USART2, &USART_InitStructure); //初始化串口1
USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);//開啟串口接受中斷
USART_ITConfig(USART2, USART_IT_IDLE, ENABLE);//使能串口總線空閑中斷
USART_Cmd(USART2, ENABLE);
}
void USART2_IRQHandler(void) //串口1中斷服務(wù)程序
{
u8 Res;
if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET) //接收中斷(接收到的數(shù)據(jù)必須是0x0d 0x0a結(jié)尾)
{
Res =USART_ReceiveData(USART2); //讀取接收到的數(shù)據(jù)
//USART_SendData(USART1,Res);
if ( strEsp8266_Fram_Record .InfBit .FramLength < ( RX_BUF_MAX_LEN - 1 ) ) //預(yù)留1個字節(jié)寫結(jié)束符
strEsp8266_Fram_Record .Data_RX_BUF [ strEsp8266_Fram_Record .InfBit .FramLength ++ ] = Res;
}
if ( USART_GetITStatus( USART2, USART_IT_IDLE ) == SET ) //數(shù)據(jù)幀接收完畢
{
strEsp8266_Fram_Record .InfBit .FramFinishFlag = 1;
Res = USART_ReceiveData( USART2 );
ucTcpClosedFlag = strstr ( strEsp8266_Fram_Record .Data_RX_BUF, "CLOSED\r\n" ) ? 1 : 0;
}
}
usart.h
添加strHC05_Fram_Record結(jié)構(gòu)體和uart2_init(u32 bound)函數(shù)
extern struct STRUCT_USARTx_Fram //串口數(shù)據(jù)幀的處理結(jié)構(gòu)體
{
//STRUCT_USARTx_Fram 讀取的數(shù)據(jù)
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;
};
}strUSART_Fram_Record,strEsp8266_Fram_Record;
//如果想串口中斷接收,請不要注釋以下宏定義
void uart1_init(u32 bound);
void uart2_init(u32 bound);
esp8266.c
#include "esp8266.h"
#include "delay.h"
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
/********************************************************************************
*
RST -- A4
EN -- A5
TX -- A2(USART2_TX)
RX -- A3(USART2_RX)
********************************************************************************/
static void ESP8266_GPIO_Config ( void );
/**
* @brief ESP8266初始化函數(shù)
* @param 無
* @retval 無
*/
void ESP8266_Init ( void )
{
ESP8266_GPIO_Config ();
ESP8266_RST_HIGH_LEVEL();
ESP8266_CH_DISABLE();
}
/**
* @brief 初始化ESP8266用到的GPIO引腳
* @param 無
* @retval 無
*/
static void ESP8266_GPIO_Config ( void )
{
/*定義一個GPIO_InitTypeDef類型的結(jié)構(gòu)體*/
GPIO_InitTypeDef GPIO_InitStructure;
/* 配置 CH_PD 引腳*/
ESP8266_CH_PD_APBxClock_FUN ( ESP8266_CH_PD_CLK, ENABLE );
GPIO_InitStructure.GPIO_Pin = ESP8266_CH_PD_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init ( ESP8266_CH_PD_PORT, & GPIO_InitStructure );
/* 配置 RST 引腳*/
ESP8266_RST_APBxClock_FUN ( ESP8266_RST_CLK, ENABLE );
GPIO_InitStructure.GPIO_Pin = ESP8266_RST_PIN;
GPIO_Init ( ESP8266_RST_PORT, & GPIO_InitStructure );
}
/*
* 函數(shù)名:ESP8266_Cmd
* 描述 :對WF-ESP8266模塊發(fā)送AT指令
* 輸入 :cmd,待發(fā)送的指令
* reply1,reply2,期待的響應(yīng),為NULL表不需響應(yīng),兩者為或邏輯關(guān)系
* waittime,等待響應(yīng)的時間
* 返回 : 1,指令發(fā)送成功
* 0,指令發(fā)送失敗
* 調(diào)用 :被外部調(diào)用
*/
bool ESP8266_Cmd ( char *cmd, char *reply1, char *reply2, u32 waittime )
{
strEsp8266_Fram_Record .InfBit .FramLength = 0; //從新開始接收新的數(shù)據(jù)包
ESP8266_Usart ( "%s\r\n", cmd );
if ( ( reply1 == 0 ) && ( reply2 == 0 ) ) //不需要接收數(shù)據(jù)
return true;
Delay_ms ( waittime ); //延時
//增加一個結(jié)束符。
strEsp8266_Fram_Record .Data_RX_BUF [ strEsp8266_Fram_Record .InfBit .FramLength ] = '\0';
//將USART2接收到的東西全部打印出來,接收到的保存在這個數(shù)組里,
//通過串口1發(fā)送出來,這樣就能看到,我們發(fā)送的指令的響應(yīng),是否出錯,
//例如:發(fā)送AT,響應(yīng)是OK, ESP_USART接收到的數(shù)據(jù)是AT OK.在交給USART1發(fā)送,在PC機的串口調(diào)試助手可以看到這些信息,
PC_Usart ( "%s", strEsp8266_Fram_Record .Data_RX_BUF );
strEsp8266_Fram_Record .InfBit .FramLength = 0; //清除接收標(biāo)志
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 ) );
else
return ( ( bool ) strstr ( strEsp8266_Fram_Record .Data_RX_BUF, reply2 ) );
}
/*
* 函數(shù)名:ESP8266_Rst
* 描述 :重啟WF-ESP8266模塊
* 輸入 :無
* 返回 : 無
* 調(diào)用 :被 ESP8266_AT_Test 調(diào)用
*/
void ESP8266_Rst ( void )
{
#if 0
ESP8266_Cmd ( "AT+RST", "OK", "ready", 2500 );
#else
ESP8266_RST_LOW_LEVEL();
Delay_ms ( 500 );
ESP8266_RST_HIGH_LEVEL();
#endif
}
/*
* 函數(shù)名:ESP8266_DHCP_CUR
* 描述 :
<mode>:
0:設(shè)置 ESP8266 SoftAP
1:設(shè)置 ESP8266 Station
2:設(shè)置 ESP8266 SoftAP 和 Station
<en>:
0:關(guān)閉 DHCP
1:開啟 DHCP
* 輸入 :None
* 返回 :1/0
* 調(diào)用 :ESP8266_StaTcpClient_Unvarnish_ConfigTest調(diào)用
*/
bool ESP8266_DHCP_CUR ( )
{
char cCmd [40];
//把格式數(shù)據(jù)寫成串(函數(shù)指令)
sprintf ( cCmd, "AT+CWDHCP_CUR=1,1");
return ESP8266_Cmd ( cCmd, "OK", NULL, 500 );
}
bool ESP8266_AT_Test ( void )
{
char count = 0;
ESP8266_RST_HIGH_LEVEL();
printf("\r\nAT測試.....\r\n");
Delay_ms ( 2000 );
while ( count < 10 )
{
printf("\r\nAT測試次數(shù) %d......\r\n", count);
if( ESP8266_Cmd ( "AT", "OK", NULL, 500 ) )
{
printf("\r\nAT測試啟動成功 %d......\r\n", count);
return 1;
}
ESP8266_Rst();
++ count;
}
return 0;
}
/*
* 函數(shù)名:ESP8266_Net_Mode_Choose
* 描述 :設(shè)置WF模式—ESP8266工作方式
* 輸入 :None
* 返回 :狀態(tài)值
* 調(diào)用 :內(nèi)部調(diào)用
*/
bool ESP8266_Net_Mode_Choose(ENUM_Net_ModeTypeDef enumMode)
{
switch (enumMode)
{
//設(shè)置WiFi模式
case STA :
return ESP8266_Cmd("AT+CWMODE=1", "OK", "no change", 2500);
case AP:
return ESP8266_Cmd("AT+CWMODE=2", "OK", "no change", 2500);
case STA_AP:
return ESP8266_Cmd("AT+CWMODE=3", "OK", "no change", 2500);
default:
return false;
}
}
/*
* 函數(shù)名:ESP8266_JoinAP
* 描述 :WF-ESP8266模塊連接外部WiFi
* 輸入 :pSSID,WiFi名稱字符串
* :pPassWord,WiFi密碼字符串
* 返回 : 1,連接成功
* 0,連接失敗
* 調(diào)用 :被外部調(diào)用
*/
bool ESP8266_JoinAP(char *pSSID, char *pPassWord)
{
char cCmd [120];
//把格式數(shù)據(jù)寫成串(函數(shù)指令)
sprintf ( cCmd, "AT+CWJAP=\"%s\",\"%s\"", pSSID, pPassWord);
return ESP8266_Cmd ( cCmd, "OK", NULL, 1500 );
}
/*
* 函數(shù)名:ESP8266_BuildAP
* 描述 :WF-ESP8266模塊創(chuàng)建WiFi熱點
* 輸入 :pSSID,WiFi名稱字符串
* :pPassWord,WiFi密碼字符串
* :enunPsdMode,WiFi加密方式代號字符串
* 返回 : 1,創(chuàng)建成功
* 0,創(chuàng)建失敗
* 調(diào)用 :被外部調(diào)用
*/
bool ESP8266_BuildAP ( char * pSSID, char * pPassWord, ENUM_AP_PsdMode_TypeDef enunPsdMode )
{
char cCmd [120];
sprintf ( cCmd, "AT+CWSAP=\"%s\",\"%s\",1,%d", pSSID, pPassWord, enunPsdMode );
return ESP8266_Cmd ( cCmd, "OK", 0, 1000 );
}
/*
* 函數(shù)名:ESP8266_Enable_MultipleId
* 描述 :WF-ESP8266模塊啟動多連接
* 輸入 :enumEnUnvarnishTx,配置是否多連接
* 返回 : 1,配置成功
* 0,配置失敗
* 調(diào)用 :被外部調(diào)用
*/
bool ESP8266_Enable_MultipleId ( FunctionalState enumEnUnvarnishTx )
{
char cStr [20];
//啟動多連接
sprintf ( cStr, "AT+CIPMUX=%d", ( enumEnUnvarnishTx ? 1 : 0 ) );
return ESP8266_Cmd ( cStr, "OK", 0, 500 );
}
/*
* 函數(shù)名:ESP8266_Link_Server
* 描述 :WF-ESP8266模塊連接外部服務(wù)器,
* 輸入 :enumE,網(wǎng)絡(luò)協(xié)議
* :ip,服務(wù)器IP地址字符串
* :ComNum,服務(wù)器端口字符串
* :id,模塊連接服務(wù)器的ID
* 返回 : 1,連接成功
* 0,連接失敗
* 調(diào)用 :被外部調(diào)用
*/
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:
//"TCP","iot.espressif.cn",8000
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 )
//建立TCP連接
sprintf ( cCmd, "AT+CIPSTART=%d,%s", id, cStr);
else
sprintf ( cCmd, "AT+CIPSTART=%s", cStr );
//如果連接已經(jīng)存在,則返回ALREAY CONNECT
return ESP8266_Cmd ( cCmd, "OK", "ALREAY CONNECT", 4000 );
}
/*
* 函數(shù)名:ESP8266_StartOrShutServer
* 描述 :WF-ESP8266模塊開啟或關(guān)閉服務(wù)器模式
* 輸入 :enumMode,開啟/關(guān)閉
* :pPortNum,服務(wù)器端口號字符串
* :pTimeOver,服務(wù)器超時時間字符串,單位:秒
* 返回 : 1,操作成功
* 0,操作失敗
* 調(diào)用 :被外部調(diào)用
*/
bool ESP8266_StartOrShutServer ( FunctionalState enumMode, char *pPortNum, char *pTimeOver )
{
char cCmd1 [120], cCmd2 [120];
if ( enumMode )
{
//建立TCP服務(wù)器
sprintf ( cCmd1, "AT+CIPSERVER=%d,%s", 1, pPortNum );
//設(shè)置TCP服務(wù)器超出時間
sprintf ( cCmd2, "AT+CIPSTO=%s", pTimeOver );
return ( ESP8266_Cmd ( cCmd1, "OK", 0, 500 ) &&
ESP8266_Cmd ( cCmd2, "OK", 0, 500 ) );
}
else
{
sprintf ( cCmd1, "AT+CIPSERVER=%d,%s", 0, pPortNum );
return ESP8266_Cmd ( cCmd1, "OK", 0, 500 );
}
}
/*
* 函數(shù)名:ESP8266_Get_LinkStatus
* 描述 :獲取 WF-ESP8266 的連接狀態(tài),較適合單端口時使用
* 輸入 :無
* 返回 : ESP8266 Station 接?口的狀態(tài)
* 2: ESP8266 Station 已連接 AP,獲得 IP 地址
* 3: ESP8266 Station 已建立 TCP 或 UDP 傳輸
* 4: ESP8266 Station 斷開網(wǎng)絡(luò)連接
* 0: ESP8266 Station 獲取狀態(tài)失敗
* 調(diào)用 :被外部調(diào)用
*/
uint8_t ESP8266_Get_LinkStatus ( void )
{
//查詢 WF-ESP8266 的連接狀態(tài)
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;
}
/*
* 函數(shù)名:ESP8266_Get_IdLinkStatus
* 描述 :獲取 WF-ESP8266 的端口(Id)連接狀態(tài),較適合多端口時使用
* 輸入 :無
* 返回 : 端口(Id)的連接狀態(tài),低5位為有效位,分別對應(yīng)Id5~0,某位若置1表該Id建立了連接,若被清0表該Id未建立連接
* 調(diào)用 :被外部調(diào)用
*/
uint8_t ESP8266_Get_IdLinkStatus ( void )
{
uint8_t ucIdLinkStatus = 0x00;
if ( ESP8266_Cmd ( "AT+CIPSTATUS", "OK", 0, 500 ) )
{
if ( strstr ( strEsp8266_Fram_Record .Data_RX_BUF, "+CIPSTATUS:0," ) )
//給第一位置1
ucIdLinkStatus |= 0x01;
else
//給第一位清0
ucIdLinkStatus &= ~ 0x01;
if ( strstr ( strEsp8266_Fram_Record .Data_RX_BUF, "+CIPSTATUS:1," ) )
ucIdLinkStatus |= 0x02;
else
ucIdLinkStatus &= ~ 0x02;
if ( strstr ( strEsp8266_Fram_Record .Data_RX_BUF, "+CIPSTATUS:2," ) )
ucIdLinkStatus |= 0x04;
else
ucIdLinkStatus &= ~ 0x04;
if ( strstr ( strEsp8266_Fram_Record .Data_RX_BUF, "+CIPSTATUS:3," ) )
ucIdLinkStatus |= 0x08;
else
ucIdLinkStatus &= ~ 0x08;
if ( strstr ( strEsp8266_Fram_Record .Data_RX_BUF, "+CIPSTATUS:4," ) )
ucIdLinkStatus |= 0x10;
else
ucIdLinkStatus &= ~ 0x10;
}
return ucIdLinkStatus;
}
/*
* 函數(shù)名:ESP8266_Inquire_ApIp
* 描述 :獲取 ESP8266 的 AP IP
* 輸入 :pApIp,存放 AP IP 的數(shù)組的首地址
* ucArrayLength,存放 AP IP 的數(shù)組的長度
* 返回 : 0,獲取失敗
* 1,獲取成功
* 調(diào)用 :被外部調(diào)用
*/
uint8_t ESP8266_Inquire_ApIp ( char *pApIp, uint8_t ucArrayLength )
{
char uc;
char *pCh;
//查詢本地 IP 地址
ESP8266_Cmd ( "AT+CIFSR", "OK", 0, 500 );
pCh = strstr ( strEsp8266_Fram_Record .Data_RX_BUF, "APIP,\"" );
if ( pCh )
pCh += 6;
else
return 0;
for ( uc = 0; uc < ucArrayLength; uc ++ )
{
pApIp [ uc ] = * ( pCh + uc);
if ( pApIp [ uc ] == '\"' )
{
pApIp [ uc ] = '\0';
break;
}
}
return 1;
}
/*
* 函數(shù)名:ESP8266_UnvarnishSend
* 描述 :配置WF-ESP8266模塊進入透傳發(fā)送
* 輸入 :無
* 返回 : 1,配置成功
* 0,配置失敗
* 調(diào)用 :被外部調(diào)用
*/
bool ESP8266_UnvarnishSend ( void )
{
//先設(shè)置傳輸模式,如果連接斷開會不斷重連,除非+++
if ( ! ESP8266_Cmd ( "AT+CIPMODE=1", "OK", 0, 500 ) )
return false;
//在透傳模式時,開始發(fā)送數(shù)據(jù)
return
ESP8266_Cmd ( "AT+CIPSEND", "OK", ">", 500 );
}
/*
* 函數(shù)名:ESP8266_ExitUnvarnishSend
* 描述 :配置WF-ESP8266模塊退出透傳模式
* 輸入 :無
* 返回 : 無
* 調(diào)用 :被外部調(diào)用
*/
void ESP8266_ExitUnvarnishSend ( void )
{
Delay_ms ( 1000 );
ESP8266_Usart ( "+++" );
Delay_ms ( 500 );
}
/*
* 函數(shù)名:ESP8266_SendString
* 描述 :WF-ESP8266模塊發(fā)送字符串
* 輸入 :enumEnUnvarnishTx,聲明是否已使能了透傳模式
* :pStr,要發(fā)送的字符串
* :ulStrLength,要發(fā)送的字符串的字節(jié)數(shù)
* :ucId,哪個ID發(fā)送的字符串
* 返回 : 1,發(fā)送成功
* 0,發(fā)送失敗
* 調(diào)用 :被外部調(diào)用
*/
bool ESP8266_SendString ( FunctionalState enumEnUnvarnishTx, char *pStr, u32 ulStrLength, ENUM_ID_NO_TypeDef ucId )
{
char cStr [20];
bool bRet = false;
//如果設(shè)置透傳模式直接發(fā)送信息
if ( enumEnUnvarnishTx )
{
ESP8266_Usart ( "%s", pStr );
bRet = true;
}
else
//先看什么連接再發(fā)送數(shù)據(jù)的長度,再發(fā)送數(shù)據(jù)
{
//如果是多連接需要AT+CIPSEND=<link ID>,<length>把格式數(shù)據(jù)寫成串
if ( ucId < 5 )
sprintf ( cStr, "AT+CIPSEND=%d,%d", ucId, ulStrLength + 2 );
else
sprintf ( cStr, "AT+CIPSEND=%d", ulStrLength + 2 );
//先返回>再接收串口數(shù)據(jù)
ESP8266_Cmd ( cStr, "> ", 0, 100 );
//如果數(shù)據(jù)發(fā)送成功,返回:SEND OK,否則SEND FATL
bRet = ESP8266_Cmd ( pStr, "SEND OK", 0, 500 );
}
return bRet;
}
/*
* 函數(shù)名:ESP8266_ReceiveString
* 描述 :WF-ESP8266模塊接收字符串
* 輸入 :enumEnUnvarnishTx,聲明是否已使能了透傳模式
* 返回 : 接收到的字符串首地址
* 調(diào)用 :被外部調(diào)用
*/
char *ESP8266_ReceiveString ( FunctionalState enumEnUnvarnishTx )
{
char *pRecStr = 0;
strEsp8266_Fram_Record .InfBit .FramLength = 0;
strEsp8266_Fram_Record .InfBit .FramFinishFlag = 0;
while ( ! strEsp8266_Fram_Record .InfBit .FramFinishFlag );
strEsp8266_Fram_Record .Data_RX_BUF [ strEsp8266_Fram_Record .InfBit .FramLength ] = '\0';//增加一個結(jié)束符。
if ( enumEnUnvarnishTx )
pRecStr = strEsp8266_Fram_Record .Data_RX_BUF;
else
{
if ( strstr ( strEsp8266_Fram_Record .Data_RX_BUF, "+IPD" ) )
pRecStr = strEsp8266_Fram_Record .Data_RX_BUF;
}
return pRecStr;
}
/*
* 函數(shù)名:ESP8266_CWLIF
* 描述 :查詢已接入設(shè)備的IP
* 輸入 :pStaIp,存放已接入設(shè)備的IP
* 返回 : 1,有接入設(shè)備
* 0,無接入設(shè)備
* 調(diào)用 :被外部調(diào)用
*/
uint8_t ESP8266_CWLIF ( char *pStaIp )
{
uint8_t uc, ucLen;
char *pCh, * pCh1;
ESP8266_Cmd ( "AT+CWLIF", "OK", 0, 100 );
pCh = strstr ( strEsp8266_Fram_Record .Data_RX_BUF, "," );
if ( pCh )
{
pCh1 = strstr ( strEsp8266_Fram_Record .Data_RX_BUF, "AT+CWLIF\r\r\n" ) + 11;
ucLen = pCh - pCh1;
}
else
return 0;
for ( uc = 0; uc < ucLen; uc ++ )
pStaIp [ uc ] = * ( pCh1 + uc);
pStaIp [ ucLen ] = '\0';
return 1;
}
/*
* 函數(shù)名:ESP8266_CIPAP
* 描述 :設(shè)置模塊的 AP IP
* 輸入 :pApIp,模塊的 AP IP
* 返回 : 1,設(shè)置成功
* 0,設(shè)置失敗
* 調(diào)用 :被外部調(diào)用
*/
uint8_t ESP8266_CIPAP ( char *pApIp )
{
char cCmd [ 30 ];
sprintf ( cCmd, "AT+CIPAP=\"%s\"", pApIp );
if ( ESP8266_Cmd ( cCmd, "OK", 0, 5000 ) )
return 1;
else
return 0;
}
/*
* 函數(shù)名:ESP8266_CIPAP
* 描述 :設(shè)置模塊的 AP IP
* 輸入 :pApIp,模塊的 AP IP
* 返回 : 1,設(shè)置成功
* 0,設(shè)置失敗
* 調(diào)用 :被外部調(diào)用
*/
uint8_t ESP8266_CIPSTA ( char *pStaIp )
{
char cCmd [ 30 ];
sprintf ( cCmd, "AT+CIPSTA=\"%s\"", pStaIp );
if ( ESP8266_Cmd ( cCmd, "OK", 0, 5000 ) )
return 1;
else
return 0;
}
esp8266.h
#ifndef __ESP8266_H_
#define __ESP8266_H_
#include "stm32f10x.h"
#include "sys.h"
#include "usart.h"
#include <stdio.h>
#include <stdbool.h>
/******************************* ESP8266 數(shù)據(jù)類型定義 ***************************/
//工作模式
typedef enum
{
STA,
AP,
STA_AP
} ENUM_Net_ModeTypeDef;
//網(wǎng)絡(luò)協(xié)議
typedef enum
{
enumTCP,
enumUDP,
} ENUM_NetPro_TypeDef;
//模塊連接服務(wù)器的ID
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;
//
typedef enum
{
OPEN = 0,
WEP = 1,
WPA_PSK = 2,
WPA2_PSK = 3,
WPA_WPA2_PSK = 4,
} ENUM_AP_PsdMode_TypeDef;
/******************************** ESP8266 連接引腳定義 ***********************************/
#define ESP8266_CH_PD_APBxClock_FUN RCC_APB2PeriphClockCmd
#define ESP8266_CH_PD_CLK RCC_APB2Periph_GPIOB
#define ESP8266_CH_PD_PORT GPIOB
#define ESP8266_CH_PD_PIN GPIO_Pin_8
#define ESP8266_RST_APBxClock_FUN RCC_APB2PeriphClockCmd
#define ESP8266_RST_CLK RCC_APB2Periph_GPIOB
#define ESP8266_RST_PORT GPIOB
#define ESP8266_RST_PIN GPIO_Pin_9
#define ESP8266_USARTx USART2
#define DEBUG_USARTx USART1
/******************************* ESP8266 外部全局變量聲明 *******************123********/
/*********************************************** ESP8266 函數(shù)宏定義 *******************************************/
#define ESP8266_Usart( fmt, ... ) USART_printf ( ESP8266_USARTx, fmt, ##__VA_ARGS__ )
#define PC_Usart( fmt, ... ) printf ( fmt, ##__VA_ARGS__ )
//#define macPC_Usart( fmt, ... )
#define ESP8266_CH_ENABLE() GPIO_SetBits ( ESP8266_CH_PD_PORT, ESP8266_CH_PD_PIN )
#define ESP8266_CH_DISABLE() GPIO_ResetBits ( ESP8266_CH_PD_PORT, ESP8266_CH_PD_PIN )
#define ESP8266_RST_HIGH_LEVEL() GPIO_SetBits ( ESP8266_RST_PORT, ESP8266_RST_PIN )
#define ESP8266_RST_LOW_LEVEL() GPIO_ResetBits ( ESP8266_RST_PORT, ESP8266_RST_PIN )
/******************************** ESP8266 函數(shù)聲明 *********************************/
void ESP8266_Init ( void );
void ESP8266_Rst ( void );
bool ESP8266_Cmd ( char *cmd, char *reply1, char *reply2, u32 waittime );
bool ESP8266_AT_Test ( void );
bool ESP8266_Net_Mode_Choose ( ENUM_Net_ModeTypeDef enumMode );
bool ESP8266_JoinAP ( char *pSSID, char *pPassWord );
bool ESP8266_BuildAP ( char *pSSID, char *pPassWord, ENUM_AP_PsdMode_TypeDef enunPsdMode );
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_StartOrShutServer ( FunctionalState enumMode, char *pPortNum, char *pTimeOver );
uint8_t ESP8266_Get_LinkStatus ( void );
uint8_t ESP8266_Get_IdLinkStatus ( void );
uint8_t ESP8266_Inquire_ApIp ( char *pApIp, uint8_t ucArrayLength );
bool ESP8266_UnvarnishSend ( void );
void ESP8266_ExitUnvarnishSend ( void );
bool ESP8266_SendString ( FunctionalState enumEnUnvarnishTx, char *pStr, u32 ulStrLength, ENUM_ID_NO_TypeDef ucId );
char *ESP8266_ReceiveString ( FunctionalState enumEnUnvarnishTx );
bool ESP8266_DHCP_CUR ( void );
uint8_t ESP8266_CWLIF ( char * pStaIp );
uint8_t ESP8266_CIPAP ( char * pApIp );
uint8_t ESP8266_CIPSTA ( char * pStaIp ); // new
//void ESP8266_AT_Test ( void );
#endif
esp8266_test.c
#include "esp8266_test.h"
#include "esp8266.h"
#include <stdio.h>
#include "led.h"
#include <string.h>
#include <stdbool.h>
//volatile uint8_t ucTcpClosedFlag = 0;
bool ESP8266_AT_Test ( void );
/**
* @brief ESP8266 StaTcpClient Unvarnish 配置測試函數(shù)
* @param 無
* @retval 無
*/
void ESP8266_StaTcpClient_Unvarnish_ConfigTest(void)
{
printf( "\r\n正在配置 ESP8266 ......\r\n" );
printf( "\r\n使能 ESP8266 ......\r\n" );
ESP8266_CH_ENABLE();
while( ! ESP8266_AT_Test() );
while( ! ESP8266_DHCP_CUR () );
printf( "\r\n正在配置工作模式 STA ......\r\n" );
while( ! ESP8266_Net_Mode_Choose ( STA ) );
printf( "\r\n正在連接 WiFi ......\r\n" );
while( ! ESP8266_JoinAP ( User_ESP8266_ApSsid, User_ESP8266_ApPwd ) );
printf( "\r\n禁止多連接 ......\r\n" );
while( ! ESP8266_Enable_MultipleId ( DISABLE ) );
printf( "\r\n正在連接 Server ......\r\n" );
while( ! ESP8266_Link_Server ( enumTCP, User_ESP8266_TcpServer_IP, User_ESP8266_TcpServer_Port, Single_ID_0 ) );
printf( "\r\n進入透傳發(fā)送模式 ......\r\n" );
while( ! ESP8266_UnvarnishSend () );
printf( "\r\n配置 ESP8266 完畢\r\n" );
printf ( "\r\n開始透傳......\r\n" );
}
/**
* @brief ESP8266 檢查是否接收到了數(shù)據(jù),檢查連接和掉線重連
* @param 無
* @retval 無
*/
void ESP8266_CheckRecvDataTest(void)
{
uint8_t ucStatus;
uint16_t i;
/* 如果接收到了串口調(diào)試助手的數(shù)據(jù) */
if(strUSART_Fram_Record.InfBit.FramFinishFlag == 1)
{
for(i = 0; i < strUSART_Fram_Record.InfBit.FramLength; i++)
{
USART_SendData( ESP8266_USARTx,strUSART_Fram_Record.Data_RX_BUF[i]); //轉(zhuǎn)發(fā)給ESP82636
while(USART_GetFlagStatus(ESP8266_USARTx,USART_FLAG_TC)==RESET) {} //等待發(fā)送完成
}
strUSART_Fram_Record .InfBit .FramLength = 0; //接收數(shù)據(jù)長度置零
strUSART_Fram_Record .InfBit .FramFinishFlag = 0; //接收標(biāo)志置零
}
/* 如果接收到了ESP8266的數(shù)據(jù) */
if(strEsp8266_Fram_Record.InfBit.FramFinishFlag)
{
for(i = 0; i < strEsp8266_Fram_Record .InfBit .FramLength; i++)
{
USART_SendData( DEBUG_USARTx,strEsp8266_Fram_Record .Data_RX_BUF[i]); //轉(zhuǎn)發(fā)給ESP82636
while(USART_GetFlagStatus(DEBUG_USARTx,USART_FLAG_TC)==RESET) {}
}
strEsp8266_Fram_Record .InfBit .FramLength = 0; //接收數(shù)據(jù)長度置零
strEsp8266_Fram_Record.InfBit.FramFinishFlag = 0; //接收標(biāo)志置零
}
if ( ucTcpClosedFlag ) //檢測是否失去連接
{
ESP8266_ExitUnvarnishSend (); //退出透傳模式
do ucStatus = ESP8266_Get_LinkStatus (); //獲取連接狀態(tài)
while ( ! ucStatus );
if ( ucStatus == 4 ) //確認(rèn)失去連接后重連
{
printf ( "\r\n正在重連熱點和服務(wù)器 ......\r\n" );
while ( ! ESP8266_JoinAP ( User_ESP8266_ApSsid, User_ESP8266_ApPwd ) );
while ( ! ESP8266_Link_Server ( enumTCP, User_ESP8266_TcpServer_IP, User_ESP8266_TcpServer_Port, Single_ID_0 ) );
printf ( "\r\n重連熱點和服務(wù)器成功\r\n" );
}
while ( ! ESP8266_UnvarnishSend () );
}
}
esp8266_test.h
#ifndef __ESP8266_TEST_H
#define __ESP8266_TEST_H
#include "stm32f10x.h"
/********************************** 用戶需要設(shè)置的參數(shù)**********************************/
#define User_ESP8266_ApSsid "ChinaNet-057B" //要連接的熱點的名稱
#define User_ESP8266_ApPwd "abc1314520" //要連接的熱點的密鑰
#define User_ESP8266_TcpServer_IP "192.168.2.6" //要連接的服務(wù)器的 IP
#define User_ESP8266_TcpServer_Port "808" //要連接的服務(wù)器的端口
/********************************** 外部全局變量 ***************************************/
extern volatile uint8_t ucTcpClosedFlag;
extern int read_dht11_finish;
/********************************** 測試函數(shù)聲明 ***************************************/
void ESP8266_StaTcpClient_Unvarnish_ConfigTest(void);
void ESP8266_CheckRecvDataTest(void);
#endif
main.c
#include "delay.h"
#include "sys.h"
#include "usart.h"
#include "led.h"
#include "esp8266.h"
#include "esp8266_test.h"
#include "stm32f10x.h"
#include "stdio.h"
int main()
{
uart1_init(115200); //串口初始化為115200
uart2_init(115200); //串口初始化為115200
/* 初始化 */
LED_GPIO_Config();
ESP8266_Init ();
ESP8266_StaTcpClient_Unvarnish_ConfigTest(); //對ESP8266進行配置
while(1)
{
ESP8266_CheckRecvDataTest();
}
}
3. ESP8266使用Ap模式控制mcu
stm32f103c8t6自帶一個led燈,使用PC13引腳就行了,
切記盡量避免使用PB3、PB4,具體看stm32f103c8t6使用PB3和PB4做普通GPIO使用時發(fā)現(xiàn)異常
led.c
#include "led.h" //綁定led.h
void LED_GPIO_Config(void) {
GPIO_InitTypeDef GPIO_InitStruct; //初始化參數(shù)結(jié)構(gòu)體指針,結(jié)構(gòu)體類型為 GPIO_InitTypeDef。
//開啟RCC時鐘
RCC_APB2PeriphClockCmd(LED_G_GPIO_CLK, ENABLE);
//配置初始化,推挽輸出方式和LED_G_GPIO_PIN管腳、赫茲
GPIO_InitStruct.GPIO_Pin = LED_G_GPIO_PIN;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
//GPIO口初始化
GPIO_Init(LED_G_GPIO_PORT, &GPIO_InitStruct);
}
led.h
#ifndef __LED_H_
#define __LED_H_
#include "stm32f10x.h"
#include "sys.h"
#define LED_G_GPIO_PIN GPIO_Pin_13
#define LED_G_GPIO_PORT GPIOC
#define LED_G_GPIO_CLK RCC_APB2Periph_GPIOC
//使用位帶操作來實現(xiàn)操作某個IO口的 1個位,由sys.h實現(xiàn)
#define LED PCout(13)
void LED_GPIO_Config(void); //函數(shù)定義
#endif
usart.c
usart.c 、usart.h 、esp8266.c、esp8266.h等文件和實現(xiàn)穿透的代碼一樣,
esp8266_test.c
#include "esp8266_test.h"
#include "esp8266.h"
#include <stdio.h>
#include "led.h"
#include "delay.h"
#include <string.h>
#include <stdbool.h>
uint8_t ucId, ucLen;
uint8_t ucLed1Status = 0;
char cStr [ 100 ] = { 0 }, cCh;
char *pCh, * pCh1;
//volatile uint8_t ucTcpClosedFlag = 0;
bool ESP8266_AT_Test ( void );
/**
* @brief ESP8266 ApTcpServer 配置測試函數(shù)
* @param 無
* @retval 無
*/
void ESP8266_ApTcpServer_ConfigTest(void)
{
printf( "\r\n正在配置 ESP8266 ......\r\n" );
printf( "\r\n使能 ESP8266 ......\r\n" );
ESP8266_CH_ENABLE();
while( ! ESP8266_AT_Test() );
printf( "\r\n正在配置工作模式為 AP ......\r\n" );
while( ! ESP8266_Net_Mode_Choose ( AP ) );
printf( "\r\n正在創(chuàng)建WiFi熱點 ......\r\n" );
while ( ! ESP8266_CIPAP ( User_ESP8266_TcpServer_IP ) ); //設(shè)置模塊的 AP IP
while ( ! ESP8266_BuildAP ( User_ESP8266_BulitApSsid, User_ESP8266_BulitApPwd, User_ESP8266_BulitApEcn ) );
printf( "\r\n允許多連接 ......\r\n" );
while( ! ESP8266_Enable_MultipleId ( ENABLE ) );
printf( "\r\n開啟服務(wù)器模式 ......\r\n" );
while ( ! ESP8266_StartOrShutServer ( ENABLE, User_ESP8266_TcpServer_Port, User_ESP8266_TcpServer_OverTime ) );
ESP8266_Inquire_ApIp ( cStr, 20 );
printf ( "\n本模塊WIFI為 %s,密碼開放\nAP IP 為:%s,開啟的端口為:%s\r\n手機網(wǎng)絡(luò)助手連接該 IP 和端口,最多可連接5個客戶端\n",
User_ESP8266_BulitApSsid, cStr, User_ESP8266_TcpServer_Port );
strEsp8266_Fram_Record .InfBit .FramLength = 0;
strEsp8266_Fram_Record .InfBit .FramFinishFlag = 0;
printf( "\r\n配置 ESP8266 完畢\r\n" );
}
/**
* @brief ESP8266 檢查接收信息并發(fā)送數(shù)據(jù)測試函數(shù)
* @param 無
* @retval 無
*/
void ESP8266_CheckRecvDataTest(void)
{
if ( strEsp8266_Fram_Record .InfBit .FramFinishFlag ) //如果有數(shù)據(jù)傳輸結(jié)束
{
USART_ITConfig ( ESP8266_USARTx, USART_IT_RXNE, DISABLE ); //禁用串口接收中斷,防止影響
strEsp8266_Fram_Record .Data_RX_BUF [ strEsp8266_Fram_Record .InfBit .FramLength ] = '\0';
printf("ucCh =%s\n", strEsp8266_Fram_Record .Data_RX_BUF);
if(strstr ( strEsp8266_Fram_Record .Data_RX_BUF, "LED=1" )) //如果手機發(fā)送的數(shù)據(jù)存在LED=1,則if成立
{
PCout(13) = 1; //PC口13引腳輸出,高電平
printf("\r\nLED滅\r\n");
Delay_ms(500); //已經(jīng)在delay.h中初始化
}
else if(strstr ( strEsp8266_Fram_Record .Data_RX_BUF, "LED=0" ))
{
PCout(13) = 0; //PC口13引腳輸出,低電平
printf("\r\nLED亮\r\n");
Delay_ms(500);
}
if ( ( pCh = strstr ( strEsp8266_Fram_Record .Data_RX_BUF, "+IPD," ) ) != 0 )
{
ucId = * ( pCh + strlen ( "+IPD," ) ) - '0';
ESP8266_SendString ( DISABLE, cStr, strlen ( cStr ), ( ENUM_ID_NO_TypeDef ) ucId );
}
strEsp8266_Fram_Record .InfBit .FramLength = 0;
strEsp8266_Fram_Record .InfBit .FramFinishFlag = 0;
USART_ITConfig ( ESP8266_USARTx, USART_IT_RXNE, ENABLE ); //使能串口接收中斷
}
}
esp8266_test.h
#ifndef __ESP8266_TEST_H
#define __ESP8266_TEST_H
#include "stm32f10x.h"
/********************************** 用戶需要設(shè)置的參數(shù)**********************************/
#define User_ESP8266_ApSsid "ChinaNet-057B" //要連接的熱點的名稱
#define User_ESP8266_ApPwd "abc1314520" //要連接的熱點的密鑰
#define User_ESP8266_TcpServer_IP "192.168.4.1" //要連接的服務(wù)器的 IP
#define User_ESP8266_TcpServer_Port "8888" //要連接的服務(wù)器的端口
#define User_ESP8266_BulitApSsid "ESP8266" //要建立的熱點的名稱
#define User_ESP8266_BulitApEcn OPEN //要建立的熱點的加密方式
#define User_ESP8266_BulitApPwd "12345678" //要建立的熱點的密鑰
#define User_ESP8266_TcpServer_OverTime "1800" //服務(wù)器超時時間(單位:秒)
/********************************** 外部全局變量 ***************************************/
extern volatile uint8_t ucTcpClosedFlag;
extern int read_dht11_finish;
/********************************** 測試函數(shù)聲明 ***************************************/
void ESP8266_ApTcpServer_ConfigTest(void);
void ESP8266_CheckRecvDataTest(void);
#endif
main.c
#include "delay.h"
#include "sys.h"
#include "usart.h"
#include "led.h"
#include "esp8266.h"
#include "esp8266_test.h"
#include "stm32f10x.h"
#include "stdio.h"
int main()
{
uart1_init(115200); //串口初始化為115200
uart2_init(115200); //串口初始化為115200
/* 初始化 */
LED_GPIO_Config();
ESP8266_Init ();
ESP8266_ApTcpServer_ConfigTest(); //對ESP8266進行配置
while(1)
{
ESP8266_CheckRecvDataTest();
}
}
3. 編譯
編譯成功
4. 選擇燒錄工具并配置MDK
本文選擇的是ST_Link燒錄工具
如果沒有ID號看博客:ST-Link V2燒錄問題(已解決)
5. 成品
1. 使用MCU完成透傳功能
2. ESP8266使用Ap模式控制mcu
這個工具開頭已經(jīng)提供
這里PC13已經(jīng)亮滅了就沒有上傳截圖,大家自己可以試試文章來源:http://www.zghlxwxcb.cn/news/detail-418637.html
工程鏈接
使用MCU完成透傳功能:
鏈接:https://pan.baidu.com/s/1RugvDofb_JQDTqpoYFQ-8w 提取碼:0000
ESP8266使用Ap模式控制mcu:
鏈接:https://pan.baidu.com/s/1Fol88R_HwS9LNbLXYpN5Iw 提取碼:0000文章來源地址http://www.zghlxwxcb.cn/news/detail-418637.html
到了這里,關(guān)于十、stm32-ESP8266(串口透傳、MCU透傳、控制LED亮滅)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!