ESP8266例程解析④softAPToNet
程式碼分析
-
初始化分割槽
-
初始化串列埠(串列埠1 串列埠2都為57600) 初始化串列埠(串列埠1 串列埠2都為57600)
-
列印sdk版本
-
按鍵初始化(簡短的單按鈕初始化 長按 短按 按鍵驅動程式初始化 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) 返回錯誤程式碼和型別 -
設定ESP8266 station 上電是否自動連線已記錄的AP(路由),預設為自動連線
-
設定為無睡眠模式
-
定時器回撥函式 檢查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:網路除錯助手