介绍
本次实验以ESP8266 为AP模式 创建一个热点 并将默认的ip地址从.4.1 改成了10.1
代码如下
/*ESP8266 WIFI Station 代码*/
#include <stdio.h> //..
#include <stdlib.h> //..
#include <string.h> //..
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "esp_system.h"
#include "esp_log.h"
#include "esp_netif.h"
#include "esp_event.h"
#include "esp_wifi.h"
#include "nvs.h"
#include "nvs_flash.h"
#include "esp_err.h"
#include "lwip/err.h"
#include "lwip/sys.h"
#include "driver/gpio.h"
#define CONFIG_ESP_WIFI_SSID "ESP_AP"//热点WIFI的名称
#define CONFIG_ESP_WIFI_PASSWD "11223366" //热点的WiFi密码
#define CONFIG_ESP_MAX_STA_CONN 5 //热电动额最大连接数量
#define AP_CONNECTED_BIT BIT0
static const char *TAG = "wifi ap";
#define LED_PIN 2
EventGroupHandle_t wifi_event_group;
static struct netif *esp_netif[TCPIP_ADAPTER_IF_MAX];
void tcpip_adapter_set_ipaddr(tcpip_adapter_if_t tcpip_if);
esp_err_t tcpip_adapter_set_hostname(tcpip_adapter_if_t tcpip_if, const char *hostname);
static esp_err_t oled_delay_ms(uint32_t time)
{
vTaskDelay(time / portTICK_RATE_MS);
return ESP_OK;
}
//GPIO 初始化代码
void gpio_config_init(void)
{
gpio_config_t gpio_conf;
gpio_conf.mode=GPIO_MODE_OUTPUT;
gpio_conf.pin_bit_mask=(1ULL << LED_PIN);
gpio_conf.pull_up_en=0;
gpio_conf.pull_down_en=0;
gpio_conf.intr_type=GPIO_INTR_DISABLE;
gpio_config(&gpio_conf);
// gpio_set_level(GPIO_Pin_2,1);
}
void HeartbeatLED(void)
{
gpio_set_level(LED_PIN,0);
oled_delay_ms(40);
gpio_set_level(LED_PIN,1);
oled_delay_ms(70);
gpio_set_level(LED_PIN,0);
oled_delay_ms(40);
gpio_set_level(LED_PIN,1);
}
static void task1(void* arg)
{
for(;;){
printf("TASK1 IS RUNNING!\n");
HeartbeatLED();
vTaskDelay(1000 / portTICK_RATE_MS);
}
}
//创建热点的处理函数
static void event_handler(void *ctx, system_event_t *event)
{
system_event_info_t *info = &event->event_info;
printf("event_id %d\n",event->event_id);
switch(event->event_id)
{
case WIFI_EVENT_AP_START:
xEventGroupSetBits(wifi_event_group,AP_CONNECTED_BIT);//设置事件组标志位
break;
case WIFI_EVENT_AP_STOP:
xEventGroupClearBits(wifi_event_group,AP_CONNECTED_BIT);
break;
case WIFI_EVENT_AP_STACONNECTED: //14
printf("station "MACSTR" join, AID=%d\n",
MAC2STR(event->event_info.sta_connected.mac), event->event_info.sta_connected.aid);
break;
case WIFI_EVENT_AP_STADISCONNECTED://15
printf("station "MACSTR" leave,AID =%d\n",
MAC2STR(event->event_info.sta_disconnected.mac),event->event_info.sta_disconnected.aid);
break;
default:
break;
}
}
//创建热点的处理函数
void wifi_init_ap(void)
{
tcpip_adapter_init();
//设置默认IP地址
tcpip_adapter_set_ipaddr(TCPIP_ADAPTER_IF_AP);
//设置主机名
// ESP_ERROR_CHECK(tcpip_adapter_set_hostname(TCPIP_ADAPTER_IF_AP,"ESP8266"));
wifi_event_group = xEventGroupCreate();//创建事件组标志
ESP_ERROR_CHECK(esp_event_loop_create_default());//创建本地事件组
ESP_ERROR_CHECK(esp_event_loop_init(event_handler,NULL));
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();//初始化硬件信息
ESP_ERROR_CHECK(esp_wifi_init(&cfg));//初始化本地硬件
//ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT,ESP_EVENT_ANY_ID,&event_handler,NULL));
ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_RAM));
wifi_config_t wifi_ap_config = {
.ap = {
.ssid = CONFIG_ESP_WIFI_SSID,
.password = CONFIG_ESP_WIFI_PASSWD,
.ssid_len = strlen(CONFIG_ESP_WIFI_SSID),
.max_connection = CONFIG_ESP_MAX_STA_CONN,
.authmode = WIFI_AUTH_WPA2_PSK,
},
};
//密码为空时设置为开放
if (strlen(CONFIG_ESP_WIFI_PASSWD) == 0) {
wifi_ap_config.ap.authmode = WIFI_AUTH_OPEN;
}
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_AP));
ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_AP,&wifi_ap_config));
ESP_ERROR_CHECK(esp_wifi_start());
//等待AP启动
xEventGroupWaitBits(wifi_event_group,AP_CONNECTED_BIT,false,true,portMAX_DELAY);
ESP_LOGI(TAG,"wifi init ap finished,SSID:%s PASSWD:%s\n",CONFIG_ESP_WIFI_SSID,CONFIG_ESP_WIFI_PASSWD);
}
//设置默认IP地址
void tcpip_adapter_set_ipaddr(tcpip_adapter_if_t tcpip_if)
{
//改变默认ipd地址
tcpip_adapter_ip_info_t local_ip;
tcpip_adapter_dhcps_stop(tcpip_if);
IP4_ADDR(&local_ip.ip,192,168,10,254);
IP4_ADDR(&local_ip.gw,192,168,10,254);
IP4_ADDR(&local_ip.netmask,255,255,255,0);
tcpip_adapter_set_ip_info(tcpip_if,&local_ip);
tcpip_adapter_dhcps_start(tcpip_if);
}
#if 0
//设置主机名
esp_err_t tcpip_adapter_set_hostname(tcpip_adapter_if_t tcpip_if, const char *hostname)
{
#if LWIP_NETIF_HOSTNAME
struct netif *p_netif;
static char hostinfo[TCPIP_ADAPTER_IF_MAX][TCPIP_HOSTNAME_MAX_SIZE + 1];
if (tcpip_if >= TCPIP_ADAPTER_IF_MAX || hostname == NULL) {
return ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS;
}
if (strlen(hostname) > TCPIP_HOSTNAME_MAX_SIZE) {
return ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS;
}
p_netif = esp_netif[tcpip_if];
if (p_netif != NULL) {
memset(hostinfo[tcpip_if], 0, sizeof(hostinfo[tcpip_if]));
strlcpy(hostinfo[tcpip_if], hostname, sizeof(hostinfo[tcpip_if]));
p_netif->hostname = hostinfo[tcpip_if];
p_netif->
return ESP_OK;
} else {
return ESP_ERR_TCPIP_ADAPTER_IF_NOT_READY;
}
#else
return ESP_ERR_TCPIP_ADAPTER_IF_NOT_READY;
#endif
}
#endif
void app_main()
{
ESP_ERROR_CHECK(nvs_flash_init());
printf("ESP8266 WIFI Station test!");
vTaskDelay(1000/portTICK_PERIOD_MS);
wifi_init_ap();
gpio_config_init();
xTaskCreate(task1, "task1_test", 512, NULL, 3, NULL);
}
分析
/*ESP8266 WIFI Station 代码*/
#include <stdio.h> //..
#include <stdlib.h> //..
#include <string.h> //..
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "esp_system.h"
#include "esp_log.h"
#include "esp_netif.h"
#include "esp_event.h"
#include "esp_wifi.h"
#include "nvs.h"
#include "nvs_flash.h"
#include "esp_err.h"
#include "lwip/err.h"
#include "lwip/sys.h"
#include "driver/gpio.h"
引入了一些要用到的头文件
#define CONFIG_ESP_WIFI_SSID "ESP_AP"//热点WIFI的名称
#define CONFIG_ESP_WIFI_PASSWD "11223366" //热点的WiFi密码
#define CONFIG_ESP_MAX_STA_CONN 5 //热电动额最大连接数量
#define AP_CONNECTED_BIT BIT0
static const char *TAG = "wifi ap";
#define LED_PIN 2
EventGroupHandle_t wifi_event_group;
static struct netif *esp_netif[TCPIP_ADAPTER_IF_MAX];
void tcpip_adapter_set_ipaddr(tcpip_adapter_if_t tcpip_if);
esp_err_t tcpip_adapter_set_hostname(tcpip_adapter_if_t tcpip_if, const char *hostname);
声明了一些用到的函数 热点的wifi名称 密码以及最大连接数量
创立了一个事件组 用来管理ap的过程 ,这个事件组有点类似于标志位 置位 清零 等待置位 或者清零
tcpip_adapter_set_ipaddr 设置IP地址的函数从.4 网段 改成了.10网段
tcpip_adapter_set_hostname 设置主机名 暂未实现
//创建热点的处理函数
void wifi_init_ap(void)
{
tcpip_adapter_init();
//设置默认IP地址
tcpip_adapter_set_ipaddr(TCPIP_ADAPTER_IF_AP);
//设置主机名
// ESP_ERROR_CHECK(tcpip_adapter_set_hostname(TCPIP_ADAPTER_IF_AP,"ESP8266"));
wifi_event_group = xEventGroupCreate();//创建事件组标志
ESP_ERROR_CHECK(esp_event_loop_create_default());//创建本地事件组
ESP_ERROR_CHECK(esp_event_loop_init(event_handler,NULL));
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();//初始化硬件信息
ESP_ERROR_CHECK(esp_wifi_init(&cfg));//初始化本地硬件
//ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT,ESP_EVENT_ANY_ID,&event_handler,NULL));
ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_RAM));
wifi_config_t wifi_ap_config = {
.ap = {
.ssid = CONFIG_ESP_WIFI_SSID,
.password = CONFIG_ESP_WIFI_PASSWD,
.ssid_len = strlen(CONFIG_ESP_WIFI_SSID),
.max_connection = CONFIG_ESP_MAX_STA_CONN,
.authmode = WIFI_AUTH_WPA2_PSK,
},
};
//密码为空时设置为开放
if (strlen(CONFIG_ESP_WIFI_PASSWD) == 0) {
wifi_ap_config.ap.authmode = WIFI_AUTH_OPEN;
}
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_AP));
ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_AP,&wifi_ap_config));
ESP_ERROR_CHECK(esp_wifi_start());
//等待AP启动
xEventGroupWaitBits(wifi_event_group,AP_CONNECTED_BIT,false,true,portMAX_DELAY);
ESP_LOGI(TAG,"wifi init ap finished,SSID:%s PASSWD:%s\n",CONFIG_ESP_WIFI_SSID,CONFIG_ESP_WIFI_PASSWD);
}
首先是初始化适配器,在初始化适配器之后修改了IP地址
创立了事件组
初始化硬件信息
设置ap参数
设置wifi模式
启动wifi
等待置位标志 也就是等待AP启动 如果AP停止 又会被清零
//创建热点的处理函数
static void event_handler(void *ctx, system_event_t *event)
{
system_event_info_t *info = &event->event_info;
printf("event_id %d\n",event->event_id);
switch(event->event_id)
{
case WIFI_EVENT_AP_START:
xEventGroupSetBits(wifi_event_group,AP_CONNECTED_BIT);//设置事件组标志位
break;
case WIFI_EVENT_AP_STOP:
xEventGroupClearBits(wifi_event_group,AP_CONNECTED_BIT);
break;
case WIFI_EVENT_AP_STACONNECTED: //14
printf("station "MACSTR" join, AID=%d\n",
MAC2STR(event->event_info.sta_connected.mac), event->event_info.sta_connected.aid);
break;
case WIFI_EVENT_AP_STADISCONNECTED://15
printf("station "MACSTR" leave,AID =%d\n",
MAC2STR(event->event_info.sta_disconnected.mac),event->event_info.sta_disconnected.aid);
break;
default:
break;
}
}
在AP连接上 会置位 断开后会复位 AP连接上时会打印STA的IP地址 MAC地址等信息
AP断开时会打印断开STA的信息
//设置默认IP地址
void tcpip_adapter_set_ipaddr(tcpip_adapter_if_t tcpip_if)
{
//改变默认ipd地址
tcpip_adapter_ip_info_t local_ip;
tcpip_adapter_dhcps_stop(tcpip_if);
IP4_ADDR(&local_ip.ip,192,168,10,254);
IP4_ADDR(&local_ip.gw,192,168,10,254);
IP4_ADDR(&local_ip.netmask,255,255,255,0);
tcpip_adapter_set_ip_info(tcpip_if,&local_ip);
tcpip_adapter_dhcps_start(tcpip_if);
}
设置ip地址将默认的.4.1的网段改成了.10.1 的网段 并且将自己的网址设置成了192.168.10.254
该函数必须在初始化tcpip适配器后执行,如果在tcpip中修改 那么就是全局的修改,所以在适配器后执行就是只限于本程序的修改 在修改前先停止dhcp服务 修改后再启动
static esp_err_t delay_ms(uint32_t time)
{
vTaskDelay(time / portTICK_RATE_MS);
return ESP_OK;
}
//GPIO 初始化代码
void gpio_config_init(void)
{
gpio_config_t gpio_conf;
gpio_conf.mode=GPIO_MODE_OUTPUT;
gpio_conf.pin_bit_mask=(1ULL << LED_PIN);
gpio_conf.pull_up_en=0;
gpio_conf.pull_down_en=0;
gpio_conf.intr_type=GPIO_INTR_DISABLE;
gpio_config(&gpio_conf);
// gpio_set_level(GPIO_Pin_2,1);
}
void HeartbeatLED(void)
{
gpio_set_level(LED_PIN,0);
delay_ms(40);
gpio_set_level(LED_PIN,1);
delay_ms(70);
gpio_set_level(LED_PIN,0);
delay_ms(40);
gpio_set_level(LED_PIN,1);
}
static void task1(void* arg)
{
for(;;){
printf("TASK1 IS RUNNING!\n");
HeartbeatLED();
vTaskDelay(1000 / portTICK_RATE_MS);
}
}
最后写了一个任务1 就行心跳灯的程序 测试多任务性能
void app_main()
{
ESP_ERROR_CHECK(nvs_flash_init());
printf("ESP8266 WIFI Station test!");
vTaskDelay(1000/portTICK_PERIOD_MS);
wifi_init_ap();
gpio_config_init();
xTaskCreate(task1, "task1_test", 512, NULL, 3, NULL);
}
效果展示