Для реализации режима станции создадим 2 файла wifi.c и wifi.h
Внутри файла wifi.h добавим:
#ifndef MAIN_H_
#define MAIN_H_
//------------------------------------------------
#include "esp_common.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "uart.h"
#include "gpio.h"
#include "wifi.h"
//------------------------------------------------
WIFI_MODE ICACHE_FLASH_ATTR init_esp_wifi();
bool ICACHE_FLASH_ATTR start_wifi_station(const char * ssid, const char * pass);
//------------------------------------------------
//#include "esp_system.h"
//------------------------------------------------
#endif /* MAIN_H_ */
Переходим в файл wifi.с и добавим:
#include "wifi.h"
//------------------------------------------------
//
//задаем переменные - указатели на функции
//
wifi_state_cb_t on_station_connect = NULL;
wifi_disco_cb_t on_station_disconnect = NULL;
wifi_state_cb_t on_station_first_connect = NULL;
wifi_state_cb_t on_client_connect = NULL;
wifi_state_cb_t on_client_disconnect = NULL;
Здесь мы создали переменные-указатели на соответствующие функции, и указываем на NULL (в дальнейшем производим присвоение «правильных» ненулевых указателей и внутри функций проверяем что указатель !=NULL)
Далее добавим переменные:
//------------------------------------------------
volatile bool wifi_station_is_connected = false;
volatile bool wifi_station_static_ip = false;
//------------------------------------------------
static os_timer_t timer;
//------------------------------------------------
#define GPIO_LED 2
//------------------------------------------------
- Напишем функции для изменения NULL переменных-указателей
//
//Записываем в переменные-указатели на функции
//
void ICACHE_FLASH_ATTR set_on_station_connect(wifi_state_cb_t cb)
{
on_station_connect = cb;
}
//----------------------------------------------------------------
void ICACHE_FLASH_ATTR set_on_station_disconnect(wifi_disco_cb_t cb)
{
on_station_disconnect = cb;
}
- Теперь создадим callback функцию, которая будет вызываться при любом событии, внутри нее обработаем эти события
void ICACHE_FLASH_ATTR wifi_event_handler_cb(System_Event_t *event)
{
static bool station_was_connected = false;
if (event == NULL) return; //если события нет - выходим
os_printf("[WiFi] event %u\n", event->event_id);
switch (event->event_id) //перебираем события
{
case EVENT_STAMODE_DISCONNECTED:
wifi_station_is_connected = false;
GPIO_OUTPUT_SET(GPIO_LED, 1); //выкл светодиод
Event_StaMode_Disconnected_t *ev = (Event_StaMode_Disconnected_t *)&event->event_info;
if(on_station_disconnect) //если такая функция есть, то вызываем ее
{
on_station_disconnect(ev->reason); //выводим причину разрыва соединения
}
break;
case EVENT_STAMODE_CONNECTED:
if(wifi_station_static_ip)
{
os_printf("STA IP is static\n");
}
wifi_station_is_connected = true;
if(!station_was_connected) //если соединения не было
{
station_was_connected = true;
//если такая функция есть, то пытаемся создать соединение
if(on_station_first_connect) on_station_first_connect();
}
if(on_station_connect) on_station_connect();
break;
case EVENT_STAMODE_DHCP_TIMEOUT: //если не получили ip и т.д. для работы
if(wifi_station_is_connected)
{
wifi_station_is_connected = false;
if(on_station_disconnect) //если такая функция есть, то
{
on_station_disconnect(REASON_UNSPECIFIED); //выводим что причина не определена
//если такая функция есть, то пытаемся сделать первое соединение
if(on_station_first_connect) on_station_first_connect();
}
//если такая функция есть, то пытаемся соединиться
if(on_station_connect) on_station_connect();
}
break;
case EVENT_STAMODE_GOT_IP: //получили IP
wifi_station_is_connected = true;
GPIO_OUTPUT_SET(GPIO_LED, 0); //зажгли светодиод
//выставили флаг что станция создала соединение
if(!station_was_connected) station_was_connected = true;
break;
case EVENT_SOFTAPMODE_STACONNECTED:
//если такая функция есть, то пытаемся соединится
if(on_client_connect) on_client_connect();
break;
case EVENT_SOFTAPMODE_STADISCONNECTED:
//если такая функция есть, то пытаемся соединится
if(on_client_disconnect) on_client_disconnect();
break;
default:
break;
}
}
- Напишем функции для ПРОВЕРКИ соединения wifi :
//
//Проверка соединения и перепроверка по таймеру
//
bool ICACHE_FLASH_ATTR wifi_station_connected()
{
if(!wifi_station_is_connected) return false;
WIFI_MODE mode = wifi_get_opmode();
if((mode & STATION_MODE) == 0) return false;
STATION_STATUS wifistate = wifi_station_get_connect_status();
//Если получили IP- считаем, что соединились
wifi_station_is_connected = (wifistate == STATION_GOT_IP ||
(wifi_station_static_ip && wifistate == STATION_CONNECTING));
return wifi_station_is_connected;
}
//------------------------------------------------
LOCAL void ICACHE_FLASH_ATTR wait_for_connection_ready(uint8 flag)
{
//если соединение есть - уходим, иначе реконнект по таймеру
os_timer_disarm(&timer);
if(wifi_station_connected())
{
os_printf("connected\n");
}
else
{
os_printf("reconnect after 2s\n");
os_timer_setfn(&timer, (os_timer_func_t *)wait_for_connection_ready, NULL);
os_timer_arm(&timer, 2000, 0);
}
}
- Напишем функции коннекта и дисконнекта:
//
//Функции коннекта и дисконнекта
//
LOCAL void ICACHE_FLASH_ATTR on_wifi_connect()
{
os_printf("on_wifi_connect();\n");
os_timer_disarm(&timer);
os_timer_setfn(&timer, (os_timer_func_t *)wait_for_connection_ready, NULL);
os_timer_arm(&timer, 100, 0);
}
//------------------------------------------------
LOCAL void ICACHE_FLASH_ATTR on_wifi_disconnect(uint8_t reason)
{
os_printf("disconnect %d\n", reason);
}
- Напишем функцию изменения режима работы модуля:
//
//Изменение режима работы wifi модуля
//
bool ICACHE_FLASH_ATTR wifi_set_mode(WIFI_MODE mode)
{
if(!mode)
{
bool s = wifi_set_opmode(mode);
wifi_fpm_open();
wifi_fpm_set_sleep_type(MODEM_SLEEP_T);
wifi_fpm_do_sleep(0xFFFFFFFF);
return s;
}
wifi_fpm_close();
return wifi_set_opmode(mode);
}
//------------------------------------------------
- Теперь напишем функцию запуска в режиме станции:
//
//запуск в режиме станции
//
bool ICACHE_FLASH_ATTR start_wifi_station(const char * ssid, const char * pass)
{
WIFI_MODE mode = wifi_get_opmode();
if((mode & STATION_MODE) == 0)
{
mode |= STATION_MODE; //точно через или???
if(!wifi_set_mode(mode))
{
os_printf("Failed to enable Station mode!\n");
return false;
}
}
if(!ssid) //если нет ssid
{
os_printf("No SSID Given. Will connect to the station saved in flash\n");
return true;
}
struct station_config config;
memset(&config, 0, sizeof(struct station_config)); //обнуление структуры
strcpy(config.ssid, ssid);
//если есть пароль - копируем пароль
if(pass) strcpy(config.password, pass);
if(!wifi_station_set_config(&config))
{
os_printf("Failed to set Station config!\n");
return false;
}
wifi_set_sleep_type(NONE_SLEEP_T);
if(!wifi_station_dhcpc_status())
{
os_printf("DHCP is not started. Starting it...\n");
if(!wifi_station_dhcpc_start()) {
os_printf("DHCP start failed!\n");
return false;
}
}
if(wifi_get_phy_mode() != PHY_MODE_11N) wifi_set_phy_mode(PHY_MODE_11N);
return wifi_station_connect();
}
- По умолчанию модуль находится в режиме точка доступа, поэтому напишем функцию убирающую этот режим.
//------------------------------------------------
bool ICACHE_FLASH_ATTR stop_wifi_ap()
{
WIFI_MODE mode = wifi_get_opmode();
mode &= ~SOFTAP_MODE;
if(!wifi_set_mode(mode))
{
os_printf("Failed to disable AP mode!\n");
return false;
}
return true;
}
- Напишем функцию инициализации ESP в режиме станции
WIFI_MODE ICACHE_FLASH_ATTR init_esp_wifi()
{
//Записываем в переменные-указатели на функции
set_on_station_connect(on_wifi_connect);
set_on_station_disconnect(on_wifi_disconnect);
//"прописываем" Callback функцию
wifi_set_event_handler_cb(wifi_event_handler_cb);
WIFI_MODE mode = wifi_get_opmode_default(); //определяем текущий режим работы
wifi_set_mode(mode); //
stop_wifi_ap(); //отключение режима точка доступа
return mode;
}
- Теперь в файле main.c можно использовать написанные функции
//------------------------------------------------------
void ICACHE_FLASH_ATTR user_init()
{
UART_SetBaudrate(UART0,BIT_RATE_115200);
UART_SetBaudrate(UART1,BIT_RATE_115200);
//Init_something();
init_esp_wifi();
start_wifi_station(WiFi_Client_SSID, WiFi_Client_Password);
}
Принцип работы:
В функции init_esp_wifi(); прописываются указатели на соответствующие функции в переменные, а также event callback функция.
При запуске функции start_wifi_station(); проверяется наличие и копируются SSID и password, в самом конце вызывается функция wifi_station_connect(); завершающая настройку wifi.
В дальнейшем работа ведется через event/события в функции wifi_event_handler_cb();
В ней проверяются текущие события (а также что указатели на функции !=NULL) и вызываются соответствующие функции.
Наиболее интересная функция:
if(on_station_connect) on_station_connect(); //проверяет наличие и запускает функцию on_wifi_connect();
функция on_wifi_connect(); запускает таймер, а в прерывании по таймеру вызывается функция wait_for_connection_ready(); внутри которой проверяется наличие соединения и если не установилось, то перезапускается таймер.
Примечание:
В терминальную программу выводится IP адрес, на основе полученного IP можно «пропинговать» микроконтроллер.
в windows 7 нажать ctrl+R ввести cmd и потом ввести ping «ip»