1. 程式人生 > >ESP8266例程解析④softAPToNet

ESP8266例程解析④softAPToNet

程式碼分析

  1. 初始化分割槽

  2. 初始化串列埠(串列埠1 串列埠2都為57600) 初始化串列埠(串列埠1 串列埠2都為57600)

  3. 列印sdk版本

  4. 按鍵初始化(簡短的單按鈕初始化 長按 短按 按鍵驅動程式初始化 IO口初始化)
    4.1 按鍵回撥函式(長按函式 短按函式 內含提示燈)
    4.2 長按函式為空
    4.3短按函式為
    4.3.1 WiFi準備(設定模式,ssid password 加密模式 信標間隔時槽 通道號(即通頻帶) 最大連線數 隱藏ssid 儲存到flash)
    4.3.2 TCP準備埠8266(分配空間 設定型別為TCP協議 本地埠 註冊連線成功回撥函式(server_listen)和重新連接回調函式(server_recon))建立 TCP server,建立偵聽 設定超時斷開時間
    4.3.2 .1註冊連線成功回撥函式(server_listen)入口 使用者tcp型別地址
    4.3.2 .1.1 回撥函式 接收(用cJSON解析接收的包 判斷包是否為空 建立物件 給物件傳遞資料 列印物件 1. 如果為空 建立物件 提示json錯誤 2.不為空 建立物件 繼承WiFi ssid password state(為0(成功連線到指定的WiFi 檢測是否有IP,有代表連線成功) 為1表示連線AP) 列印資訊)AP和WiFi區別是IP地址
    4.3.2 .1.2傳送(設定為station模式 傳送資訊) 斷開
    4.3.2 .2重新連接回調函式(server_recon) 返回錯誤程式碼和型別

  5. 設定ESP8266 station 上電是否自動連線已記錄的AP(路由),預設為自動連線

  6. 設定為無睡眠模式

  7. 定時器回撥函式 檢查WIFI狀態,用IO口的燈變化顯示出WiFi狀態列印sdk版本 按鍵初始化定時器回撥函式 檢查WIFI狀態,用IO口的燈變化顯示出WiFi狀態

程式碼

user_main.c
#include "driver/uart.h"  //串列埠0需要的標頭檔案
#include "osapi.h"  //串列埠1需要的標頭檔案
#include "user_interface.h" //WIFI連線需要的標頭檔案
#include "espconn.h"//TCP連線需要的標頭檔案
#include "mem.h" //系統操作需要的標頭檔案
#include "gpio.h"  //埠控制需要的標頭檔案
#include "cJSON.h"
#include "hal_key.h"

struct espconn user_tcp_espconn;
os_timer_t checkTimer_wifistate;

//按鍵定義
#define GPIO_KEY_NUM                            1
#define KEY_0_IO_MUX                            PERIPHS_IO_MUX_MTMS_U
#define KEY_0_IO_NUM                            14
#define KEY_0_IO_FUNC                           FUNC_GPIO14

LOCAL key_typedef_t * singleKey[GPIO_KEY_NUM]; 
LOCAL keys_typedef_t keys; 

bool isConnected = false;

void Check_WifiState(void)//檢查WIFI狀態
 {

	uint8 status = wifi_station_get_connect_status();//查詢ESP8266 WIFI  station 介面連線AP的狀態 

	if (status == STATION_GOT_IP)//檢測是否連線AP並且返回資訊
	 {
		GPIO_OUTPUT_SET(GPIO_ID_PIN(15), 0);  //設定IO口輸出電平
		GPIO_OUTPUT_SET(GPIO_ID_PIN(12), 1);
		wifi_set_opmode(0x01);   //WIFI模式為station
	} 
	else 
	{
		GPIO_OUTPUT_SET(GPIO_ID_PIN(12), 0); //GPIO15 低電平輸出
		GPIO_OUTPUT_SET(GPIO_ID_PIN(15), 1); //GPIO15 低電平輸出
	}
}

