零知开源模块篇2-ESP8266 wifi模块 ESP-12 ESP-07 ESP-01

一、材料

MCU:零知开源开发板
wifi模块:ESP-12F
开发工具:零知实验室

功能:通过串口连接零知实验室开发板与esp-12f wifi模块,实现联网:本示例使用AP指令开发方式,开启一个热点并设置为TCP服务器模式,程序运行后就可以被其他wifi功能的终端连接上进行网络通信

二、方法步骤


1、ESP8266 烧过其他程序的重新 烧录AT固件方法


2、硬件连接

我们把esp8266连接到零知开发板的Serial1的引脚上(注意RX和TX交叉连接)

零知-标准板   <------------->   ESP8266
0                    <------------->   TX
1                    <------------->   RX  
5v                  <------------->   5v
GND              <------------->   GND
RST               <------------->   RST  

打开零知开发工具,在【示例】中选择如下选项:

3、程序编写


												
/**************************************************************************************
 * 文件: \esp8266-wifi-test(AP模式下建立TCP服务器)\AP_TCP_Server.ino
 * 作者:零知实验室
 * -^^- 零知开源,让电子制作变得更简单! -^^-
 * 时间: 2019-11-20 19:01:29
 * 说明: 使用ESP8266建立TCP服务器示例
****************************************************************************************/
#include "esp8266.h"

#include <HardwareSerial.h>

#define ssid "ESP8266-TCP服务器"                 //在这里设置你的热点名称
#define password "12345678"                     //在这里设置你的热点密码
#define serverPort 8081                         // 开启的端口号

Esp8266 wifi;                                   //创建实例

#define serialDebug Serial
#define serialEsp Serial1

void setup()
{

	delay(8000);                        //等待一段时间,以便查看串口的调试信息

	serialDebug.begin(115200);          //设置调试串口波特率,启动调试串口
	serialEsp.begin(115200);            //设置ESP串口波特率,启动ESP传输串口

	wifi.begin(&serialEsp, &serialDebug);  ///Serial串行用于与esp8266模块通信,serialDebug用于打印调试消息

	if (wifi.enableAP(ssid, password))
	{
		wifi.debugPrintln("AP成功开启!");
	}
	if (wifi.setMultiConnect())
	{
		wifi.debugPrintln("开启多连接模式成功!");
	}
	if (wifi.openTCPServer(serverPort, 180))
	{
		wifi.debugPrintln("开启TCP服务器成功!");
	}
	wifi.debugPrintln("服务器IP:" + wifi.getIP() + " 端口:" + String(serverPort));
}

