下面的内容编写时间跨度有点大,乱了得一团,也没ai整理。食之无味,弃之可惜。

推荐笔记:ESP32 之 ESP-IDF 教学(十八)—— 组件配置(KConfig)
推荐笔记:Kconfig 拓展
乐鑫组件库,网页在线。

一、准备工程

  • 先重新弄一个工程,也算是复习一下上一节课的内容。这次换一种方式创建。

在这里插入图片描述

  • 选择模板

在这里插入图片描述

  • 最后结果如下图. 编译下载监听调试都没有问题。再开始下一步。

在这里插入图片描述

二、添加或创建组件

1) 添加组件

  • 乐鑫官方有一个在线库,可以方便 添加组件 ,使用以下指令打开主页。
ESP-IDF: 乐鑫组件注册表 
ESP-IDF: Show ESP Component Registry
  • 添加 点灯组件 led_strip 和 按钮组件 button ,注意版本,不同版本直接差别可能较大!!!
  • 两个组件的官方介绍页面为:LED 指示灯 和 按键 。

在这里插入图片描述

  • 官方组件添加很方便,直接下载即可。编译没有问题。
  • 虽然只添加了两个组件,但是下载了三个,其中一个应该是依赖,被一同下载了。
  • 官方组件是不允许修改的,每次编译都会检查和确保哈希值。一般创建自己的组件,然后依赖,在其基础上实现功能或改动。应该是不建议直接复制一份然后修改

在这里插入图片描述

2) 创建组件

  • 下面使用vscode的一键 创建组件 功能,快速弄两个模板组件。

在这里插入图片描述

  • 如何就可以看到大致结构如下,创建两个组件实现对提示灯和按键的测试或调用。
  • 创建多一些测试文件,最后结构如下:

在这里插入图片描述

自动创建的 .h 头文件居然没有 ifndef 宏定义保护。我个人还是喜欢加保护。这样以防万一。在个人工程里,嵌套调用还是很频繁的。

  • 往代码里填写一些测试内容,按钮的测试内容如下,闪灯的内容类似。
  • 注意 CMakeLists.txt 简单理解,添加编译路径,指定参与编译的文件。
/* 以下是 CMakeLists.txt 内容 */
idf_component_register(SRCS "button_test.c" "examples/button_examples.c" INCLUDE_DIRS "include") 
// 因为 CMakeLists.txt 中没有添加 examples 文件路径, 所以下面使用相对路径/* 以下是 button_examples.c 内容 */
#include <stdio.h>
#include "button_examples.h"
#include "esp_log.h"static const char *TAG = "button_examples.c";void button_examples_func(void)
{ESP_LOGI(TAG, "button_examples_func Start!");}/* 以下是 button_test.c 内容 */
#include <stdio.h>
#include "button_test.h"
#include "examples/button_examples.h" // 注意这里是使用了相对路径 
#include "esp_log.h" // 组件默认包含了 esp-idf 库, 直接引用static const char *TAG = "button_test.c";void button_test_func(void)
{ESP_LOGI(TAG, "button_test_func Start!");button_examples_func();
}/* 以下是 main.c 内容 */
#include <stdio.h>
#include "esp_log.h"#include "led_test.h"
#include "button_test.h"
// #include "examples/button_examples.h" 无法导入 button_examples.h 文件,起到隔离保护作用const char *TAG = "main.c";void app_main(void)
{ESP_LOGI(TAG, "app_main Start!");led_test_func();button_test_func();
}/* 编译运行监听内容如下 */
I (236) main_task: Started on CPU0
I (246) main_task: Calling app_main()
I (246) main.c: app_main Start!
I (246) led_test.c: led_test_func Start!
I (246) led_examples.c: led_examples_func Start!
I (256) button_test.c: button_test_func Start!
I (256) button_examples.c: button_examples_func Start!
I (266) main_task: Returned from app_main()

四、组件路径依赖