void wifiStationConnect(char *ssid, char *psw)//WiFi重新連線
 {
	os_printf(" wifiStationConnect name:%s \n", ssid);
	os_printf(" wifiStationConnect psw :%s \n", psw);
	struct station_config stationConf;
	os_strcpy(stationConf.ssid, ssid);	  //路由器的使用者名稱
	os_strcpy(stationConf.password, psw); //路由器的密碼
	wifi_station_set_config(&stationConf); //設定WiFi station介面配置,並儲存到 flash
	wifi_station_connect(); //連線路由器

}

void ICACHE_FLASH_ATTR server_recv(void *arg, char *pdata, unsigned short len)  //註冊 TCP 連線成功建立後的回撥函式接收
{
    //判斷是否為json資料
	cJSON *root = cJSON_Parse(pdata);//解析資料  返回一個解析成功的值  呼叫cJSON.c庫
	if (!root) 
	{
		os_printf("Error before: [%s]\n", cJSON_GetErrorPtr());/*用於分析失敗的分析。這將返回指向分析錯誤的指標。你可能需要找幾個字元來解釋它。當cjson_parse()返回0時定義。當cjson_parse()成功時為0。*/
		cJSON * Result = cJSON_CreateObject();/*這些呼叫建立適當型別的CJSON項。 創造物件分配空間 大小為6 範圍為0到6 */  
		cJSON_AddNumberToObject(Result, "status", 3);//新增數字到物件   物件  名字  數字
		cJSON_AddStringToObject(Result, "msg", "json error!");//新增字串到物件   物件  名字  字串
		char *succeedData = cJSON_Print(Result);//將CJSON項/實體/結構呈現為文字。
		char data[1024];
		os_sprintf(data, "%s", succeedData);    //列印Result
		espconn_send((struct espconn *) arg, data, strlen(data));//通過WIFI傳送資料
		return;
	} 
	else
	 {
		char *ssid, *psw;
		int state;
		//解析欄位
		cJSON *ssid_json = cJSON_GetObjectItem(root, "ssid");
		cJSON *psw_json = cJSON_GetObjectItem(root, "psw");
		cJSON *state_json = cJSON_GetObjectItem(root, "state");
	
		state = state_json->valueint;
		//對state 進行剖析
		switch (state) 
		{	//當前wifi的連線情況查詢
		case 0://成功連線到指定的WiFi
			if (STATION_GOT_IP == wifi_station_get_connect_status()) 
			{

				cJSON * Result = cJSON_CreateObject();
				cJSON_AddNumberToObject(Result, "status", 0);
				cJSON_AddStringToObject(Result, "msg", "connect succeed!");
				char *succeedData = cJSON_Print(Result);
				char data[1024];
				os_sprintf(data, "%s", succeedData);
				espconn_send((struct espconn *) arg, data, strlen(data));
				isConnected = true;
			} 
			else
			 {
				//未連線到指定的WiFi
				cJSON * Result = cJSON_CreateObject();
				cJSON_AddNumberToObject(Result, "status", 1);
				cJSON_AddStringToObject(Result, "msg", "connect fail!");
				char *succeedData = cJSON_Print(Result);
				char data[1024];
				os_sprintf(data, "%s", succeedData);
				espconn_send((struct espconn *) arg, data, strlen(data));
			}

			break;

			//1表示連線AP
		case 1:

			if (ssid_json && psw_json) 
			{
				ssid = ssid_json->valuestring;
				psw = psw_json->valuestring;
				wifiStationConnect(ssid, psw);//WiFi重新連線
			} 
			else {
				os_printf(" width null! \n");
			}

			cJSON_Delete(root);//釋放記憶體
			cJSON * Result = cJSON_CreateObject();//構造json
			cJSON_AddNumberToObject(Result, "status", 2);
			cJSON_AddStringToObject(Result, "msg", "AP connectting!");
			char *succeedData = cJSON_Print(Result);
			char data[1024];
			os_sprintf(data, "%s", succeedData);
			espconn_send((struct espconn *) arg, data, strlen(data));

			break;

		}

	}
}

