当前位置: 首页 > news >正文

esp32-idf框架学习笔记/教程

esp32型号:

环境搭建

安装:就按这个来,别的试了好多次都不行,这个一次成功!!!!

vscode下ESP32开发环境配置(100%成功)_哔哩哔哩_bilibili

esp芯片的两种模式:

ESP32 固件烧录教程_哔哩哔哩_bilibili

1.运行模式

2.下载模式

esp32s3程序下载

1.数据线插在TTL的那个口,下载过程中不用按什么按键

2.

3.点击小火花一键编译下载

ESP32的启动流程

ESP32_freeRTOS教程三:系统启动流程_哔哩哔哩_bilibili

注意:app_main()是在一个任务中被调用的,它是任务的一部分,与所以里面没有死循环,在执行app_main()之前就开启了任务调度器了

任务的创建与删除

实验现象:首先创建my_task任务,系统会输出十次my_task1这个任务的最小剩余堆栈大小,之后调用vTaskDelete()删除m_task1这个任务

#include <stdio.h>
#include <inttypes.h>
#include "sdkconfig.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_chip_info.h"
#include "esp_flash.h"
#include "esp_system.h"
void my_task1(void *param)
{while (1){UBaseType_t stack_remain = uxTaskGetStackHighWaterMark(NULL);//显示及最小栈大小printf("Stack remaining: %d\n", stack_remain);//fflush(stdout);  // 手动刷新缓冲区vTaskDelay(50);}
}
void app_main(void)
{TaskHandle_t my_task1_handle=NULL;xTaskCreate(my_task1, "my_task1", 3000, NULL, 3, &my_task1_handle);vTaskDelay(500);if(my_task1_handle!=NULL){vTaskDelete(my_task1_handle);}}

注意:gcc的printf默认需要换行符\n才会输出,或者等缓冲区满了才输出,keil没有这个问题

任务创建时的输入参数

传给任务的参数类型时void *类型,void *类型它可以接收任何类型,

传递整数型

#include <stdio.h>
#include <inttypes.h>
#include "sdkconfig.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_chip_info.h"
#include "esp_flash.h"
#include "esp_system.h"int num=9;
void my_task1(void *param)
{int *tem=(int *)param;while (1){printf("get num: %d\n", *tem);vTaskDelay(100);}
}
void app_main(void)
{TaskHandle_t my_task1_handle=NULL;xTaskCreate(my_task1, "my_task1", 3000, (void *)&num, 3, &my_task1_handle);
}

传递数组:

传递结构体

传递字符串: 

vTaskList()的使用

static char pcWriteBuffer[512]={0};vTaskList(pcWriteBuffer);printf("%s",pcWriteBuffer);

输出格式:

State表示:

 Stack表示:最小剩余的堆栈大小

#include <stdio.h>
#include <inttypes.h>
#include "sdkconfig.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_chip_info.h"
#include "esp_flash.h"
#include "esp_system.h"void my_task1(void *param)
{while (1){UBaseType_t stack_remain = uxTaskGetStackHighWaterMark(NULL);//显示及最小栈大小printf("my_task1 Stack: %d\n", stack_remain);//fflush(stdout);  // 手动刷新缓冲区vTaskDelay(500/portTICK_PERIOD_MS);}
}
void my_task2(void *param)
{while (1){UBaseType_t stack_remain = uxTaskGetStackHighWaterMark(NULL);//显示及最小栈大小printf("my_task2 Stack: %d\n", stack_remain);//fflush(stdout);  // 手动刷新缓冲区vTaskDelay(500/portTICK_PERIOD_MS);}
}
void app_main(void)
{TaskHandle_t my_task1_handle=NULL;TaskHandle_t my_task2_handle=NULL;xTaskCreate(my_task1, "my_task1", 3000, NULL, 10, &my_task1_handle);xTaskCreate(my_task2, "my_task2", 3000, NULL, 10, &my_task2_handle);static char pcWriteBuffer[512]={0};vTaskList(pcWriteBuffer);printf("%s",pcWriteBuffer);vTaskDelay(2000/portTICK_PERIOD_MS);}

看门狗

中断看门狗:

        当中断程序执行过长时间时可能会触发中断看门狗

任务看门狗:

        任务看被狗是今天重点;

使用任务看门狗需要包含头文件: #include "esp_task_wdt.h"

#include "esp_task_wdt.h"
void my_task1(void *param)
{//将任务添加到任务看门狗所监控的列表esp_task_wdt(NULL);while (1){//喂狗esp_task_wdt_reset();vTaskDelay(500 / portTICK_PERIOD_MS);}
}void app_main(void)
{TaskHandle_t my_task1_handle = NULL;xTaskCreate(my_task1, "my_task1", 3000, NULL, 1, &my_task1_handle);
}

点亮一颗LED 

led的引脚连接在了G19引脚 

#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"#define LED_GPIO GPIO_NUM_19void task_led(void *param)
{int gpio_level = 0;while(1){gpio_level=gpio_level?0:1;gpio_set_level(GPIO_NUM_19,gpio_level);vTaskDelay(pdMS_TO_TICKS(500));}}
void app_main(void)
{gpio_config_t led_cfg;led_cfg.pin_bit_mask=(1<<GPIO_NUM_19);led_cfg.mode=GPIO_MODE_OUTPUT;led_cfg.intr_type=GPIO_INTR_DISABLE;led_cfg.pull_down_en=GPIO_PULLDOWN_DISABLE;led_cfg.pull_up_en=GPIO_PULLUP_DISABLE;gpio_config(&led_cfg);xTaskCreatePinnedToCore(task_led,"task_led",3000,NULL,2,NULL,1);}

LEDC-(PWM) 

#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "driver/gpio.h"
#include "driver/ledc.h"#define LED_GPIO GPIO_NUM_19#define FULL_EV_BIT BIT0        //
#define EMPTY_EV_BIT BIT1static EventGroupHandle_t ledc_event_handle; // 修正变量名bool IRAM_ATTR ledc_flish_cb(const ledc_cb_param_t *param, void *user_arg) {BaseType_t xHigherPriorityTaskWoken = pdFALSE;if (param->event == LEDC_FADE_END_EVT) {if (param->duty == 0) {xEventGroupSetBitsFromISR(ledc_event_handle, EMPTY_EV_BIT, &xHigherPriorityTaskWoken);} else {xEventGroupSetBitsFromISR(ledc_event_handle, FULL_EV_BIT, &xHigherPriorityTaskWoken);}}portYIELD_FROM_ISR(xHigherPriorityTaskWoken);return (xHigherPriorityTaskWoken == pdTRUE);
}void task_led(void *param) {EventBits_t ev;while (1) {ev = xEventGroupWaitBits(ledc_event_handle, FULL_EV_BIT | EMPTY_EV_BIT, pdTRUE, pdFALSE, pdMS_TO_TICKS(5000));if (ev & FULL_EV_BIT) {ledc_set_fade_with_time(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0, 0, 2000);ledc_fade_start(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0, LEDC_FADE_NO_WAIT);}if (ev & EMPTY_EV_BIT) {ledc_set_fade_with_time(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0, 8191, 2000);ledc_fade_start(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0, LEDC_FADE_NO_WAIT);}}
}void app_main(void) {// 1. 初始化事件组ledc_event_handle = xEventGroupCreate();// 2. 配置LEDC定时器和通道ledc_timer_config_t timer_cfg = {.speed_mode = LEDC_LOW_SPEED_MODE,.timer_num = LEDC_TIMER_0,.duty_resolution = LEDC_TIMER_13_BIT,.freq_hz = 5000,.clk_cfg = LEDC_AUTO_CLK};ESP_ERROR_CHECK(ledc_timer_config(&timer_cfg));ledc_channel_config_t channel_cfg = {.speed_mode = LEDC_LOW_SPEED_MODE,.channel = LEDC_CHANNEL_0,.timer_sel = LEDC_TIMER_0,.intr_type = LEDC_INTR_DISABLE,.gpio_num = LED_GPIO,.duty = 0,.hpoint = 0};ESP_ERROR_CHECK(ledc_channel_config(&channel_cfg));// 3. 安装渐变功能并注册回调ledc_fade_func_install(0);ledc_cbs_t cbs = { .fade_cb = ledc_flish_cb };ledc_cb_register(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0, &cbs, NULL);// 4. 启动初始渐变ledc_set_fade_with_time(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0, 8191, 2000);ledc_fade_start(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0, LEDC_FADE_NO_WAIT);// 5. 创建任务xTaskCreatePinnedToCore(task_led, "task_led", 3000, NULL, 2, NULL, 1);
}

WS2812 

单个WS2812 

ws2812的0码和1码都是由高低电平组成的        

RES为复位电平:表示一帧数据传输结束

数据帧,RGB格式

 多个WS2812

通常情况下,电路中会有不止一个WS2812串联起来,串联方式如下

 

第一个灯的输出连接到第二个灯的输入引脚上,第二个灯的输出连接到第三个灯的输入引脚上,以此类推

那么任何才能控制每一个灯珠的颜色呢?

这就得益于ws2812的独特控制方式:当我们发生一个24位数据帧后,第一个ws2812会记录并且锁存起来,当我们发生第二个24位数据帧时,第一个ws2812内部以及锁存了数据,此时会将数据通过out引脚输出给第二个ws2812灯,第二个ws2812灯会录并且锁存起来,当我们发生第三个24位数据帧时继续向下递交数据,直到我们发生了一个rest信号,本次传输才会结束,后续发送的数据又会从第一个ws2812开始记录

WIFI 

WIFI模型:

AP:路由器,所有的设备和电脑通过ap热点进行数据交换

WIFI热点的启动流程

    wifi driver被启动之后, 会发送WIFI_EVENT_AP_START这个事件到event Task中,如果有处理这个事件的回调函数,就会再这个回调函数中进行处理; 如果有设备进行连接,就会发送WIFI_EVENT_AP_STACONNECTED这个事件到event Task, 之后再wifi_event_handler中进行处理(实例代码中只是打印了相应的信息)如果有断开连接的事件WIFI_EVENT_AP_STADISCONNECTED,也会发送到event Task,event Task调用wifi_event_handler进行处理

#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_mac.h"
#include "esp_wifi.h"
#include "esp_event.h"
#include "esp_log.h"
#include "nvs_flash.h"#include "lwip/err.h"
#include "lwip/sys.h"/* The examples use WiFi configuration that you can set via project configuration menu.If you'd rather not, just change the below entries to strings withthe config you want - ie #define EXAMPLE_WIFI_SSID "mywifissid"
*/
#define EXAMPLE_ESP_WIFI_SSID      CONFIG_ESP_WIFI_SSID
#define EXAMPLE_ESP_WIFI_PASS      CONFIG_ESP_WIFI_PASSWORD
#define EXAMPLE_ESP_WIFI_CHANNEL   CONFIG_ESP_WIFI_CHANNEL
#define EXAMPLE_MAX_STA_CONN       CONFIG_ESP_MAX_STA_CONNstatic const char *TAG = "wifi softAP";static void wifi_event_handler(void* arg, esp_event_base_t event_base,int32_t event_id, void* event_data)
{if (event_id == WIFI_EVENT_AP_STACONNECTED) {//有设备连接到我们的软件热点时会触发这个事件  wifi_event_ap_staconnected_t* event = (wifi_event_ap_staconnected_t*) event_data;ESP_LOGI(TAG, "station "MACSTR" join, AID=%d",MAC2STR(event->mac), event->aid);} else if (event_id == WIFI_EVENT_AP_STADISCONNECTED) {//断开连接时wifi_event_ap_stadisconnected_t* event = (wifi_event_ap_stadisconnected_t*) event_data;//打印断开设备的信息,如ipESP_LOGI(TAG, "station "MACSTR" leave, AID=%d, reason=%d",MAC2STR(event->mac), event->aid, event->reason);}
}void wifi_init_softap(void)
{//通过调用esp_netif_init()来启动LWIPtaskESP_ERROR_CHECK(esp_netif_init());//通过esp_event_loop_create_default()来启动时间task--eventtask ESP_ERROR_CHECK(esp_event_loop_create_default());esp_netif_create_default_wifi_ap();wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();//esp_wifi_init() 初始化WIFI driverESP_ERROR_CHECK(esp_wifi_init(&cfg));//4.对我们所需处理的一些事件注册了一个回调函数wifi_event_handlerESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT,ESP_EVENT_ANY_ID,&wifi_event_handler,NULL,NULL));//配置driverwifi_config_t wifi_config = {.ap = {.ssid = EXAMPLE_ESP_WIFI_SSID,//热点的名字.ssid_len = strlen(EXAMPLE_ESP_WIFI_SSID),.channel = EXAMPLE_ESP_WIFI_CHANNEL,.password = EXAMPLE_ESP_WIFI_PASS,//热点的密码.max_connection = EXAMPLE_MAX_STA_CONN,//热点的最大连接数目
#ifdef CONFIG_ESP_WIFI_SOFTAP_SAE_SUPPORT.authmode = WIFI_AUTH_WPA3_PSK,//授权的模式,登录的加密模式 .sae_pwe_h2e = WPA3_SAE_PWE_BOTH,
#else /* CONFIG_ESP_WIFI_SOFTAP_SAE_SUPPORT */.authmode = WIFI_AUTH_WPA2_PSK,
#endif.pmf_cfg = {.required = true,},},};if (strlen(EXAMPLE_ESP_WIFI_PASS) == 0) {wifi_config.ap.authmode = WIFI_AUTH_OPEN;}//使用esp_wifi_set_mode()对driver进行配置ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_AP));ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_AP, &wifi_config));//启动driverESP_ERROR_CHECK(esp_wifi_start());ESP_LOGI(TAG, "wifi_init_softap finished. SSID:%s password:%s channel:%d",EXAMPLE_ESP_WIFI_SSID, EXAMPLE_ESP_WIFI_PASS, EXAMPLE_ESP_WIFI_CHANNEL);
}
/*wifi driver被启动之后, 会发送WIFI_EVENT_AP_START这个事件到event Task中,如果有处理这个事件的回调函数,就会再这个回调函数中进行处理;如果有设备进行连接,就会发送WIFI_EVENT_AP_STACONNECTED这个事件到event Task,之后再wifi_event_handler中进行处理(实例代码中只是打印了相应的信息)如果有断开连接的事件WIFI_EVENT_AP_STADISCONNECTED,也会发送到event Task,event Task调用wifi_event_handler进行处理
*/
void app_main(void)
{//初始化存储空间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(TAG, "ESP_WIFI_MODE_AP");wifi_init_softap();
}

NVS分区:主要是保存一些配置参数,即使设备重启之后,NVS中的数据仍然可以保存,比如说wifi的ssid和密码 

socket编程流程 

TCP与UDP对比

TCP是基于连接的,是可靠的,但传输速度慢,UDP是不基于连接的, 不可靠,传输速度快

UDP可以进行广播和组播

UDP没有建立连接的过程,所有recvfrom()与sendto()这两个函数在发生数据的时候会包含IP地址等信息,而TCP的recv()与send()不包含IP地址等信息 

相关文章:

  • 甘特图实例 dhtmlxGantt.js
  • 前端状态管理介绍(React状态管理)(通过管理状态来控制UI的呈现,确保数据的一致性和可维护性)(界面与数据分离、可预测性、组件化、响应式更新)
  • table表格鼠标圈选数据并复制且自带html结构
  • React从基础入门到高级实战:React 基础入门 - JSX与组件基础
  • JAVA查漏补缺(2)
  • Ubuntu 上进行树莓派交叉编译
  • 跨域解决方案之JSONP
  • SQL实战之索引失效案例详解
  • 【机械视觉】Halcon—【二、Halcon算子全面介绍(超详细版)】
  • 基于Java(GUI)实现五子棋
  • 【ARM/RISCV 嵌入式 编译系列 16 -- GCC 进制优化编译的常用方法】
  • SQL进阶之旅 Day 1:高效表设计与规范
  • leetcode-快慢指针系列
  • FFTW图像处理之频域滤波和频域分析
  • 2025语音语聊系统源码开发深度解析:WebRTC与AI降噪技术如何重塑语音社交体验
  • 苍穹外卖07 缓存菜品缓存套餐 添加购物车
  • 电脑风扇转速不正常的原因
  • Python、PyTorch、TensorFlow和飞桨(PaddlePaddle)的核心介绍及对比
  • EtherNet IP到modbus TCP网关完成AGV系统的安全解决方案及应用
  • Day34 Python打卡训练营
  • onedrive 做网站静态/开封网络推广公司
  • wordpress建站镜像/提交网址给百度
  • 怎么做网赌网站/丁香人才网官方网站
  • 建设南大街小学网站/推广排名seo
  • win10做的网站其他电脑访问不了怎么办/上海高端网站定制
  • wordpress免费企业资讯主题/百度关键词优化工具