本文只介绍 ESP-IDF 推荐的规范格式,有一些非规范的操作也可以灵活实现目的,并不推荐也不介绍

1) 组件路径/目录

  • ESP-IDF 默认仅从以下位置查找组件:

    • $IDF_PATH/components/(ESP-IDF 内置组件,如 driveresp_wifi 等)
    • $PROJECT_PATH/components/(当前项目的 components 目录)
    • $PROJECT_PATH/managed_components/(当前项目的 managed_components 目录)
  • 有一些第三方组件(开发板的驱动),不合适重复放在工程中,也不能放在 ESP-IDF安装目录里,就可以在 CMakeLists.txt 中显式设置 EXTRA_COMPONENT_DIRS ,该定义默认是空,不会添加任何额外的组件目录。

# ⭐ 必须在 项目根目录的 CMakeLists.txt 中设置
cmake_minimum_required(VERSION 3.5)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)  # 必须放在 set 之前list(APPEND EXTRA_COMPONENT_DIRS     	# 额外组件路径(可以是绝对路径或相对于项目目录的路径)# "../shared_components"         	# 上级目录的共享组件# "C:/your/custom_components"   	# 绝对路径组件目录
)# ⭐ EXTRA_COMPONENT_DIRS 必须在这里设置(在 project() 之前)
project(hello_component)  # 初始化 ESP-IDF 项目
  • 重名组件会被替换,优先级从小到大,和局部变量类似。
  • 初始编译时所有组件都会被编译,所以需要很久

2) 组件依赖

  • 重点:永远通过组件名而非路径建立依赖关系,这是 ESP-IDF 模块化设计的核心原则!
  • 组件之间的依赖通过 CMakeLists.txt 修改。
  • 例如上例中,按钮组件依赖闪灯组件,就可以导入闪灯组件的头文件,调用函数。