void loop()
{

	int state = wifi.getState();            //根据WiFi状态进入以下操作
	switch (state)
	{
	case WIFI_NEW_MESSAGE:																											//从客户端接收到了新的信息,打印
		wifi.debugPrintln(String(wifi.getWorkingID()) + ":" + wifi.getMessage()); // 调试
		wifi.sendMessage(wifi.getWorkingID(), wifi.getMessage());	// 把接收到的信息发送回给客户端
		wifi.setState(WIFI_IDLE);
		break;
	case WIFI_CLOSED:                                 //如果连接口已关闭
		wifi.debugPrintln(String(wifi.getFailConnectID()) + ":连接关闭!");
		wifi.setState(WIFI_IDLE);
		break;
	case WIFI_IDLE:
	{
		int state = wifi.checkMessage();
		wifi.setState(state);
		break;
	}
	case WIFI_CLIENT_ON:                                //客户端连接成功,WiFi发出问候字符串信息
		wifi.sendMessage(wifi.getWorkingID(), "from ESP8266: Hello, www.lingzhilab.com");
		wifi.setState(WIFI_IDLE);
		break;
	}
}
		

								
	#include "esp8266.h"
	
	Esp8266::Esp8266() {
	        this->workingState = WIFI_IDLE;
	        this->wifiMode = WIFI_MODE_STATION;
	        this->isDebug = false;
	}
	
	void Esp8266::begin(Stream *serial){
	        this->serial=serial;
	}
	
	void Esp8266::begin(Stream *serial, Stream *serialDebug){
	        this->serial = serial;
	        this->serialDebug = serialDebug;
	        this->isDebug = true;
	}
	
	bool Esp8266::connectAP(String ssid, String password) {
	
	        unsigned long timeout = 20000;
	        unsigned long t_start = 0;
	        int buf[10];
	        char index=0;
	
	        if (checkMode()!=WIFI_MODE_AP){
	                this->wifiMode = WIFI_MODE_STATION;
	        }
	        else {
	                if (setMode(WIFI_MODE_STATION))
	                        this->wifiMode = WIFI_MODE_STATION;
	                else {
	                        if (this->isDebug) {
	                                debugPrintln("set mode to station false!");
	                        }
	                        return false;
	                }
	        }
	
	        clearBuf();
	        this->serial->println("AT+CWJAP=""+ssid+"",""+password+""");
	        t_start = millis();
	        while ((millis()-t_start) < timeout) {
	                while (available()>0) {
	                        buf[index] = read();
	                        if (buf[index]=='K' && buf[(index+9)%10]=='O') {
	                                return true;
	                        }
	                        if (buf[index]=='L' && buf[(index+9)%10]=='I' && buf[(index+8)%10]=='A' && buf[(index+7)%10]=='F') {
	                                return false;
	                        }
	                        index++;
	                        if (index==10)
	                                index = 0;
	                }
	        }
	        if (this->isDebug) {
	                debugPrintln("connect AP timeout");
	        }
	        return false;
	}
	
	int Esp8266::available() {
	        return this->serial->available();
	}
	
	void Esp8266::write(String str) {
	         this->serial->println(str);
	         flush();  /*wait the data send ok, clear send_buf*/
	}
	
	bool Esp8266::checkEsp8266() {
	        bool isOK=false;
	        clearBuf();
	        write("AT");
	        delay(200);
	        isOK = this->serial->findUntil("AT", "\r\n");
	        if (true == isOK) {
	                return true;
	        } else {
	                return false;
	        }
	}
	
	/*clear rx_buf*/
	void Esp8266::clearBuf() {
	        while(available() > 0)
	                read();
	}
	
	int Esp8266::read() {
	        return this->serial->read();
	}
	
	String Esp8266::readData() {
	        unsigned long timeout = 100;
	        unsigned long t = millis();
	    String data = "";
	    while(millis() - t < timeout) {
	            if(available() > 0) {
	                char r = serial->read();
	                data += r;  
	            t = millis();
	            }
	    }
	    return data;
	}
	
	bool Esp8266::setMode(char mode) {
	        clearBuf();
	        write("AT+CWMODE="+String(mode));
	        delay(200);
	        String str = readData();
	        if (str.indexOf("no change") > 0)
	                return true;
	        else {
	                 if (resetEsp8266()) {
	                        this->wifiMode = mode;
	                        return true;
	                }
	                else {
	                        return false;
	                }
	        }
	
	}
	
	/*clear send_buf*/
	void Esp8266::flush() {
	        this->serial->flush();
	}
	
	char Esp8266::checkMode() {
	        clearBuf();
	        write("AT+CWMODE?");
	        delay(200);
	        String str = readData();
	        // Serial.println(str);
	        if (str.indexOf('1') > 0 )  
	                return '1';
	        else if (str.indexOf('2') > 0)
	                return '2';
	        else if (str.indexOf('3') > 0)
	                return '3';
	        else
	                return '0';
	}
	
	bool Esp8266::resetEsp8266() {
	
	        unsigned long timeout = 7000;
	        unsigned long t_start = 0;
	        int buf[10];
	        char index=0;
	
	        clearBuf();
	        write("AT+RST");
	        t_start = millis();
	        while ((millis()-t_start) < timeout) {
	                while (available()>0) {
	                        buf[index] = read();
	                        if (buf[index]=='y' && buf[(index+9)%10]=='d' && buf[(index+8)%10]=='a' && buf[(index+7)%10]=='e' && buf[(index+6)%10]=='r') {
	                                return true;
	                        }
	                        index++;
	                        if (index==10)
	                                index = 0;
	                }
	        }
	           if (this->isDebug) {
	                debugPrintln("rest esp8266 timeout");
	        }
	        return false;        
	}
	
	
	void Esp8266::debugPrintln(String str) {
	        this->serialDebug->println(str);
	}
	
	
	bool Esp8266::setMux(int flag) {
	        String str;
	        clearBuf();
	        write("AT+CIPMUX="+String(flag));
	        delay(100);
	        str = readData();
	        if (str.indexOf("OK")>0 || str.indexOf("link is builded")>0)
	                return true;
	        else
	                return false;
	}
	
	bool Esp8266::setSingleConnect() {
	        this->connectID = 0;
	        this->multiFlag = false;
	        return setMux(0);
	}
	
	bool Esp8266::setMultiConnect() {
	        this->connectID = 0;
	        this->multiFlag = true;
	        return setMux(1);
	}
	
	
	
	bool Esp8266::connectTCPServer(String serverIP, String serverPort) {
	        unsigned long timeout = 5000;
	        unsigned long t_start = 0;
	        unsigned char buf[10];
	        unsigned char index=0;
	
	        clearBuf();
	        if (!this->multiFlag) {
	                write("AT+CIPSTART="TCP","" + serverIP + ""," + serverPort);        
	                t_start = millis();
	                while((millis())-t_start < timeout)        {
	                        while(available()) {
	                                buf[index] = read();
	                                if (buf[index]=='T' && buf[(index+9)%10]=='C' && buf[(index+8)%10]=='E' && buf[(index+7)%10]=='N'
	                                                                        && buf[(index+6)%10]=='N' && buf[(index+5)%10]=='O' && buf[(index+4)%10]=='C') {
	                                        return true;
	                                }
	                                index++;
	                                if (index==10)
	                                        index = 0;                        
	                        }
	                }
	                if (this->isDebug) {        
	                        debugPrintln("connectTCPServer timeout");
	                }
	                return false;
	        } else {
	                write("AT+CIPSTART="+ String(this->connectID) + ","TCP","" + serverIP + ""," + serverPort);
	                t_start = millis();
	                while((millis())-t_start < timeout)        {
	                        while(available()) {
	                                buf[index] = read();
	                                if (buf[index]=='T' && buf[(index+9)%10]=='C' && buf[(index+8)%10]=='E' && buf[(index+7)%10]=='N'
	                                                                        && buf[(index+6)%10]=='N' && buf[(index+5)%10]=='O' && buf[(index+4)%10]=='C') {
	                                        this->connectID++;
	                                        return true;
	                                }
	                                index++;
	                                if (index==10)
	                                        index = 0;                        
	                        }
	                }
	                if (this->isDebug) {
	                        debugPrintln("connectTCPServer timeout");
	                }
	                return false;               
	        }
	}
	
	
	int Esp8266::getState() {
	        return this->workingState;
	}
	
	void Esp8266::setState(int state) {
	        this->workingState = state;
	}
	int Esp8266::checkMessage() {
	        String tmp="";
	        tmp = readData();
	        if (tmp!="") {
	                if (tmp.substring(2, 6) == "+IPD") {
	                        if (!(this->multiFlag)) {
	                                int index = tmp.indexOf(":");
	                                int length = tmp.substring(7, index+1).toInt();
	                                this->message = tmp.substring(index+1, index+length+1);
	                                return WIFI_NEW_MESSAGE;
	                        } else {
	                                int id = 0, length=0, index=0;
	                                id = tmp.substring(7, 8).toInt();
	                                index = tmp.indexOf(":");
	                                length = tmp.substring(9, index+1).toInt();
	                                this->workingID = id;
	                                this->message = tmp.substring(index+1, index+length+1);
	                                return WIFI_NEW_MESSAGE;
	                        }
	                } else if (tmp.substring(0,6) == "CLOSED" || (tmp.charAt(1)==',' && tmp.substring(2,8)=="CLOSED")) {
	                        if (!(this->multiFlag)) {
	                                return WIFI_CLOSED;
	                        } else {
	                                this->failConnectID = tmp.charAt(0)-'0';
	                                return WIFI_CLOSED;
	                        }
	                } else if (tmp.substring(1,9) == ",CONNECT") {
	                        int index = tmp.charAt(0)-'0';
	                        this->workingID = index;
	                        return WIFI_CLIENT_ON;
	                } else if (this->isPureDataMode) {
	                        this->message = tmp;
	                        return WIFI_NEW_MESSAGE;
	                } else {
	                        return WIFI_IDLE;
	                }
	        } else {
	                return this->workingState;
	        }
	}
	
	String Esp8266::getMessage() {
	        return this->message;
	}
	
	bool Esp8266::sendMessage(String str) {
	        if (this->isPureDataMode) {
	                this->serial->print(str);
	        } else {
	                String tmp = "";
	                int index = 0;
	                int len = 0;
	                len = str.length();
	                write("AT+CIPSEND="+String(len));
	                delay(20);
	                this->serial->print(str);
	
	                tmp = readData();
	                index = tmp.length();
	                if (tmp.substring(index-9, index-2) == "SEND OK") {
	                        return true;
	                } else {
	                        return false;
	                }
	        }
	}
	
	bool Esp8266::sendMessage(int index, String str) {
	        
	        String tmp = "";
	        int i = 0;
	        int len = 0;
	
	        len = str.length();
	        write("AT+CIPSEND="+String(index)+","+String(len));
	        delay(20);
	        this->serial->print(str);
	
	        tmp = readData();
	        i = tmp.length();
	        if (tmp.substring(i-9, i-2) == "SEND OK") {
	                return true;
	        } else {
	                return false;
	        }
	}
	
	int Esp8266::getWorkingID() {
	        return this->workingID;
	}
	
	int Esp8266::getFailConnectID() {
	        return this->failConnectID;
	}
	
	bool Esp8266::openTCPServer(int port, int timeout) {
	        if (setMux(1)) {
	                String str="";
	                write("AT+CIPSERVER=1,"+String(port));
	                str = readData();
	                if (str.indexOf("OK")) {
	                        write("AT+CIPSTO="+String(timeout));
	                        str = readData();
	                        if (str.indexOf("OK")) {
	                                return true;
	                        } else {
	                                return false;
	                        }
	                } else {
	                        return false;
	                }
	        } else {
	                return false;
	        }        
	}
	
	bool Esp8266::enableAP(String ssid, String password) {
	        if (setMode(WIFI_MODE_AP)) {
	                write("AT+CWSAP=""+ssid+"",""+password+"","+String(10)+String(',')+String(4));
	                String tmp;
	                delay(200);
	                tmp = readData();
	                if (tmp.indexOf("OK")>0) {
	                        return true;
	                } else {
	                        return false;
	                }
	        }
	}
	
	String Esp8266::getIP() {
	        write("AT+CIFSR");
	        String tmp = readData();
	        if (this->wifiMode == WIFI_MODE_STATION) {
	                int index1 = tmp.indexOf("STAIP");
	                int index2 = tmp.indexOf("+CIFSR:STAMAC");
	                this->staIP =  tmp.substring(index1+7, index2-3);
	                return this->staIP;
	        } else {
	                int index1 = tmp.indexOf("APIP");
	                int index2 = tmp.indexOf("+CIFSR:APMAC");               
	                this->apIP =  tmp.substring(index1+6, index2-3);        
	                return this->apIP;
	        }        
	}
	
	bool Esp8266::setPureDataMode() {
	        write("AT+CIPMODE=1");
	        String tmp = readData();
	        if (tmp.indexOf("OK")>0) {
	                write("AT+CIPSEND");
	                this->isPureDataMode = true;
	                return true;
	        } else
	                return false;
	}
	

								
