3.自定义工程目录配置CMakeLists
问题背景
熟悉stm32keil开发的都知道,我们在编写不同的外设时,通常都会单独编写一个app文件夹或者是user文件夹之类的来存放不同外设功能的源文件和头文件。
在前面一节2.构建第一个工程并烧录到ESP32开发板-CSDN博客中,我们是使用了一个乐鑫的官方所提供的一个hello world工程模板,这个工程里面我们表面上是用到了GPIO功能和USART功能,其他的一些功能我们暂时还没有用到,或者说暂时还没有包含其他功能模块。
那么如果我一开始使用了模板是generic_gpio这个模板工程,在项目设计的前期实现我只需要gpio功能就够了,所以我就直接使用的是generic_gpio模板,后来我有需要使用到定时器功能,可能generic_gpio模板里面并没有包含这个功能,我们难道再去打开一个timer外设的模板工程吗,显然是比较麻烦的。
虽然第二节我提到了我们一般会使用官方模板而不是自己新建一个空工程,但是那只是初期新建工程的时候是用官方模板,当我们新建工程完毕以后,我们需要对官方提供的模板进行修改,添加自己的文件目录以存放之后所使用的其他外设文件。因为官方的外设模板工程里面只有main文件夹下一个主函数的文件,我们总不可能把所有的外设实现函数统统写到这个主函数文件里面。
解决方案
事实上官方已经提前想到了这个问题,乐鑫官方对 components 路径的介绍:“可选的 “components” 目录中包含了项目的部分自定义组件,并不是每个项目都需要这种自定义组件,但它有助于构建可复用的代码或者导入第三方(不属于 ESP-IDF)的组件。或者,您也可以在顶层 CMakeLists.txt 中设置 EXTRA_COMPONENT_DIRS 变量以查找其他指定位置处的组件。有关详细信息,请参阅 重命名 main 组件。如果项目中源文件较多,建议将其归于组件中,而不是全部放在 “main” 中。
我们从官方的说明中可以获得两个方法来构建自己的工程文件
- 1 在顶层目录下的 components 路径下添加组件。
- 2 在顶层目录下的 CMakeLists.txt 中设置 EXTRA_COMPONENT_DIRS 变量以查找其他指定位置处的组件。
两种方法的实现原理:
我们观察顶层CMakeLists文件可以发现里面已有三行语句,其中第二行语句为include($ENV{IDF_PATH}/tools/cmake/project.cmake)
而配置项目、检索组件等任务都是 $ENV{IDF_PATH}/tools/cmake/project.cmake 决定的。
组件默认的搜索目录为 IDF_PATH/components、 PROJECT_DIR/components、和 EXTRA_COMPONENT_DIRS。
- ESP-IDF内部组件
IDF_PATH/components
- 扩展组件
EXTRA_COMPONENT_DIRS
- 项目组件
PROJECT_DIR/components
IDF_PATH/components 用于系统组件。我们一般不会将文件放在这里面。
PROJECT_DIR/components、和 EXTRA_COMPONENT_DIRS 对应上面两种添加组件的方法。
在 PROJECT_DIR/components 中添加组件
步骤:
- 首先新建 PROJECT_DIR/components 路径。
- 在PROJECT_DIR/components 中添加我们自定义的组件,比如我添加了 led_key
- 将组件相关的头文件和源文件放到 led_key中,并新建 CMakeLists.txt 文件。
- 在 CMakeLists.txt 中添加源文件与头文件的路径。格式为:
idf_component_register(SRCS "led_key.c"INCLUDE_DIRS "."REQUIRES driver)
相信前两个SRC和INCLUDE_DIRS都很好理解,分别是包含源文件和头文件的路径,那么后一个QEQUIRES到底是干什么的,为啥要后面跟上driver?
这里我先解释第一个问题,QEQUIRES可以理解为添加依赖。在说第二个问题之前我们先来看看现在的文件目录是个什么情况:
然后看下源文件和头文件里面的内容:
led_key.c
#include "led_key.h"void LED_Init(void)
{gpio_config_t io_config;io_config.intr_type = GPIO_INTR_DISABLE;io_config.mode = GPIO_MODE_OUTPUT;io_config.pin_bit_mask = 1<<2;io_config.pull_down_en = GPIO_PULLDOWN_DISABLE;io_config.pull_up_en = GPIO_PULLUP_DISABLE;gpio_config(&io_config);// esp_rom_gpio_pad_select_gpio (GPIO_NUM_2);// gpio_set_direction(GPIO_NUM_2,GPIO_MODE_OUTPUT);
}void KEY_Init(void)
{gpio_config_t io_config;io_config.intr_type = GPIO_INTR_POSEDGE;io_config.mode = GPIO_MODE_INPUT;io_config.pin_bit_mask = 1<<0;io_config.pull_down_en = GPIO_PULLDOWN_DISABLE;io_config.pull_up_en = GPIO_PULLUP_DISABLE;gpio_config(&io_config);
}void led_blink( void * pvParameters )
{while(1){gpio_set_level(GPIO_NUM_2,0);vTaskDelay(1000 / portTICK_PERIOD_MS);//FreeRTOS延时函数--毫秒级gpio_set_level(GPIO_NUM_2,1);vTaskDelay(1000 / portTICK_PERIOD_MS);}
}void gpio_isr_handler(void* arg)
{static int flag = 0;flag ^= 1;gpio_set_level(GPIO_NUM_2,flag);
}
led_key.h
#ifndef __LED_KEY__
#define __LED_KEY__#include "driver/gpio.h"#define ESP_INTR_FLAG_DEFAULT 0void LED_Init(void);
void KEY_Init(void);
void led_blink( void * pvParameters );
void gpio_isr_handler(void* arg);#endif
看完文件结构和文件内容之后,我们大体可以明白为什么要添加一个driver依赖了,因为我们在led_key.h里面包含了driver/gpio.h,而如果我们不去进行依赖的包含,在编译的时候就会报出这样的错误:
fatal error: driver/gpio.h: No such file or directory
这就是由于依赖问题没有解决导致,我们编写的led_key.h文件没有指定依赖,那么编译器将不知道去哪里找这个driver/gpio.h文件。
在自定义的 EXTRA_COMPONENT_DIRS 中添加组件
有时候我们不想用官方所提供的存放组件集的组件目录components,我们仍然希望创建单独的组件目录,这时候就需要在最顶层CMakeLists文件里面添加一语句用于设置外部组件的路径
# The following lines of boilerplate have to be in your project's CMakeLists
# in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.16)include($ENV{IDF_PATH}/tools/cmake/project.cmake)
set(EXTRA_COMPONENT_DIRS "./src")
project(myProject)
比方说我们创建了一个叫做src的外部组件,就需要在最顶层CMakeLists文件添加set(EXTRA_COMPONENT_DIRS "./src"),
创建自己存放组件集的组件目录,之后在组件目录下创建组件,不能直接创建组件目录,什么意思呢,就是我们要创建一个led的程序,需要在src下面再创建一个led的文件夹作为组件目录,再在led组件目录里面新建led.c源文件。src是一个组件集的目录。
接下来的操作就和在PROJECT_DIR/components 中添加组件的操作一样了。其实这样做无非是吧官方提供的组件集文件名字替换为了自己起的组件集名字,然后由于顶层CMakeLists默认包含components组件集所以不需要我们添加,而我们自己创建的非components组件集属于外部组件,那么就需要在顶层说明一下外部组件集的路径了。
相关文章:

3.自定义工程目录配置CMakeLists
问题背景 熟悉stm32keil开发的都知道,我们在编写不同的外设时,通常都会单独编写一个app文件夹或者是user文件夹之类的来存放不同外设功能的源文件和头文件。 在前面一节2.构建第一个工程并烧录到ESP32开发板-CSDN博客中,我们是使用了一个乐鑫…...

Vue3.0里为什么要用 Proxy API 替代 defineProperty API
一、Object.defineProperty 定义:Object.defineProperty() 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象 为什么能实现响应式 通过defineProperty 两个属性,get及set get 属性的 getter 函…...

c++初阶------类和对象(下)
作者前言 🎂 ✨✨✨✨✨✨🍧🍧🍧🍧🍧🍧🍧🎂 🎂 作者介绍: 🎂🎂 🎂 🎉🎉🎉…...

PMP考试:如何高效学习PMBOK?
PMBOK(项目管理知识体系指南)是PMP考试的核心教材,学习PMBOK对于备考PMP考试至关重要。那么我将分享一些高效学习PMBOK的方法和技巧,帮助同学们更好地掌握项目管理知识。 一、制定学习计划 在学习PMBOK之前,制定一个详…...

个人博客网站前端页面的实现
博客网站前端页面的实现 博客登录页 相关代码 login.html <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><…...
Kotlin Retrofit 网络请求
一、添加依赖: //Retrofit 网络请求implementation("com.squareup.retrofit2:retrofit:2.3.0")implementation("com.squareup.retrofit2:converter-gson:2.3.0")//json转换 二、创建单例类: package com.example.buju.httpimport …...
pyside6 pytq PyDracula QVideoWidget视频只有声音没有画面
解决方案: 先不使用框架,纯pyside6代码,如果添加视频有画面有声音,那可以排除是硬件问题,如果没有画面只有声音,可能是视频解码器无法解码,换个格式的视频文件如果只有使用PyDracula 出问题&am…...
Python爬网页,不确定网页的编码,不需要用第三方库
Python爬网页,不确定网页的编码,不需要用第三方库,自己写个判断,乱拳打死老师傅 detect试了,不好用 apparent_encoding试了,不好用 encoding试了,不好用 headers里get试了,不好用…...

Web测试的基础流程(外加测试过程需要的注意5点)
前言 在Web工程过程中,基于Web系统的测试、确认和验收是一项重要而富有挑战性的工作。基于Web的系统测试与传统的软件测试不同,它不但需要检查和验证是否按照设计的要求运行,而且还要测试系统在不同用户的浏览器端的显示是否合适。 重要的是…...

项目解决方案:视频监控接入和录像系统设计方案(下)
目 录 1.概述 2. 建设目标及需求 2.1建设总目标 2.2 需求描述 2.3 需求分析 3.设计依据与设计原则 3.1设计依据 3.2 设计原则 4.建设方案设计 4.1系统方案设计 4.2组网说明 5.产品介绍 5.1视频监控综合资源管理平台介绍 5.2视频录像服务器和存储 5.2.…...
Python爬虫-使用Prefect框架实现一个可视化爬虫项目
前言 本文是该专栏的第19篇,后面会持续分享python爬虫干货知识,记得关注。 相信有的同学,在处理爬虫项目的时候,有时也会需要你将爬虫项目进行一个可视化展示,方便管理者能及时详细的了解当前爬虫任务的执行进度以及执行情况,甚至需要做一个爬虫监控预警的可视化任务。 …...
[hive面试真题]-基础理论篇
hive的工作流程 hive中分区表,分桶表 工作中hive分区表的应用示例 发现hive分区中的数据不对怎么处理 hive出现code 1 2 3 什么原因 ,怎么处理 工作中hive常见的文件格式 .压缩格式 工作时常用的hive函数 谈谈对窗口函数的理解 hive中如果出现数据倾斜 ,怎么发现 ,怎么…...
【其他】sd卡的照片在相机上能看到在电脑上却看不到
sd卡的照片在相机上能看到在电脑上却看不到 前情提要:太长不看版解决办法:思路:一、首先考虑恢复数据二、 解决文件后缀是exe的问题 前情提要: 在相机里可以看到照片和视频,但是SD卡通过读卡器插入电脑看不到&#x…...

Linux 之六:系统性能监控和挂载
系统性能 Linux系统中,有许多命令用于监测和分析性能指标。以下是一些常用的Linux性能分析命令: top:实时查看并监控CPU、内存以及各个进程的资源占用情况。htop(需要安装):一个增强版的 top 命令&#x…...

【Web】浅聊Java反序列化之C3P0——JNDI注入利用
目录 简介 原理分析 EXP 前文:【Web】浅聊Java反序列化之C3P0——URLClassLoader利用 【Web】浅聊Java反序列化之C3P0——不出网Hex字节码加载利用 简介 出网的情况下,这个C3P0的Gadget可以和fastjson,Snake YAML , JYAML,Yamlbeans , …...

Java项目:基于Springboot+vue实现的付费自习室系统设计与实现(源码+数据库+毕业论文)附含微信小程序端代码
一、项目简介 本项目是一套基于Springbootvue实现的付费自习室系统 包含:项目源码、数据库脚本等,该项目附带全部源码可作为毕设使用。 项目都经过严格调试,eclipse或者idea 确保可以运行! 该系统功能完善、界面美观、操作简单、…...

C++写食堂菜品管理系统
说明:本博文来自CSDN-问答板块,题主提问。 需要:学校拟开发一套食堂菜品管理系统,以便对菜品和同学们的评价进行管理,其中包含如下信息: 商户:商户名称、柜面位置、电话…… 菜品:菜品编号、菜品名称、价格、所属商户…… 学生:注册账号、昵称、电话…… 食堂里的商户…...

vue 在线预览word
1 mammoth 先找的是mammoth这个插件yarn add mammoth,版本是1,7.0 参考网上的示例使用如下: import mammoth from "mammoth"; const vHtml ref("") const readExcelFromRemoteFile (url) >{var xhr new XMLHttpRequest();xhr.open("…...

七彩虹八渐变 外贸建站公司wordpress模板
进出口水果wordpress外贸模板 漂亮水果wordpress外贸模板,做水果进出品生意的外贸公司自建站官网模板。 https://www.jianzhanpress.com/?p3516 玩具wordpress外贸模板 简洁玩具wordpress外贸模板,适合做跨境电商外贸公司使用的wordpres外贸s网站主题…...
[C++] C++生成随机数
一、简介 在C语言中常使用srand()random()的方式生成随机数,该方式并不是一个很好的随据说生成方法,一方面是因为其生成的随机数质量较低,另一方面其随机数范围也有所限制。在C11中推荐使用随机数引擎的方式生成随机数。 如何高效得生成高质…...

MFC内存泄露
1、泄露代码示例 void X::SetApplicationBtn() {CMFCRibbonApplicationButton* pBtn GetApplicationButton();// 获取 Ribbon Bar 指针// 创建自定义按钮CCustomRibbonAppButton* pCustomButton new CCustomRibbonAppButton();pCustomButton->SetImage(IDB_BITMAP_Jdp26)…...

Python实现prophet 理论及参数优化
文章目录 Prophet理论及模型参数介绍Python代码完整实现prophet 添加外部数据进行模型优化 之前初步学习prophet的时候,写过一篇简单实现,后期随着对该模型的深入研究,本次记录涉及到prophet 的公式以及参数调优,从公式可以更直观…...
相机Camera日志分析之三十一:高通Camx HAL十种流程基础分析关键字汇总(后续持续更新中)
【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了:有对最普通的场景进行各个日志注释讲解,但相机场景太多,日志差异也巨大。后面将展示各种场景下的日志。 通过notepad++打开场景下的日志,通过下列分类关键字搜索,即可清晰的分析不同场景的相机运行流程差异…...
重启Eureka集群中的节点,对已经注册的服务有什么影响
先看答案,如果正确地操作,重启Eureka集群中的节点,对已经注册的服务影响非常小,甚至可以做到无感知。 但如果操作不当,可能会引发短暂的服务发现问题。 下面我们从Eureka的核心工作原理来详细分析这个问题。 Eureka的…...
C++.OpenGL (14/64)多光源(Multiple Lights)
多光源(Multiple Lights) 多光源渲染技术概览 #mermaid-svg-3L5e5gGn76TNh7Lq {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-3L5e5gGn76TNh7Lq .error-icon{fill:#552222;}#mermaid-svg-3L5e5gGn76TNh7Lq .erro…...
QT3D学习笔记——圆台、圆锥
类名作用Qt3DWindow3D渲染窗口容器QEntity场景中的实体(对象或容器)QCamera控制观察视角QPointLight点光源QConeMesh圆锥几何网格QTransform控制实体的位置/旋转/缩放QPhongMaterialPhong光照材质(定义颜色、反光等)QFirstPersonC…...

使用LangGraph和LangSmith构建多智能体人工智能系统
现在,通过组合几个较小的子智能体来创建一个强大的人工智能智能体正成为一种趋势。但这也带来了一些挑战,比如减少幻觉、管理对话流程、在测试期间留意智能体的工作方式、允许人工介入以及评估其性能。你需要进行大量的反复试验。 在这篇博客〔原作者&a…...
Vue 模板语句的数据来源
🧩 Vue 模板语句的数据来源:全方位解析 Vue 模板(<template> 部分)中的表达式、指令绑定(如 v-bind, v-on)和插值({{ }})都在一个特定的作用域内求值。这个作用域由当前 组件…...
pycharm 设置环境出错
pycharm 设置环境出错 pycharm 新建项目,设置虚拟环境,出错 pycharm 出错 Cannot open Local Failed to start [powershell.exe, -NoExit, -ExecutionPolicy, Bypass, -File, C:\Program Files\JetBrains\PyCharm 2024.1.3\plugins\terminal\shell-int…...
Modbus RTU与Modbus TCP详解指南
目录 1. Modbus协议基础 1.1 什么是Modbus? 1.2 Modbus协议历史 1.3 Modbus协议族 1.4 Modbus通信模型 🎭 主从架构 🔄 请求响应模式 2. Modbus RTU详解 2.1 RTU是什么? 2.2 RTU物理层 🔌 连接方式 ⚡ 通信参数 2.3 RTU数据帧格式 📦 帧结构详解 🔍…...