ESP-IDF教程
1、开发环境搭建(win10+vscode)
参考网络资料。
2、helloworld
使用esp-idf提供的模板工程快速构建一个项目(打开示例工程快捷键ctrl+Alt+P)。
设置串口芯片型号和编译以及烧录、串口监视命令
2、设置波特率
点击右下角“齿轮按钮”,搜索框输入urat,打开相关设置
3、gpio控制(点亮LED为例子)
操作思想:由于esp-idf缺少相关文档,所以我们怎么知道操作引脚函数需要的参数是什么呢,答案是F12查看函数原型,通过查看函数的原型去查找函数需要的参数,如果参数也是库定义的,那就F12到参数的定义去查看。如下以gpio_set_direction()引脚状态设置函数为例子演示:
通过查看如下函数原型我们可知道该函数需要两个参数。
esp_err_t gpio_set_direction(gpio_num_t gpio_num, gpio_mode_t mode)
{
GPIO_CHECK(GPIO_IS_VALID_GPIO(gpio_num), "GPIO number error", ESP_ERR_INVALID_ARG);
if ((GPIO_IS_VALID_OUTPUT_GPIO(gpio_num) != true) && (mode & GPIO_MODE_DEF_OUTPUT)) {
ESP_LOGE(GPIO_TAG, "io_num=%d can only be input", gpio_num);
return ESP_ERR_INVALID_ARG;
}
esp_err_t ret = ESP_OK;
if (mode & GPIO_MODE_DEF_INPUT) {
gpio_input_enable(gpio_num);
} else {
gpio_input_disable(gpio_num);
}
if (mode & GPIO_MODE_DEF_OUTPUT) {
gpio_output_enable(gpio_num);
} else {
gpio_output_disable(gpio_num);
}
if (mode & GPIO_MODE_DEF_OD) {
gpio_od_enable(gpio_num);
} else {
gpio_od_disable(gpio_num);
}
return ret;
}
F12跳转到第一个参数的定义,发现是一个枚举类型的结构体,定义了芯片引脚。
F12跳转到第二个参数的定义,可知是管脚的状态。
1.引入gpio库文件
2.使用gpio_reset_pin()初始化引脚(2为例子)。
gpio_reset_pin(2); //初始化引脚
3.gpio_set_direction();
gpio_set_direction(2, GPIO_MODE_OUTPUT); // 设置管脚输出模式
- gpio_set_level();
gpio_set_level(2, status); // 设置管脚状态
5.LED灯间隔一秒闪烁代码
#include <stdio.h>
#include "esp_log.h"
#include "driver/gpio.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
uint32_t status = 0;
void app_main(void)
{
gpio_reset_pin(2); // 初始化引脚
gpio_set_direction(2, GPIO_MODE_OUTPUT); // 设置管脚输出模式
while (1)
{
status != status; // 取反
gpio_set_level(2, status); // 设置管脚状态
vTaskDelay(1000 / portTICK_PERIOD_MS); // 延时1000/1秒运行周期=1
}
}
如果闪烁时间不对注意查看如下配置
4、查看freertos中所有的进程信息
#include <stdio.h>
#include "esp_log.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
int count = 0;
char prtTaskList[250];
void app_main(void)
{
ESP_LOGI("COUNT", "Tick(ms):%d", portTICK_PERIOD_MS);
// vTaskDelay(1000 / portTICK_PERIOD_MS); // 延时1秒
printf("**************************************\n");
printf("Task state prio stack Num\n");
printf("**************************************\n");
printf(prtTaskList);
printf("**************************************\n");
}
5、自定义配置菜单
参考官方说明:乐鑫编程指南
新建一个配置文件,Kconfig.projbuild
打开menuconfig查看新增配置
设置
.c文件获取项目配置文件中的值。你可以在菜单中动态设置一个变量,该变量的声明会出现在项目配置文件中,复制变量名到源代码文件中即可引用菜单动态设置的变量。
6、向nvs中写入复杂数据(结构体数组以二进制的形式写入)
#include <stdio.h>
#include <string.h>
#include "esp_system.h"
#include "nvs_flash.h"
#include "nvs.h"
#include "esp_log.h"
void app_main()
{
char *bilibili_namespace = "BILIBILI_abc";
nvs_flash_init();
nvs_handle_t bilibili_handle;
nvs_open(bilibili_namespace, NVS_READWRITE, &bilibili_handle);
// 创建一个结构体并用结构体创建结构体数组,存储两个无线网的账号密码
uint32_t max_ap = 2;
typedef struct
{
char ssid[50];
char password[50];
} ap_t;
ap_t aps_set[max_ap];
ap_t aps_get[max_ap];
size_t length = sizeof(aps_get);
for (int i = 0; i < max_ap; i++)
{
strcpy(aps_set[i].ssid, "bilibili");
strcpy(aps_set[i].password, "123456");
}
// write
nvs_set_blob(bilibili_handle, "aps", aps_set, sizeof(aps_set));
// read
nvs_get_blob(bilibili_handle, "aps", aps_get, &length);
for (int i = 0; i < max_ap; i++)
{
ESP_LOGI("NVS", "ssid:password %s:%s", aps_get[i].ssid, aps_get[i].password);
}
// NVS
nvs_commit(bilibili_handle);
// 关闭NVS
nvs_close(bilibili_handle);
// 执行重启
esp_restart();
}
7、 打印内存数据
#include <stdio.h>
#include <string.h>
#include "esp_system.h"
#include "nvs_flash.h"
#include "nvs.h"
#include "esp_log.h"
void printMemory(unsigned char *address, int size)
{
int count;
for (count = 0; count < size; count++)
{
printf("%.2x", address[count]);
}
printf("\n");
}
void app_main()
{
uint32_t num = 200;
printMemory((unsigned char *)&num, 4);
num = 100;
printMemory((unsigned char *)&num, 4);
}
8、ESP32的WiFi模块
#include <stdio.h>
#include <string.h>
#include "esp_log.h"
#include "esp_wifi.h"
#include "nvs_flash.h"
void app_main(void)
{
ESP_LOGI("WIFI", "0. 初始化NVS存储");
esp_err_t ret = nvs_flash_init();
if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND)
{
ESP_ERROR_CHECK(nvs_flash_erase());
ret = nvs_flash_init();
}
ESP_ERROR_CHECK(ret);
ESP_LOGI("WIFI", "1. Wi-Fi 初始化阶段");
ESP_ERROR_CHECK(esp_netif_init());
ESP_ERROR_CHECK(esp_event_loop_create_default());
esp_netif_create_default_wifi_sta();
wifi_init_config_t wifi_config = WIFI_INIT_CONFIG_DEFAULT();
ESP_ERROR_CHECK(esp_wifi_init(&wifi_config));
ESP_LOGI("WIFI", "2. Wi-Fi 初始化阶段");
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
ESP_LOGI("WIFI", "3. Wi-Fi 启动阶段");
ESP_ERROR_CHECK(esp_wifi_start());
ESP_LOGI("WIFI", "4. Wi-Fi 扫描");
wifi_country_t wifi_country_config = {
.cc = "CN",
.schan = 1,
.nchan = 13,
};
ESP_ERROR_CHECK(esp_wifi_set_country(&wifi_country_config));
ESP_ERROR_CHECK(esp_wifi_scan_start(NULL, true));
uint16_t ap_num = 0;
ESP_ERROR_CHECK(esp_wifi_scan_get_ap_num(&ap_num));
ESP_LOGI("WIFI", "AP Count : %d", ap_num);
uint16_t max_aps = 20;
wifi_ap_record_t ap_records[max_aps];
memset(ap_records, 0, sizeof(ap_records));
uint16_t aps_count = max_aps;
ESP_ERROR_CHECK(esp_wifi_scan_get_ap_records(&aps_count, ap_records));
ESP_LOGI("WIFI", "AP Count: %d", aps_count);
printf("%30s %s %s %s\n", "SSID", "频道", "强度", "MAC地址");
for (int i = 0; i < aps_count; i++)
{
printf("%30s %3d %3d %02X-%02X-%02X-%02X-%02X-%02X\n", ap_records[i].ssid, ap_records[i].primary, ap_records[i].rssi, ap_records[i].bssid[0], ap_records[i].bssid[1], ap_records[i].bssid[2], ap_records[i].bssid[3], ap_records[i].bssid[4], ap_records[i].bssid[5]);
}
}
9、esp32多任务扫描附近所有WiFi
#include <stdio.h>
#include <string.h>
#include "esp_log.h"
#include "esp_wifi.h"
#include "nvs_flash.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_task_wdt.h"
// wifi_scan
void wifi_scan_task()
{
ESP_LOGI("WIFI", "4. Wi-Fi 扫描");
wifi_country_t wifi_country_config = {
.cc = "CN",
.schan = 1,
.nchan = 13,
};
ESP_ERROR_CHECK(esp_wifi_set_country(&wifi_country_config));
ESP_ERROR_CHECK(esp_wifi_scan_start(NULL, false));
uint16_t ap_num = 0;
ESP_ERROR_CHECK(esp_wifi_scan_get_ap_num(&ap_num));
ESP_LOGI("WIFI", "AP Count : %d", ap_num);
vTaskDelete(NULL);
}
void wifi_scan_show()
{
uint16_t ap_num = 0;
ESP_ERROR_CHECK(esp_wifi_scan_get_ap_num(&ap_num));
ESP_LOGI("WIFI", "AP Count : %d", ap_num);
uint16_t max_aps = 20;
wifi_ap_record_t ap_records[max_aps];
memset(ap_records, 0, sizeof(ap_records));
uint16_t aps_count = max_aps;
ESP_ERROR_CHECK(esp_wifi_scan_get_ap_records(&aps_count, ap_records));
ESP_LOGI("WIFI", "AP Count: %d", aps_count);
printf("%30s %s %s %s\n", "SSID", "频道", "强度", "MAC地址");
for (int i = 0; i < aps_count; i++)
{
printf("%30s %3d %3d %02X-%02X-%02X-%02X-%02X-%02X\n", ap_records[i].ssid, ap_records[i].primary, ap_records[i].rssi, ap_records[i].bssid[0], ap_records[i].bssid[1], ap_records[i].bssid[2], ap_records[i].bssid[3], ap_records[i].bssid[4], ap_records[i].bssid[5]);
}
vTaskDelete(NULL);
}
// 1. 定义事件处理程序
void run_on_event(void *handler_arg, esp_event_base_t base, int32_t id, void *event_data)
{
// 事件处理程序逻辑
ESP_LOGE("event_handle", "BASE:ID %s:%d", base, id);
// WIFI_EVENT_SCAN_DONE,
// WIFI_EVENT_STA_START,
switch (id)
{
case WIFI_EVENT_STA_START:
ESP_LOGE("event_handle", "WIFI_EVENT_STA_START");
// 创建任务wifi_scan任务
xTaskCreate(wifi_scan_task, "wifi scan task", 1024 * 12, NULL, 1, NULL);
break;
case WIFI_EVENT_SCAN_DONE:
ESP_LOGE("event_handle", "WIFI_EVENT_SCAN_DONE");
// 创建任务wifi_scan任务
xTaskCreate(wifi_scan_show, "wifi_scan_show", 1024 * 12, NULL, 1, NULL);
break;
default:
break;
}
}
void app_task(void *pt)
{
ESP_LOGI("APP_TASK", "APP_TASK create success!");
esp_event_handler_register(ESP_EVENT_ANY_BASE, ESP_EVENT_ANY_ID, run_on_event, NULL);
while (1)
{
// ESP_LOGI("APP_TASK", "APP_TASK 无聊的运行中!");
vTaskDelay(1000 / portTICK_PERIOD_MS); // 定时喂狗
}
}
/*
task_list()
显示当前的所有FreeRTOS任务
使用前,请在menuconfig中启动
Enable FreeRTOS trace facility
Enable FreeRTOS stats formatting functions
*/
void task_list(void)
{
char ptrTaskList[250];
vTaskList(ptrTaskList);
printf("*******************************************\n");
printf("Task State Prio Stack Num\n");
printf("*******************************************\n");
printf(ptrTaskList);
printf("*******************************************\n");
}
void app_main(void)
{
ESP_LOGI("WIFI", "0. 初始化NVS存储");
esp_err_t ret = nvs_flash_init();
if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND)
{
ESP_ERROR_CHECK(nvs_flash_erase());
ret = nvs_flash_init();
}
ESP_ERROR_CHECK(ret);
ESP_LOGI("WIFI", "1. Wi-Fi 初始化阶段");
ESP_ERROR_CHECK(esp_netif_init());
ESP_ERROR_CHECK(esp_event_loop_create_default());
esp_netif_create_default_wifi_sta();
wifi_init_config_t wifi_config = WIFI_INIT_CONFIG_DEFAULT();
ESP_ERROR_CHECK(esp_wifi_init(&wifi_config));
// 创建任务
xTaskCreate(app_task, "APP TASK", 1024 * 12, NULL, 1, NULL);
ESP_LOGI("WIFI", "2. Wi-Fi 初始化阶段");
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
ESP_LOGI("WIFI", "3. Wi-Fi 启动阶段");
ESP_ERROR_CHECK(esp_wifi_start());
while (1)
{
// ESP_LOGI("main_task", "main_task 无聊的运行中!");
vTaskDelay(1000 / portTICK_PERIOD_MS); // 定时喂狗
}
vTaskDelete(NULL); // 删除当前任务
}