#ifndef _ESP8266_H_
#define _ESP8266_H_

#include <Arduino.h>
#include <Stream.h>
#include <avr/pgmspace.h>
#include <IPAddress.h>

#define        WIFI_IDLE                        1
#define WIFI_NEW_MESSAGE        2
#define WIFI_CLOSED                        3
#define WIFI_CLIENT_ON                4

#define WIFI_MODE_STATION                        '1'
#define WIFI_MODE_AP                                '2'
#define WIFI_MODE_BOTH                                '3'

class Esp8266
{
public:
        Esp8266();
        void begin(Stream *serial);
        void begin(Stream *serial,Stream *serialDebug);
        void comSend();
        bool connectAP(String ssid, String password);
        bool checkEsp8266();
        bool resetEsp8266();
        void debugPrintln(String str);
        bool setSingleConnect();
        bool setMultiConnect();
        bool connectTCPServer(String serverIP, String serverPort);        
        int         checkMessage();
        String getMessage();
        void setState(int state);
        int getState();        
        bool sendMessage(String str);
        bool sendMessage(int index, String str);
        int getWorkingID();
        int getFailConnectID();
        bool openTCPServer(int port, int timeout);
        bool enableAP(String ssid, String password);
        String getIP();
        bool setPureDataMode();

private:
        int available();
        void write(String str);
        void clearBuf();
        int read();
        String readData();
        void flush();        
        bool setMode(char mode);
        char checkMode();        
        bool setMux(int flag);


private:
        Stream *serial;                                            
        Stream *serialDebug;
        int connectID;
        int workingID;
        int failConnectID;
        bool multiFlag;
        int workingState;
<font style="vertical-align: inherit;"><font style="vertical-align: inherit;">        字符串消息; </font></font>
<font style="vertical-align: inherit;"><font style="vertical-align: inherit;">        char wifiMode; </font></font>
<font style="vertical-align: inherit;"><font style="vertical-align: inherit;">        String staIP; </font></font>
<font style="vertical-align: inherit;"><font style="vertical-align: inherit;">        String apIP; </font></font>
<font style="vertical-align: inherit;"><font style="vertical-align: inherit;">        bool isDebug; </font></font>
<font style="vertical-align: inherit;"><font style="vertical-align: inherit;">        bool是PureDataMode; </font></font>
<font style="vertical-align: inherit;"><font style="vertical-align: inherit;">}; </font></font>

<font style="vertical-align: inherit;"><font style="vertical-align: inherit;">#万一</font></font>		

4、测试结果

程序烧写到开发板后,打开零知Lab开发工具的串口监视器,选择波特率为115200,就可以看到如下所示:

可以看到网络功能开启成功的信息,以及服务器开放的ip和端口号。

在手机上打开网络设置界面,可以看到esp8266的热点信息,如下

再打开手机上的网络调试助手工具,再到TCP客户端项目中选择增加,填写正确的ip和端口,如下

然后连接成功后会显示如下:

可以看到从esp8266 wifi模块发送过来的信息,在发送框中发送信息,就可以在串口监视器中看到从手机上发过来的信息,如下:

这就实现了STM32与手机之间通过无线网络的TCP协议的通信

5、完整工程

将该文件解压后放到IDE安装目录的stm32duino文件夹下面的stm32examples中【13.wifi】目录中,在开发工具中的示例13下面就可以从示例中看到该工程示例。


esp8266-tcpserver.rar(点击下载)