ESP-IDF 笔记
视频教程来自B站Up主孤独的二进制发布的ESP32系列ESP-IDF课程,使用合宙ESP32C3开发板实际测试,本文整理示例代码及我在合宙esp32c3的实际运行效果。
入门笔记
printf函数
- demo01
示例程序功能为使用printf函数输出各类信息
fflush()函数用于刷新流 stream 的输出缓冲区。 - 示例代码
#include <stdio.h>
void app_main(void)
{
printf("Hello world!\n");
printf("Name:%s\n","Dapenson");
printf("Char:%c %c\n",'A',65);
printf("%d年%d月%d日\n",2022,11,21);
printf("传感器1 %+10.3f\n",12.345);
printf("传感器2 %+10.3f\n",-11.123);
printf("传感器3 %+10.3f\n",2.345);
uint64_t millis = 0x12345678;
printf("millis:%llu\n",millis);
fflush(stdout);
}
- 运行效果
日志
- demo02
使用ESP_LOGE()打印日志信息
通过menu更改底层默认打印设置
当产品出现问题,联系售后的时候,用户如何通过神秘的按键,或者按键的组合方式,输出更多的debug 信息,已便于远程排错。
- 示例代码
#include <stdio.h>
#include "esp_log.h"
const char *tag_traffic = "交通灯";
bool serer_log = true;
void app_main(void)
{
// 可通过按钮或变量设置日志打印等级,
// 需在ESP-IDF: Menuconfig将日志可打印等级(Maximum log verbosity)设置为Verbose
if (serer_log == true)
{
esp_log_level_set(tag_traffic, ESP_LOG_VERBOSE);
}
else
{
esp_log_level_set(tag_traffic, ESP_LOG_INFO);
}
// E error
ESP_LOGE(tag_traffic, "不亮了");
// W warning
ESP_LOGW(tag_traffic, "灯泡寿命还有%i%%", 15);
// I info
ESP_LOGI(tag_traffic, "灯泡寿命还有%i%%", 80);
// D debug
ESP_LOGD(tag_traffic, "灯泡亮度为1000,已使用200小时");
// V verbose
ESP_LOGV(tag_traffic, "灯泡灯丝还有5丝厚度,氧化程度0.23,寿命正常");
ESP_LOGE("人行横道", "有人闯红灯");
ESP_LOGW("人行横道", "现在是红灯,禁止通行");
ESP_LOGI("人行横道", "现在是绿灯,可以通行");
}
- 运行效果
Tick
-
demo03
使用延时
通过menu更改底层默认tick设置(默认100Hz,即一个tick是10ms) -
示例代码
#include <stdio.h>
#include "esp_log.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
int count;
void app_main(void)
{
count = 100;
ESP_LOGI("COUNTER", "Tick (ms): %d", portTICK_PERIOD_MS);
while (1)
{
ESP_LOGI("COUNTER", "Count: %d", count);
vTaskDelay(1000 / portTICK_PERIOD_MS);
count++;
}
}
- 效果演示
任务看门狗
很多朋友在初试IDF时,经常遇到程序莫名跑飞重启的情况,很有可能是出发了任务看门狗。以下对ESP32中众多狗中的任务看门狗进行实际测试与通过idf menu配置看门狗。
- demo04
示例代码功能为查看当前所有的任务情况
程序运行之前需要先打开两个配置,否则无法使用vTaskList()函数
#include <stdio.h>
#include "esp_log.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
char ptrTaskList[250];
void app_main(void)
{
vTaskList(ptrTaskList);
printf("**********************************************\n")
printf("Task State Priority Stack Num\n");
printf("**********************************************\n")
printf("%s", ptrTaskList);
printf("**********************************************\n")
}
- 演示效果
可以看到main这个任务优先级是高于idle的,当mian中有死循环且一直没有释放资源的时候,程序就不会去跑idle任务,因此跑飞。
可以将示例程序demo03中的vtaskDelay注释之后查看打印信息,程序每5s会报错重启并继续打印。
在menu中搜索watchdog
和panic
,可以配置任务看门狗的时间和触发时候的动作等(重启+打印寄存器信息、重启 等)
因此在程序开发的时候,最好不要死循环,让代码有时间来运行idle。
Blink
经典的点灯来了
-
demo05
示例程序功能为闪烁合宙esp32c3的板载左侧LED灯 -
示例程序
#include <stdio.h>
#include "driver/gpio.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#define LED_LEFT GPIO_NUM_12
#define LED_RIGHT GPIO_NUM_13
#define DELAYS_MS 1000
uint32_t led_state = 0;
void app_main(void)
{
gpio_reset_pin(LED_LEFT);
gpio_set_direction(LED_LEFT, GPIO_MODE_OUTPUT);
while (1)
{
led_state = !led_state;
gpio_set_level(LED_LEFT, led_state);
vTaskDelay(DELAYS_MS / portTICK_PERIOD_MS);
}
}
- 效果演示
获取硬件信息
-
demo06
通过乐鑫提供的API说明手册获取芯片硬件信息 -
示例源码
点击查看代码
#include <stdio.h>
#include "esp_system.h"
#include "esp_spi_flash.h"
#include "esp_log.h"
const char *hw = "硬件";
const char *sw = "软件";
void app_main(void)
{
ESP_LOGE(sw, "IDF版本号: %s", esp_get_idf_version());
esp_chip_info_t chip_info;
esp_chip_info(&chip_info);
ESP_LOGE(hw, "CPU核心数: %d", chip_info.cores);
// ESP_LOGE(hw, "CPU 版本号: %s", chip_info.revision);
// char *esp_type;
// switch (chip_info.model)
// {
// case CHIP_ESP32:
// esp_type = "ESP32";
// break;
// case CHIP_ESP32S2:
// esp_type = "ESP32-S2";
// break;
// case CHIP_ESP32S3:
// esp_type = "ESP32-S3";
// break;
// case CHIP_ESP32C3:
// esp_type = "ESP32-C3";
// break;
// default:
// esp_type = "未知";
// break;
// }
// ESP_LOGE(hw, "芯片类型: %s", esp_type);
// ESP_LOGE(hw, "特征: %s", chip_info.features);
ESP_LOGE(hw, "WIFI: %s", chip_info.features & CHIP_FEATURE_WIFI_BGN ? "支持" : "不支持");
ESP_LOGE(hw, "蓝牙BLE: %s", chip_info.features & CHIP_FEATURE_BLE ? "支持" : "不支持");
ESP_LOGE(hw, "蓝牙2.0: %s", chip_info.features & CHIP_FEATURE_BT ? "支持" : "不支持");
ESP_LOGE(hw, "IEEE 802.15.4: %s", chip_info.features & CHIP_FEATURE_IEEE802154 ? "支持" : "不支持");
ESP_LOGE(hw, "内置PSRAM: %s", chip_info.features & CHIP_FEATURE_EMB_PSRAM ? "支持" : "不支持");
ESP_LOGE(hw, "内置FLASH: %s", chip_info.features & CHIP_FEATURE_EMB_FLASH ? "支持" : "不支持");
ESP_LOGE(hw, "Flash 容量: %d MBytes", spi_flash_get_chip_size() / (1024 * 1024));
ESP_LOGE(hw, "Flash 容量: %d MBits", spi_flash_get_chip_size() * 8 / (1024 * 1024));
}
- 效果演示
WIFI基础
WIFI扫描
根据介绍乐鑫官方手册wifi部分,
介绍一种ESP32片上无线模块扫频应用,让ESP32 能够获取周围WiFi热点信息,实现无线扫频功能。详细步骤如下:
- 使用NVS存储初始化。
- 使用Wi-Fi和LwIP初始化,绑定station或AP。
- 配置Wi-Fi模式为station模式,然后启动Wi-Fi。
- 进行Wi-Fi扫描,获取周围的热点详情,包括SSID、频道、信号强度、MAC地址等详细信息。
点击查看代码
#include <stdio.h>
#include <string.h>
#include "esp_log.h"
#include "nvs_flash.h"
#include "esp_wifi.h"
// https://docs.espressif.com/projects/esp-idf/zh_CN/v4.4.3/esp32/api-guides/wifi.html
void app_main(void)
{
ESP_LOGI("WIFI", "0.初始化NVS存储");
nvs_flash_init();
ESP_LOGI("WIFI", "1.Wi-Fi/LwIP 初始化阶段");
esp_netif_init();
esp_event_loop_create_default();
// 创建有 TCP/IP 堆栈的默认网络接口实例绑定 station 或 AP。
esp_netif_create_default_wifi_sta();
wifi_init_config_t wifi_config = WIFI_INIT_CONFIG_DEFAULT();
esp_wifi_init(&wifi_config);
ESP_LOGI("WIFI", "2.Wi-Fi 配置阶段");
esp_wifi_set_mode(WIFI_MODE_STA);
ESP_LOGI("WIFI", "3.Wi-Fi 启动阶段");
esp_wifi_start();
ESP_LOGI("WIFI", "4.WIFI扫描");
wifi_country_t config_country = {.cc = "CN", .schan = 1, .nchan = 13, .policy = WIFI_COUNTRY_POLICY_AUTO};
esp_wifi_set_country(&config_country);
wifi_scan_config_t config_scan = {.show_hidden = true};
esp_wifi_scan_start(&config_scan, true);
// 方式1:获取扫描到的AP数量
uint16_t ap_num = 0;
ESP_ERROR_CHECK(esp_wifi_scan_get_ap_num(&ap_num));
ESP_LOGI("WIFI", "扫描到的AP数量: %d", ap_num);
// 方式2:获取扫描到的AP数量
uint16_t max_aps = 20;
wifi_ap_record_t ap_records[max_aps];
// 初始化结构体数组
memset(ap_records, 0, sizeof(ap_records));
uint16_t ap_count = max_aps;
ESP_ERROR_CHECK(esp_wifi_scan_get_ap_records(&ap_count, ap_records));
ESP_LOGI("WIFI", "获取到的AP数量: %d", ap_count);
printf("%30s %s %s %s \n", "SSID", "频道", "强度", "MAC地址");
for (size_t i = 0; i < ap_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]);
}
}
- 输出效果演示
FreeRTOS
在上一个示例的基础上,我们需要先初始化ESP32的NVS存储,使用nvs_flash_init()和nvs_flash_erase()等API进行初始化,这时可以得到一个NVS空间用来存储需要的配置信息,例如Wi-Fi的网络设置等。此外,还需要把esp_wifi_init()放在初始化ESP32的网络适配器esp_netif_init()和默认事件循环esp_event_loop_create_default()之后,并且用esp_netif_create_default_wifi_sta()来创建一个默认的Wi-Fi供应器,这样才能确保Wi-Fi网络设置能够正确的被传递,从而完成Wi-Fi的初始化过程。
然后就可以在ESP32上使用FreeRTOS进行任务分配了。使用xTaskCreate()函数创建应用任务“App Task”。在App Task中,我们可以使用esp_event_handler_register()注册Wi-Fi事件到事件句柄,来监听Wi-Fi的一些事件,比如连接成功事件,从而避免应用程序一直等待Wi-Fi连接完成。然后,使用vTaskDelay()函数控制任务延迟,控制函数的用时,从而实现应用程序的流程控制。
总的来说,FreeRTOS在ESP32上的使用可以极大的提高开发效率和程序稳定性,让开发者可以实现复杂的应用程序功能,快速稳定的嵌入ESP32开发平台中。
点击查看代码
#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"
void wifi_scan_task(void *pt)
{
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));
vTaskDelete(NULL);
}
void wifi_scan_show(void *pt)
{
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);
}
void run_on_event(void *handler_arg, esp_event_base_t base, int32_t id, void *event_data)
{
ESP_LOGE("EVENT_HANDLE", "BASE:%s, ID:%d", base, id);
switch (id)
{
case WIFI_EVENT_STA_START:
ESP_LOGE("EVENT_HANDLE", "WIFI_EVENT_STA_START");
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");
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 创建完成");
esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, run_on_event, NULL);
while (1)
{
// ESP_LOGI("APP_TASK", "APP Task 无聊的运行中");
vTaskDelay(1000 / portTICK_PERIOD_MS);
}
}
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);
}
}
Event Group
Event Group 程序实例
点击查看代码
/*
通过Event Group 来实现,任务之间的Event通知。
Task2 执行完自己的秘密任务后,通知Task1,然后Task1执行自己的任务
Task3 是用来验证,在通过xEventGroupWaitBits的时候CPU进入阻塞状态是不消耗CPU的。
*/
#include <stdio.h>
#include "esp_log.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
static EventGroupHandle_t s_wifi_event_group;
#define SECRET_TASK BIT23
void task1(void *pt)
{
ESP_LOGE("TASK1", "TASK1 创建完毕");
while (1)
{
ESP_LOGE("TASK1", "等待task2的把重要的事情做完");
xEventGroupWaitBits(s_wifi_event_group,
SECRET_TASK,
pdFALSE,
pdFALSE,
portMAX_DELAY);
ESP_LOGE("TASK1", "终于轮到我了。。。。");
vTaskDelete(NULL);
}
}
void task2(void *pt)
{
ESP_LOGI("TASK2", "TASK2 创建完毕");
while (1)
{
ESP_LOGI("TASK2", "TASK2 假装在做很重要的事情,大约需要5秒");
vTaskDelay(5000 / portTICK_PERIOD_MS);
xEventGroupSetBits(s_wifi_event_group, SECRET_TASK);
vTaskDelete(NULL);
}
}
void task3(void *pt)
{
ESP_LOGI("TASK3", "TASK3 创建完毕");
while (1)
{
ESP_LOGI("TASK3", "其他任务阻塞,CPU归我了~");
vTaskDelay(500 / portTICK_PERIOD_MS);
}
}
void app_main(void)
{
ESP_LOGW("MAIN", "Event Group Bits : %d bits", configUSE_16_BIT_TICKS ? 8 : 24);
s_wifi_event_group = xEventGroupCreate();
xTaskCreate(task1, "task1", 1024 * 12, NULL, 1, NULL);
xTaskCreate(task2, "task2", 1024 * 12, NULL, 1, NULL);
//xTaskCreate(task3, "task3", 1024 * 12, NULL, 1, NULL);
}
引入FreeRTOS的Event Group 事件标志组来讲上节课的我们创建的3个任务合并起来。
可以简单的把Event Group想成一个全局的变量, FreeRTOS 任务使用这个全局变量来互相沟通的。
点击查看代码
/*
这节课中,我们在ESP32 event loop handler中使用了freeRtos Event Group 来取代上节课的xTaskCreate
注意: Event Loop 是 乐鑫的东西, Event Group是FreeRTOS的东西,他们是完全不同的两个东西
*/
#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"
#include "freertos/event_groups.h"
static EventGroupHandle_t s_wifi_event_group;
#define STA_START BIT0
#define SCAN_DONE BIT1
void run_on_event(void *handler_arg, esp_event_base_t base, int32_t id, void *event_data)
{
ESP_LOGE("EVENT_HANDLE", "BASE:%s, ID:%d", base, id);
switch (id)
{
case WIFI_EVENT_STA_START:
ESP_LOGE("EVENT_HANDLE", "WIFI_EVENT_STA_START");
xEventGroupSetBits(s_wifi_event_group, STA_START);
break;
case WIFI_EVENT_SCAN_DONE:
ESP_LOGE("EVENT_HANDLE", "WIFI_EVENT_SCAN_DONE");
xEventGroupSetBits(s_wifi_event_group, SCAN_DONE);
break;
default:
break;
}
}
void app_task(void *pt)
{
ESP_LOGI("APP_TASK", "APP Task 创建完成");
esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, run_on_event, NULL);
while (1)
{
xEventGroupWaitBits(s_wifi_event_group,
STA_START,
pdFALSE,
pdFALSE,
portMAX_DELAY);
ESP_LOGE("APP_TASK", "接收到了STA START事件, 可以运行AP Scan了");
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));
xEventGroupWaitBits(s_wifi_event_group,
SCAN_DONE,
pdFALSE,
pdFALSE,
portMAX_DELAY);
ESP_LOGE("APP_TASK", "接收到了SCAN DONE事件, 可以打印出AP扫描结果了");
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);
}
}
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", "创建App Task 和 FreeRTOS Event Group");
s_wifi_event_group = xEventGroupCreate();
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);
}
}
Event Loop
为了区分 FreeRTOS的 Event Group 和 乐鑫的 Event Loop 这两个概念,
通过具体形象的夜市吃烧烤喝啤酒,来给大家形象的讲解Event Loop诞生的初衷和代码实现
点击查看代码
#include <stdio.h>
#include "esp_event.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_log.h"
#include <string.h>
esp_event_loop_handle_t night_market_loop_handler;
esp_event_base_t XINJIANG_BASE = "新疆餐厅";
typedef enum {
BBQ_EVENT_LAMB_SKEWERS_SPICY = 0,
BBQ_EVENT_LAMB_SKEWERS_NOT_SPICY,
BBQ_EVENT_HOT_PACKET,
BBQ_EVENT_BAKED_BAOZI,
BBQ_EVENT_THIN_SKIN_BAOZI,
BBQ_EVENT_FROZEN_BEER
} bbq_event_t;
// typedef enum {
// 羊肉串_辣 = 0,
// 羊肉串_不辣,
// 热囊,
// 烤包子,
// 薄皮包子,
// 冰冻啤酒
// } bbq_event_t;
void consumer_event_handle(void *handler_arg, esp_event_base_t base, int32_t id, void *event_data)
{ char * msg_from_booth = (char*) event_data;
char * msg_from_consumer = (char*) handler_arg;
ESP_LOGE("EVENT_HANDLE", "顾客:%s 摊位:%s, 事件:%li, 老板说:%s", msg_from_consumer, base, id,msg_from_booth);
}
void consumer_add_task(void *pt)
{
ESP_LOGE("CONSUMER_TASK", "来了一个吃货");
char * handle_arg = "我是个大胃王,爱吃辣";
esp_event_handler_register_with(night_market_loop_handler, XINJIANG_BASE, BBQ_EVENT_LAMB_SKEWERS_SPICY, consumer_event_handle, handle_arg);
esp_event_handler_register_with(night_market_loop_handler, XINJIANG_BASE, BBQ_EVENT_FROZEN_BEER, consumer_event_handle, handle_arg);
while(1) {
vTaskDelay(1000/portTICK_PERIOD_MS);
}
}
void booth_xinjiang_task(void *pt)
{
ESP_LOGE("BOOTH_TASK", "新疆饭店开张了");
while(1) {
vTaskDelay(5000/portTICK_PERIOD_MS);
char * event_data = "这次肥肉比较多,不好意思哦";
ESP_LOGE("新疆饭店", "BBQ_EVENT_BAKED_BAOZI好了");
esp_event_post_to(night_market_loop_handler, XINJIANG_BASE, BBQ_EVENT_BAKED_BAOZI, event_data,strlen(event_data)+1, portMAX_DELAY);
vTaskDelay(5000/portTICK_PERIOD_MS);
ESP_LOGE("新疆饭店", "BBQ_EVENT_LAMB_SKEWERS_SPICY");
event_data = "变态辣, 吃进医院不负责哦";
esp_event_post_to(night_market_loop_handler, XINJIANG_BASE, BBQ_EVENT_LAMB_SKEWERS_SPICY, event_data,strlen(event_data)+1, portMAX_DELAY);
vTaskDelay(5000/portTICK_PERIOD_MS);
ESP_LOGE("新疆饭店", "BBQ_EVENT_LAMB_SKEWERS_NOT_SPICY");
event_data = "一点辣味都没有,这有啥吃的呀";
esp_event_post_to(night_market_loop_handler, XINJIANG_BASE, BBQ_EVENT_LAMB_SKEWERS_NOT_SPICY, event_data,strlen(event_data)+1, portMAX_DELAY);
vTaskDelay(5000/portTICK_PERIOD_MS);
ESP_LOGE("新疆饭店", "BBQ_EVENT_FROZEN_BEER");
event_data = "超级冰, 都是冰渣子, 牙齿给你冻掉";
esp_event_post_to(night_market_loop_handler, XINJIANG_BASE, BBQ_EVENT_FROZEN_BEER, event_data,strlen(event_data)+1, portMAX_DELAY);
ESP_LOGE("新疆饭店", "新年提前收工了, 明年见");
vTaskDelete(NULL);
}
}
void app_main(void)
{
/*
课程开始前,我们先回顾一下
char_pointer - 指针指向的地址
%char_pointer - 指针自己的地址
sizeof(char_pointer) - 指针本身的大小
strlen(char_pointer) - 指针指向的char数组的大小,不包括最后的NULL
strlen(char_pointer)+1 - 指针指向的char数组的大小,包括最后的NULL
*/
char * char_pointer = "1234567890";
ESP_LOGI("main","char_pointer 内容: %s",char_pointer);
ESP_LOGI("main","char_pointer %p",char_pointer);
ESP_LOGI("main","&char_pointer %p",&char_pointer);
ESP_LOGI("main","sizeof(char_pointer) %d",sizeof(char_pointer));
ESP_LOGI("main","strlen(char_pointer) %d",strlen(char_pointer));
ESP_LOGE("MAIN","创建 Event Loop");
esp_event_loop_args_t night_market_loop_args = {
.queue_size = 5,
.task_name = "night_market_task",
.task_priority = uxTaskPriorityGet(NULL),
.task_stack_size = 1024*4,
.task_core_id = tskNO_AFFINITY,
};
ESP_ERROR_CHECK(esp_event_loop_create(&night_market_loop_args, &night_market_loop_handler));
xTaskCreate(consumer_add_task, "consumer a", 1024 * 12, NULL, 1, NULL);
xTaskCreate(booth_xinjiang_task, "xinjiang bbq", 1024 * 12, NULL, 1, NULL);
vTaskDelete(NULL);
}