void ICACHE_FLASH_ATTR server_sent(void *arg)  //註冊 TCP 連線成功建立後的回撥函式傳送
{
	os_printf("send data succeed!\r");
	if (isConnected) 
	{
		wifi_set_opmode(0x01); //設定為STATION模式
	}
}

void ICACHE_FLASH_ATTR server_discon(void *arg) //註冊 TCP 連線成功建立後的回撥函式斷開
 {
	os_printf("conect diable! \r");
}

void ICACHE_FLASH_ATTR server_listen(void *arg) //註冊 TCP 連線成功建立後的回撥函式
{
	struct espconn *pespconn = arg;
	espconn_regist_recvcb(pespconn, server_recv); //接收
	espconn_regist_sentcb(pespconn, server_sent); //傳送
	espconn_regist_disconcb(pespconn, server_discon); //斷開
}

void ICACHE_FLASH_ATTR server_recon(void *arg, sint8 err) //註冊 TCP 連線發生異常斷開時的回撥函式,可以在回撥函式中進行重連
{
	os_printf("連線錯誤,錯誤程式碼為:%d\r\n", err); //%d,用來輸出十進位制整數
}

void Inter213_InitTCP(uint32_t Local_port) 
{
	user_tcp_espconn.proto.tcp = (esp_tcp *) os_zalloc(sizeof(esp_tcp)); //分配空間
	user_tcp_espconn.type = ESPCONN_TCP; //設定型別為TCP協議
	user_tcp_espconn.proto.tcp->local_port = Local_port; //本地埠

	//註冊連線成功回撥函式和重新連接回調函式
	espconn_regist_connectcb(&user_tcp_espconn, server_listen); //註冊 TCP 連線成功建立後的回撥函式
	espconn_regist_reconcb(&user_tcp_espconn, server_recon); //註冊 TCP 連線發生異常斷開時的回撥函式,可以在回撥函式中進行重連
	espconn_accept(&user_tcp_espconn); //建立 TCP server,建立偵聽
	espconn_regist_time(&user_tcp_espconn, 180, 0); //設定超時斷開時間 單位:秒,最大值:7200 秒
	//如果超時時間設定為 0,ESP8266 TCP server 將始終不會斷開已經不與它通訊的 TCP client,不建議這樣使用。

}

void WIFI_Init()
 {
	struct softap_config apConfig;
	wifi_set_opmode(0x03);    //設定為station+soft-AP模式,儲存到 flash
	apConfig.ssid_len = 10;						//設定ssid長度
	os_strcpy(apConfig.ssid, "xaiofang");	    //設定ssid名字
	os_strcpy(apConfig.password, "12345678");	//設定密碼
	apConfig.authmode = 3;                      //設定加密模式
	apConfig.beacon_interval = 100;            //信標間隔時槽100 ~ 60000 ms
	apConfig.channel = 1;                      //通道號1 ~ 13
	apConfig.max_connection = 4;               //最大連線數
	apConfig.ssid_hidden = 0;                  //隱藏SSID

	wifi_softap_set_config(&apConfig);		//設定 WiFi soft-AP 介面配置,並儲存到 flash
}

void wifiConnectCb(uint8_t status)
 {

}

LOCAL void ICACHE_FLASH_ATTR keyLongPress(void)//長按按鍵
 {

}

LOCAL void ICACHE_FLASH_ATTR keyShortPress(void) //短按按鍵
{
	os_printf(" key short...\r\n");
	WIFI_Init();    //WIFI 準備
	Inter213_InitTCP(8266); //本地埠
}
//按鍵初始化
LOCAL void ICACHE_FLASH_ATTR keyInit(void)
 {
	singleKey[0] = keyInitOne(KEY_0_IO_NUM, KEY_0_IO_MUX, KEY_0_IO_FUNC,
			keyLongPress, keyShortPress);//簡短的單按鈕初始化 長按  短按
	keys.singleKey = singleKey;
	keyParaInit(&keys);//簡短按鈕驅動程式初始化

	PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDI_U, FUNC_GPIO12); //GPIO12初始化(管腳功能選擇)
	PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDO_U, FUNC_GPIO15); //GPIO15初始化(管腳功能選擇)
}

