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

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 中添加组件

步骤:

  1. 首先新建 PROJECT_DIR/components 路径。
  2. 在PROJECT_DIR/components 中添加我们自定义的组件,比如我添加了 led_key
  3. 将组件相关的头文件和源文件放到 led_key中,并新建 CMakeLists.txt 文件。
  4. 在 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开发的都知道&#xff0c;我们在编写不同的外设时&#xff0c;通常都会单独编写一个app文件夹或者是user文件夹之类的来存放不同外设功能的源文件和头文件。 在前面一节2.构建第一个工程并烧录到ESP32开发板-CSDN博客中&#xff0c;我们是使用了一个乐鑫…...

Vue3.0里为什么要用 Proxy API 替代 defineProperty API

一、Object.defineProperty 定义&#xff1a;Object.defineProperty() 方法会直接在一个对象上定义一个新属性&#xff0c;或者修改一个对象的现有属性&#xff0c;并返回此对象 为什么能实现响应式 通过defineProperty 两个属性&#xff0c;get及set get 属性的 getter 函…...

c++初阶------类和对象(下)

作者前言 &#x1f382; ✨✨✨✨✨✨&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f382; ​&#x1f382; 作者介绍&#xff1a; &#x1f382;&#x1f382; &#x1f382; &#x1f389;&#x1f389;&#x1f389…...

PMP考试:如何高效学习PMBOK?

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

个人博客网站前端页面的实现

博客网站前端页面的实现 博客登录页 相关代码 login.html <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><…...

Kotlin Retrofit 网络请求

一、添加依赖&#xff1a; //Retrofit 网络请求implementation("com.squareup.retrofit2:retrofit:2.3.0")implementation("com.squareup.retrofit2:converter-gson:2.3.0")//json转换 二、创建单例类&#xff1a; package com.example.buju.httpimport …...

pyside6 pytq PyDracula QVideoWidget视频只有声音没有画面

解决方案&#xff1a; 先不使用框架&#xff0c;纯pyside6代码&#xff0c;如果添加视频有画面有声音&#xff0c;那可以排除是硬件问题&#xff0c;如果没有画面只有声音&#xff0c;可能是视频解码器无法解码&#xff0c;换个格式的视频文件如果只有使用PyDracula 出问题&am…...

Python爬网页,不确定网页的编码,不需要用第三方库

Python爬网页&#xff0c;不确定网页的编码&#xff0c;不需要用第三方库&#xff0c;自己写个判断&#xff0c;乱拳打死老师傅 detect试了&#xff0c;不好用 apparent_encoding试了&#xff0c;不好用 encoding试了&#xff0c;不好用 headers里get试了&#xff0c;不好用…...

Web测试的基础流程(外加测试过程需要的注意5点)

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

项目解决方案:视频监控接入和录像系统设计方案(下)

目 录 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卡的照片在相机上能看到在电脑上却看不到 前情提要&#xff1a;太长不看版解决办法&#xff1a;思路&#xff1a;一、首先考虑恢复数据二、 解决文件后缀是exe的问题 前情提要&#xff1a; 在相机里可以看到照片和视频&#xff0c;但是SD卡通过读卡器插入电脑看不到&#x…...

Linux 之六:系统性能监控和挂载

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

【Web】浅聊Java反序列化之C3P0——JNDI注入利用

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

Java项目:基于Springboot+vue实现的付费自习室系统设计与实现(源码+数据库+毕业论文)附含微信小程序端代码

一、项目简介 本项目是一套基于Springbootvue实现的付费自习室系统 包含&#xff1a;项目源码、数据库脚本等&#xff0c;该项目附带全部源码可作为毕设使用。 项目都经过严格调试&#xff0c;eclipse或者idea 确保可以运行&#xff01; 该系统功能完善、界面美观、操作简单、…...

C++写食堂菜品管理系统

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

vue 在线预览word

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

七彩虹八渐变 外贸建站公司wordpress模板

进出口水果wordpress外贸模板 漂亮水果wordpress外贸模板&#xff0c;做水果进出品生意的外贸公司自建站官网模板。 https://www.jianzhanpress.com/?p3516 玩具wordpress外贸模板 简洁玩具wordpress外贸模板&#xff0c;适合做跨境电商外贸公司使用的wordpres外贸s网站主题…...

[C++] C++生成随机数