idf_component_register(SRCS "led_test.c" // 单独指定每一个参与编译的 .cINCLUDE_DIRS "include" // 只限定对外开放 这个文件夹内的头文件# REQUIRES # button_test  # 明确依赖的组件名(非路径)PRIV_REQUIRES button_test  # 仅当前组件内部使用,对外不可见# "$($ENV{IDF_TARGET})"  # 根据目标芯片选择依赖,相当于可配置更改)            
  • 头文件不添加在 INCLUDE_DIRS : 用相对路径,作用域仅限于当前组件内部。
  • 头文件添加在 INCLUDE_DIRS : 将路径变为公共 API,允许跨组件直接引用。
  • 黄金法则最小化暴露原则——仅将必要的头文件路径加入 INCLUDE_DIRS,内部实现细节用相对路径隔离
  • 为什么 .c 文件需要逐个指定? .c 文件在编译时会经历以下过程:
    • 编译(Compile):每个 .c 文件都会独立编译成对象文件(.o)。
    • 链接(Link):所有 .o 文件合并生成最终的库或固件。
  • 因此需要 显式列出每个 .c 文件;
    • 避免误编译:确保只编译需要参与构建的源文件(而不是目录下所有文件)。
    • 精确控制依赖:可以针对特定 .c 文件设置编译选项(如 CFLAGS)。
    • 构建系统优化:仅重新编译修改过的 .c 文件。

五、菜单配置项

问DS:为什么esp中,有Kconfig和Kconfig.projbuild两种不同的格式?

在 ESP-IDF 开发框架中,KconfigKconfig.projbuild 是两种不同用途的配置文件格式,它们的主要区别在于 作用范围设计目的。以下是详细解释:


1. Kconfig(组件级配置)

  • 作用对象:用于 单个组件(Component) 内部的配置。
  • 功能:定义组件自身需要的可配置选项(如硬件参数、功能开关等)。
  • 文件位置:位于组件的根目录(如 components/your_component/Kconfig)。
  • 特点
    • 仅在组件的编译过程中生效。
    • 选项对其他组件不可见(除非显式暴露)。
    • 遵循 ESP-IDF 的组件隔离原则,保证模块化。

示例场景
比如一个 SPI 驱动组件可能需要配置默认时钟频率,此时会在 Kconfig 中定义:

   config SPI_CLOCK_SPEEDint "SPI clock speed (Hz)"default 1000000helpSet the SPI master clock frequency.

2. Kconfig.projbuild(项目级全局配置)

  • 作用对象:影响 整个项目多个组件 的全局配置。
  • 功能:覆盖或扩展项目范围的配置(如 SDK 工具链选项、系统级参数)。
  • 文件位置:可存在于组件目录或项目根目录(优先级高于普通 Kconfig)。
  • 特点
    • 配置选项会直接出现在顶层 menuconfig 菜单中。
    • 可能破坏组件隔离性,需谨慎使用。
    • 通常用于硬件适配或特殊需求(如切换目标芯片型号)。

示例场景
项目需要强制指定所有组件的日志级别,可以在 Kconfig.projbuild 中:

   config LOG_DEFAULT_LEVELint "Global log level"default 3range 0 4

关键区别总结

特性KconfigKconfig.projbuild
作用范围组件内部整个项目全局
使用场景组件私有配置跨组件或系统级配置
隔离性严格隔离可能影响其他组件
推荐使用频率高频(标准做法)低频(特殊需求)

为什么设计两种格式?

  1. 模块化需求
    ESP-IDF 强调组件化开发,Kconfig 确保每个组件的配置独立,避免命名冲突。

  2. 灵活性的平衡
    Kconfig.projbuild 为特殊场景(如硬件适配、全局优化)提供“后门”,但需手动启用。

  3. 优先级控制
    当两者冲突时,Kconfig.projbuild 的配置会覆盖普通 Kconfig,方便项目定制。


最佳实践建议

  • 优先使用 Kconfig:保持组件解耦。
  • 慎用 Kconfig.projbuild:仅在需要全局覆盖时使用,并添加详细注释说明。
  • 命名约定:在组件中避免定义全局选项(如以 CONFIG_ 开头的选项应谨慎)。

通过这种设计,ESP-IDF 实现了配置的灵活性和模块化的平衡。


  • 修改 Kconfig 文件,一定要删除 build 文件才会同步 sdkmenuconfig 菜单,否则最多只是刷新了宏定义,不会刷新菜单选项。
  • 尝试修改例程,添加以下测试代码。分别添加全局和组件配置,然后刷新菜单。就能看到宏定义被创建,菜单也出现选项。
/* main/Kconfig.projbuild 文件内容 */
menu "Example Configuration main.c"config MAIN_TESTint "main.c test"range 10 3600000default 1000helpDefine the main test.endmenu/* components/button_test/Kconfig 文件内容 */
menu "Example Configuration button.c"config BUTTON_TESTint "button.c test"range 10 3600000default 1000helpDefine the button test.endmenu/* components/led_test/Kconfig 文件内容 */
menu "Example Configuration led.c"config LED_TESTint "led.c test"range 10 3600000default 1000helpDefine the led test.endmenu
  • main 配置菜单出现在一级菜单,而组件配置菜单位于 Component config 下面的二级菜单。
  • 如果希望本地组件的菜单在 main 菜单下面,可以修改为以下内容。可以输入中文,但终端显示错位,VSCode 中就能显示正常。
menu "Example Configuration main.c"rsource "../components/button_test/Kconfig" # 相对路径rsource "../components/led_test/Kconfig"config MAIN_TESTint "main.c test 中文" # 名字 range 10 3600000default 1000helpmain.c test 中文. # 帮助endmenu

在这里插入图片描述

在这里插入图片描述


问 DS:sourcersourceorsource 的区别?
以下内容貌似瞎说的,我试了而一下觉得路径没成功,相对路径成功了。而另一个工程使用source搭配相对路径也成功了。所以有点疑惑。

在 Kconfig 系统中,sourcersourceorsource 是用于导入其他 Kconfig 文件的命令,但它们的行为和用途有所不同。以下是它们的详细解释和区别:


1. source

  • 功能:从指定的路径导入另一个 Kconfig 文件。
  • 路径解析规则
    • 绝对路径:直接使用给定的路径(如 source "/path/to/Kconfig")。
    • 相对路径:路径是**相对于 $srctree(源码根目录)**解析的,而不是当前文件所在目录。
  • 典型用途
    用于导入项目中或 ESP-IDF 内置的组件 Kconfig 文件。
  • 失败行为
    如果文件不存在,会报错并终止解析(如你遇到的问题)。

2. rsource

  • 功能相对路径导入(Relative-source),路径是相对于当前 Kconfig 文件所在目录解析的。
  • 路径解析规则
    相对路径基于当前文件的位置,而非 $srctree
    (这是与 source 的关键区别!)
  • 典型用途
    当需要从当前组件目录中导入子模块的 Kconfig 文件时。
  • 失败行为
    文件不存在时会报错。

3. orsource

  • 功能可选导入(Optional-source),如果文件不存在,则静默忽略,不会报错。
  • 路径解析规则
    source 相同(相对于 $srctree)。
  • 典型用途
    导入可能不存在的可选配置文件,避免因文件缺失导致构建失败。
  • 失败行为
    文件不存在时不会报错。

三者的对比总结

命令路径解析基准文件不存在时的行为典型场景
source$srctree报错并终止强制依赖的组件或核心配置
rsource当前文件目录报错并终止组件内部的子模块配置
orsource$srctree静默忽略可选的自定义或平台特定配置

  • 最后,如果修改了配置文件,为了避免每次重复配置,可以使用指令 idf.py save-defconfig
    保 存当前的已修改配置,留作下次使用。
# This file was generated using idf.py save-defconfig. It can be edited manually.
# Espressif IoT Development Framework (ESP-IDF) 5.4.1 Project Minimal Configuration
#
CONFIG_IDF_TARGET="esp32s3"
CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y
CONFIG_BUTTON_TEST=999
CONFIG_LED_TEST=666
CONFIG_MAIN_TEST=555

六、实战

  • 将组件的示例内容实现,路径类似:managed_components\espressif__button\test_apps\main。里面有多个例子,拷贝出来进行仿制,然后对组件进行二次打包,作为个人组件方便调用。搭配 Kconfig 配置就更加规范了。

在这里插入图片描述

  • 提一句按钮的使用,单个按键没啥好讲的,主要是adc按键,使用 excel 表格方便计算,举例3000mV,分成5个按钮。
  • 参考例程给的思路,分成 n+1,已知所需电压,假设上拉电阻R0,计算理论R1~R5,然后查电阻本寻找合适的电阻,然后再计算实际触发电压,然后编写注册按钮的程序。

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/news/912740.shtml
繁体地址,请注明出处:http://hk.pswp.cn/news/912740.shtml
英文地址,请注明出处:http://en.pswp.cn/news/912740.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Java_EE】单例模式、阻塞队列、线程池、定时器

目录 单例模式 饿汉模式<代码> 懒汉模式<代码> 阻塞队列 阻塞队列概念 阻塞队列解决的问题 阻塞队列工作原理 阻塞队列的优/缺点 优点 缺点 模拟实现阻塞队列<代码> 线程池 线程池概念 线程池解决的问题 线程池参数 四种拒绝策略 线程池工作…

Redis初识第七期---ZSet的命令和应用场景

ZSet相较于Set来说&#xff0c;它又是有序的&#xff0c;这个有序指的就是我们通常意义上的有序了&#xff0c;ZSet内部中是按照升序来排序的。 排序规则&#xff1a;ZSet相较于Set来说&#xff0c;它内部引入了一个新的属性&#xff1a;分数&#xff08;Score&#xff09;&am…

Wps开放平台v5升级v7上传实体文件踩坑(Java使用restTemplate)

背景&#xff1a; 最近接到一个老项目需求&#xff0c;之前开发的WPS开放平台文件&#xff08;商密集成&#xff09;预览功能因为升级需要重新对接api&#xff0c;新的上传文件接口踩坑特意记录一下。 这里出问题的是第二步&#xff0c;请求文件上传信息 踩坑代码 调用后403 p…

啥时候上RAG?啥时候上微调?丨实战笔记

哈喽&#xff0c;大家好&#x1f44f; 我是阿星&#xff01; 现在很多AI科普文章都会提到微调&#xff0c;RAG。 但是没有实战的过的同学可能会问&#x1f914;—— 啥时候用RAG&#xff1f;啥时候用微调呢&#xff1f;有啥区别&#xff1f;不都是让模型增加知识面的吗&…

RabbitMQ-基础篇

前言&#xff1a; 今天开始学RabbitMQ,还是跟着黑马的课程。 今日所学&#xff1a; RabbitMQ介绍RabbitMQ入门Java客户端中的MQ 1.RabbitMQ介绍 1.1 什么是RabbitMQ RabbitMQ 是一个开源的消息代理软件&#xff08;消息队列中间件&#xff09;&#xff0c;实现了高级消息…

docker-compose配置redis哨兵详细步骤和配置文件

docker-compose配置redis哨兵详细步骤和配置文件 目录结构调整 redis-cluster/ ├── config/ │ ├── master.conf # 主节点配置 │ ├── slave1.conf # 从节点1配置 │ ├── slave2.conf # 从节点2配置 │ ├── sentinel1.…

多模态大语言模型arxiv论文略读(146)

Exploring Response Uncertainty in MLLMs: An Empirical Evaluation under Misleading Scenarios ➡️ 论文标题&#xff1a;Exploring Response Uncertainty in MLLMs: An Empirical Evaluation under Misleading Scenarios ➡️ 论文作者&#xff1a;Yunkai Dang, Mengxi G…

【教程】Linux中限制用户可以使用的GPU数量 | 附脚本

转载请注明出处&#xff1a;小锋学长生活大爆炸[xfxuezhagn.cn] 如果本文帮助到了你&#xff0c;欢迎[点赞、收藏、关注]哦~ 目录 背景说明 设置方法 管理脚本 进阶限制 恢复默认组 注意事项 背景说明 比较简单的方式是使用group来管理权限&#xff0c;这种方式能限制哪些…

90.xilinx复位低电平(一般使用低电平复位)

Xilinx FPGA 中的寄存器&#xff08;Flip-Flop&#xff09;**确实支持异步复位**&#xff0c;但具体实现方式取决于你使用的设计方法&#xff08;HDL 代码风格或原语实例化&#xff09;。以下是详细说明&#xff1a; --- ### 1. **Xilinx 寄存器的复位特性** - **同步复位…

NVMe高速传输之摆脱XDMA设计10: DMA 控制单元设计

DMA 控制单元负责控制 DMA 传输事务&#xff0c; 该单元承担了 DMA 事务到 NVMe 事务的转换任务&#xff0c; 使用户对数据传输事务的控制更加简单快捷。 DMA 控制功能由 DMA寄存器组实现。 DMA 寄存器组包含 DMA 操作寄存器、 DMA 长度寄存器、 DMA 源目的地址寄存器和 DMA 状…

如何设置电脑定时休眠?操作指南详解

长时间运行电脑会导致硬件过热&#xff0c;缩短其使用寿命。定时关机有助于让硬件得到休息&#xff0c;降低因长时间高负荷工作导致损坏的风险。 它的界面简洁直观&#xff0c;功能却十分实用&#xff0c;涵盖了定时关机、重启、注销、休眠、待机以及锁定等多种操作。 以设置“…

LeetCode[617]合并二叉树

思路&#xff1a; 我们合并左右子树&#xff0c;在递归左右子树的时候&#xff0c;一定要保证左右子树不为空&#xff0c;如果左子树为空&#xff0c;那么直接返回右子树就行了&#xff0c;即使右子树为空。如果右子树为空那么直接返回左子树就行了&#xff0c;这样判断完就正常…

Redis 常用五大数据类型

1、Redis 关键字&#xff08;Key&#xff09; keys * 查看当前库所有keyexists [key] 判断某个key是否存在type [key] 查看当前key的数据类型del [key] 删除指定的key数据unlink [key] 根据value选择非阻塞删除&#xff0c;仅将keys从keyspace元数据中删除&#xff0c;真正的删…

大语言模型(LLM)专业术语汇总

1. 训练与部署 1.1 预训练 专业&#xff1a;在海量无标注文本&#xff08;如Common Crawl、Wikipedia&#xff09;上通过自监督学习训练基础语言模型&#xff0c;学习通用语言表征&#xff08;如GPT-3训练数据达45TB&#xff09;。通俗&#xff1a;AI的“通识教育阶段”&…

【Java Swing 图形界面编程】JList 列表组件 ① ( JList 组件简介 | 核心作用 | 关键特性 | 基础用法示例 )

文章目录 一、JList 组件简介1、JList 概念简介2、JList 核心作用3、JList 关键特性 二、JList 组件基础用法示例1、使用 String 数组构建列表项2、使用 Vector 集合构建列表项3、使用 DefaultListModel 构建列表项 一、JList 组件简介 1、JList 概念简介 基本概念 : JList 组件…

【小技巧】Python+PyCharm IDE 配置解释器出错,环境配置不完整或不兼容。(小智AI、MCP、聚合数据、实时新闻查询、NBA赛事查询)

报错信息如下&#xff1a; [unsupported] Python 3.1 (mcp-calculator-main) (3) C:\Users(xsshu\AppData\Local\Programs\Python\Python313\python.exe [unsupported] Python 3.1 C:\Users\xsshu\AppData\Local\Programs\Python\Python311\python.exe 这条输出显示了两个 Pyth…

Ragflow 前后端登录逻辑

前端登录逻辑 路由配置&#xff1a; /login 路由指向 /pages/login 组件。登录表单使用 Ant Design 的 Form, Input, 和 Button 组件。 登录表单处理&#xff1a; 使用 useLogin钩子来处理登录请求。密码通过 RSA 加密后再发送到服务器。成功登录后导航至 /knowledge 页面。 …

基于图神经网络的ALS候选药物预测模型设计与实现

基于图神经网络的ALS候选药物预测模型设计与实现 一、任务背景与意义 肌萎缩侧索硬化症(ALS)是一种致命的神经退行性疾病,目前尚无有效治愈方法。传统药物发现流程耗时长、成本高,而人工智能技术为加速药物发现提供了新途径。本文设计并实现了一个基于图神经网络(GNN)的…

运维打铁: 数据加密与备份恢复策略制定

文章目录 思维导图一、数据加密1. 加密算法选择AES 加密示例&#xff08;Python&#xff09;RSA 加密示例&#xff08;Python&#xff09; 2. 密钥管理3. 加密范围 二、数据备份1. 备份类型全量备份增量备份差异备份 2. 备份频率3. 备份存储位置 三、数据恢复1. 恢复测试2. 恢复…

AIbase MCP服务库上线:集成服务器、客户端、案例教程等服务

在当今数字化时代&#xff0c;人工智能技术正以前所未有的速度发展&#xff0c;深刻地改变着我们的生活和工作方式。而要充分发挥AI的强大能力&#xff0c;离不开高效的工具和服务支持。今天&#xff0c;就让我们来了解一下一个专注于MCP&#xff08;Model Context Protocol&am…