void user_init()
 {
	uart_init(57600, 57600);		//設定串列埠0和串列埠1的波特率
	os_printf("-----SDK version:%s------\n", system_get_sdk_version());//列印版本號
	keyInit();  //按鍵準備
	
	wifi_station_set_auto_connect(1);//設定ESP8266 station 上電是否自動連線已記錄的AP(路由),預設為自動連線1 0為不自動
	wifi_set_sleep_type(NONE_SLEEP_T);                     //set none sleep mode,預設為睡眠模式(modem-sleep引數為sleep_type)

	os_timer_disarm(&checkTimer_wifistate); //取消定時器定時
	os_timer_setfn(&checkTimer_wifistate, (os_timer_func_t *) Check_WifiState,
	NULL); //設定定時器回撥函式   檢查WIFI狀態
	os_timer_arm(&checkTimer_wifistate, 1000, true); //啟動定時器,單位:毫秒

}

void user_rf_pre_init() 
{

}

在這裡插入圖片描述

在這裡插入圖片描述

keyInitOne(uint8 gpio_id, uint32 gpio_name, uint8 gpio_func, gokit_key_function long_press, gokit_key_function short_press)
/**
*@簡短的單按鈕初始化

*在這個函式中要完成單鍵初始化,這裡需要結合ESP8266 GPIO暫存器描述文件來設定引數

*@param[in]gpio_id ESP8266 GPIO號碼

*@param[in]gpio_name ESP8266 GPIO名稱

*@param[in]gpio_func ESP8266 GPIO函式

*@param[in]long_press Long按回調函式地址

*@param[in]._press Short press狀態回撥函式地址

*@return單按鈕結構指標

*/

/**
* @brief button driver initialization

* In the function to complete all the keys GPIO initialization, and open a timer to start the key state monitoring
* @param [in] keys Key Function Global structure pointer
* @return none
* /**

*@簡短按鈕驅動程式初始化
*在函式中完成所有金鑰GPIO初始化,並開啟定時器開始金鑰狀態監控。
*@param[in]keys鍵函式全域性結構指標
*@無返回

*/
*/
void ICACHE_FLASH_ATTR keyParaInit(keys_typedef_t * keys)
{
    uint8 tem_i = 0; 
    
    if(NULL == keys)
    {
        return ;
         
    }
    
    //init key timer    準備按鍵定時器
    keys->key_timer_ms = KEY_TIMER_MS; 
    os_timer_disarm(&keys->key_timer); 
    os_timer_setfn(&keys->key_timer, (os_timer_func_t *)gokitKeyHandle, keys); //定時器回撥函式
    
    keys->keyTotolNum = keyTotolNum;

    //Limit on the number keys (Allowable number: 0~12)  數字鍵的限制(0-12)
    if(KEY_MAX_NUMBER < keys->keyTotolNum) 
    {
        keys->keyTotolNum = KEY_MAX_NUMBER; 
    }
    
    //GPIO configured as a high level input mode  GPIO,配置為高階輸入模式
    for(tem_i = 0; tem_i < keys->keyTotolNum; tem_i++) 
    {
        PIN_FUNC_SELECT(keys->singleKey[tem_i]->gpio_name, keys->singleKey[tem_i]->gpio_func); //管腳功能選擇
        GPIO_OUTPUT_SET(GPIO_ID_PIN(keys->singleKey[tem_i]->gpio_id), 1); //設定GPIO屬性
        PIN_PULLUP_EN(keys->singleKey[tem_i]->gpio_name); //管腳使能上拉
        GPIO_DIS_OUTPUT(GPIO_ID_PIN(keys->singleKey[tem_i]->gpio_id)); 
        
        os_printf("gpio_name %d \r\n", keys->singleKey[tem_i]->gpio_id); 
    }
    
    //key timer start   按鍵定時器啟動
    os_timer_arm(&keys->key_timer, keys->key_timer_ms, 1); 
}

在這裡插入圖片描述
在這裡插入圖片描述
在這裡插入圖片描述
在這裡插入圖片描述
在這裡插入圖片描述
安卓APK:網路除錯助手