一、简介 在C语言中常使用srand()random()的方式生成随机数&#xff0c;该方式并不是一个很好的随据说生成方法&#xff0c;一方面是因为其生成的随机数质量较低&#xff0c;另一方面其随机数范围也有所限制。在C11中推荐使用随机数引擎的方式生成随机数。 如何高效得生成高质…...

地震勘探——干扰波识别、井中地震时距曲线特点

目录 干扰波识别反射波地震勘探的干扰波 井中地震时距曲线特点 干扰波识别 有效波&#xff1a;可以用来解决所提出的地质任务的波&#xff1b;干扰波&#xff1a;所有妨碍辨认、追踪有效波的其他波。 地震勘探中&#xff0c;有效波和干扰波是相对的。例如&#xff0c;在反射波…...

AI Agent与Agentic AI:原理、应用、挑战与未来展望

文章目录 一、引言二、AI Agent与Agentic AI的兴起2.1 技术契机与生态成熟2.2 Agent的定义与特征2.3 Agent的发展历程 三、AI Agent的核心技术栈解密3.1 感知模块代码示例&#xff1a;使用Python和OpenCV进行图像识别 3.2 认知与决策模块代码示例&#xff1a;使用OpenAI GPT-3进…...

【SpringBoot】100、SpringBoot中使用自定义注解+AOP实现参数自动解密

在实际项目中,用户注册、登录、修改密码等操作,都涉及到参数传输安全问题。所以我们需要在前端对账户、密码等敏感信息加密传输,在后端接收到数据后能自动解密。 1、引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId...

论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(一)

宇树机器人多姿态起立控制强化学习框架论文解析 论文解读&#xff1a;交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架&#xff08;一&#xff09; 论文解读&#xff1a;交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化…...

GC1808高性能24位立体声音频ADC芯片解析

1. 芯片概述 GC1808是一款24位立体声音频模数转换器&#xff08;ADC&#xff09;&#xff0c;支持8kHz~96kHz采样率&#xff0c;集成Δ-Σ调制器、数字抗混叠滤波器和高通滤波器&#xff0c;适用于高保真音频采集场景。 2. 核心特性 高精度&#xff1a;24位分辨率&#xff0c…...

WPF八大法则:告别模态窗口卡顿

⚙️ 核心问题&#xff1a;阻塞式模态窗口的缺陷 原始代码中ShowDialog()会阻塞UI线程&#xff0c;导致后续逻辑无法执行&#xff1a; var result modalWindow.ShowDialog(); // 线程阻塞 ProcessResult(result); // 必须等待窗口关闭根本问题&#xff1a…...

嵌入式学习之系统编程(九)OSI模型、TCP/IP模型、UDP协议网络相关编程(6.3)

目录 一、网络编程--OSI模型 二、网络编程--TCP/IP模型 三、网络接口 四、UDP网络相关编程及主要函数 ​编辑​编辑 UDP的特征 socke函数 bind函数 recvfrom函数&#xff08;接收函数&#xff09; sendto函数&#xff08;发送函数&#xff09; 五、网络编程之 UDP 用…...

6️⃣Go 语言中的哈希、加密与序列化:通往区块链世界的钥匙

Go 语言中的哈希、加密与序列化:通往区块链世界的钥匙 一、前言:离区块链还有多远? 区块链听起来可能遥不可及,似乎是只有密码学专家和资深工程师才能涉足的领域。但事实上,构建一个区块链的核心并不复杂,尤其当你已经掌握了一门系统编程语言,比如 Go。 要真正理解区…...

写一个shell脚本,把局域网内,把能ping通的IP和不能ping通的IP分类,并保存到两个文本文件里

写一个shell脚本&#xff0c;把局域网内&#xff0c;把能ping通的IP和不能ping通的IP分类&#xff0c;并保存到两个文本文件里 脚本1 #!/bin/bash #定义变量 ip10.1.1 #循环去ping主机的IP for ((i1;i<10;i)) doping -c1 $ip.$i &>/dev/null[ $? -eq 0 ] &&am…...

FOPLP vs CoWoS

以下是 FOPLP&#xff08;Fan-out panel-level packaging 扇出型面板级封装&#xff09;与 CoWoS&#xff08;Chip on Wafer on Substrate&#xff09;两种先进封装技术的详细对比分析&#xff0c;涵盖技术原理、性能、成本、应用场景及市场趋势等维度&#xff1a; 一、技术原…...