ESP32 S3

开发方式

ESP-IDF [ 面向专业开发者 ]

ESP-IDF , 乐鑫官方开发框架、专门为esp32系列芯片设计、支持C c++ 语言,并提供一套完整的API,可控制ESP32各种功能和外设

优点: 配置灵活、性能更高、功能更多、适合商用
缺点: 搭建环境步骤繁琐

arduino

是一种流行的开源电子圆形平台,包括开发板、开发环境
提供了一种基于c c++的语言,让开发者更容易控制和编程

优点: 代码简单、入门容易、快速开发
缺点··编译下载耗时长、开发效率低

esp32-idf

在这里插入图片描述

idf环境和esp-idf框架,他们之间是什么关系
IDF 环境包含了 ESP-IDF 框架。
IDF 环境是一个完整的开发环境设置,它涵盖了各种工具、编译器、库等,以支持对 ESP32 等芯片进行开发。而 ESP-IDF 框架是这个环境中的核心部分,它提供了一系列的软件架构、功能模块、接口等,用于构建应用程序和实现各种功能,是具体进行开发所依赖的关键部分。可以说 IDF 环境是围绕 ESP-IDF 框架搭建起来的,为开发者提供便利的开发条件来使用 ESP-IDF 框架进行高效的开发工作。

搭建开发环境

有2种开发环境,
第一种是:基于windows,采用命令的方式;(需要配置环境变量
第二种是:基于vscode + espIdf插件 集成开发环境 (通过按钮实现命令的功能,需要使用esp-idf配置集成开发环境

IDF前端工具(1):

  • 新建工程
    在这里插入图片描述

  • 新建新组件

在这里插入图片描述
在这里插入图片描述

  • 设置目标芯片

在这里插入图片描述

  • 编译工程
    使用idf.py build 来编译当前项目工程
    -

  • 监控项目
    在这里插入图片描述

  • 配置项目
    在这里插入图片描述
    在这里插入图片描述

  • 下载代码
    在这里插入图片描述

  • 清除编译文件

在这里插入图片描述
在这里插入图片描述

搭建集成开发环境(2) ( 省去idf的命令输入,直接通过按钮触发实现 )

vscode 安装

安装chinese 中文插件

安装与配置esp-idf插件

在vscode插件商店搜索:esp-idf 安装
然后 ctrl + shift + p , 输入:配置 ESP-IDF 插件
选择advance
在这里插入图片描述
安装成功后显示如下:
在这里插入图片描述

注意:vscode 安装idf环境,由几种方式:
1、通过引入本地已经下载好的IDF固件代码路径
2、通过在线下载的方式,执行从云端下载的idf工程存放在哪个路径下(包含tools工具包)

个性化配置和工作环境配置

STM32 VS ESP32

城哥,学习ESP32-S3和STM32的外设有一些共同点,但也有显著差异。以下是一些详细的建议和对比:

1. 学习资源

ESP32-S3:

官方文档:Espressif提供了详细的ESP32-S3技术参考手册,这是最权威的资料。
SDK:使用Espressif的ESP-IDF(Espressif IoT Development Framework),它包含了大量的示例代码和外设驱动。
社区支持:Espressif的论坛和GitHub社区非常活跃,可以找到许多实用的例子和解决方案。
STM32:

官方文档:STMicroelectronics提供了详细的STM32产品手册和参考手册。
库和工具:使用STM32CubeMX和HAL库,这些工具可以简化外设初始化和配置,并提供许多示例代码。
社区支持:STM32的开发者社区和论坛也非常活跃,可以找到丰富的资源。

2. 开发环境

ESP32-S3:

IDE:通常使用VS Code或Eclipse,结合ESP-IDF插件。
编译工具链:ESP-IDF提供了基于CMake的构建系统,使用GNU工具链进行编译。
调试工具:使用JTAG调试器(如ESP-Prog)进行硬件调试。
STM32:

IDE:常用STM32CubeIDE,也可以使用Keil MDK或IAR Embedded Workbench。
编译工具链:使用STM32CubeMX生成初始化代码,结合HAL库进行开发。
调试工具:使用ST-Link调试器进行硬件调试。

3. 外设驱动和编程

ESP32-S3:

外设种类:ESP32-S3内置了许多常用外设,如UART、SPI、I2C、ADC、DAC等。
API使用:ESP-IDF提供了丰富的外设驱动API,可以直接调用这些API实现外设的配置和控制。例如,使用UART外设时,只需调用uart_driver_install和uart_param_config等函数。
FreeRTOS:ESP32-S3集成了FreeRTOS,许多外设驱动和应用都是基于FreeRTOS任务和队列实现的。
STM32:

外设种类:STM32也有丰富的外设,如UART、SPI、I2C、ADC、DAC等,但每个系列的具体外设可能有所不同。
API使用:使用STM32CubeMX生成初始化代码,然后调用HAL库中的函数进行外设操作。例如,使用UART外设时,可以调用HAL_UART_Init和HAL_UART_Transmit等函数。
中断和DMA:STM32的外设驱动中,经常会用到中断和DMA传输,需要对这些机制有深入的理解。

4. 实际应用中的区别

ESP32-S3:

Wi-Fi和蓝牙:ESP32-S3内置Wi-Fi和蓝牙,适合物联网应用。学习时需要关注网络连接、协议栈和低功耗管理等方面。
多核处理:ESP32-S3具有双核处理器,学习时需要掌握多线程编程和资源管理。
STM32:

实时性和工业控制:STM32在工业控制和实时性要求高的应用中更为常见,学习时需要关注实时操作系统(如FreeRTOS)和精确定时控制。
多样化的系列:STM32有多个系列(如F系列、L系列、H系列),每个系列的特点和应用场景有所不同,学习时需要根据具体需求选择合适的系列和型号。

总结

ESP32-S3和STM32在外设学习上的主要区别在于开发环境、工具链和实际应用领域的不同。ESP32-S3更侧重于物联网和无线通信,而STM32更注重工业控制和实时性应用。希望这些信息对您有所帮助,祝您学习顺利!如果有更多问题,欢迎随时提问。

Cmake 构建系统

CMake构建系统

CMake 是一个跨平台的自动化构建系统,它使用名为CMakeLists.txt的脚本文件来描述源代码的构建过程和各种依赖关系。CMake可以生成标准的构建文件(如Unix的Makefile或Windows的Visual Studio项目文件),这样开发者就可以在多种平台上使用相同的构建脚本。

在ESP-IDF中,CMake用于:

  • 管理项目结构:定义哪些文件是源代码文件,哪些是需要编译的目标。
  • 指定编译器和链接器选项:设置编译器的参数,如优化级别、编译器警告和定义宏等。
  • 处理依赖关系:自动解析和处理项目中不同模块之间的依赖关系,确保编译顺序正确。
  • 集成组件:ESP-IDF使用的是基于组件的架构,CMake帮助整合和配置这些组件,使其可以在项目中轻松使用。

GNU工具链

GNU工具链 是一套开源的软件工具,包括GCC(GNU编译器集合)、GDB(GNU调试器)和其他工具。GCC可以编译C、C++、Objective C、Fortran、Ada和Go等多种编程语言。

在ESP-IDF中,GNU工具链用于:

  • 编译和链接:GCC编译器编译源代码并生成机器码,链接器将多个对象文件链接成最终的可执行文件。
  • 调试:GDB调试器用于调试程序,可以设置断点、单步执行、查看变量等,帮助开发者找出程序中的错误。
  • 优化代码:GCC提供多级别的优化选项,可以帮助提高程序的性能和减少资源消耗。

使用过程

  • 编写CMake脚本:定义项目的源文件、目标文件、编译选项等。
  • 配置项目:使用cmake命令进行项目配置,指定目标处理器和交叉编译器。
  • 构建项目:运行make或ninja等命令,CMake根据CMakeLists.txt文件中的定义执行编译过程。
  • 调试和测试:使用GDB进行程序的调试。

结论

通过使用CMake和GNU工具链,ESP-IDF为开发者提供了一个高效、灵活且强大的开发环境,特别适用于复杂的嵌入式系统项目开发。这种方法不仅可以提高开发效率,还可以帮助维持代码的可维护性和可扩展性。

cmake学习·

理论学习:首先,通过阅读官方文档和教程,了解CMake的基本概念和语法。这一阶段的重点是理解CMake的核心功能和组件。
实践操作:通过创建简单的项目实践CMake的用法。逐步增加项目的复杂性,如添加库依赖、条件编译等。
查看示例:分析并尝试理解开源项目中的CMake配置文件。这可以帮助您看到CMake在实际项目中的应用。
社区学习:加入CMake的用户社区,如Stack Overflow、Reddit等,这些社区可以提供帮助,同时您可以看到其他人是如何解决问题的。
持续进步:随着CMake版本的更新,持续关注并学习新的功能和最佳实践。

外设

定时器

esp32 内置一组52位的系统定时器,用于生成系统所需的滴答定时器中断,也可用于普通定时器生成周期 或者单次延时中断。

定时器是内部集成的功能,可通过编程灵活控制,依赖内部计数器的视线,没经历一个机器周期并产生一个脉冲时,计数器就会递增。

定时器的作用在于计时,当设定的时间到达后,就会触发中断,从而通知系统计时完成
在中断服务函数中,编写业务逻辑.

流程步骤

  • 初始化定时器(产生 n uS 的定时器中断)
  • 配置定时器参数
  • 设置定时器回调函数(定时器时间到了之后,执行的函数)

定时器源文件




#include "esptim.h"
/**
 * 定时器初始化
*/
void esptim_int_init(uint64_t tps){
    esp_timer_handle_t esp_tim_handle;
    // 定时器参数配置结构体
    esp_timer_create_args_t tim_periodic_arg = {
        .callback = &esptim_callback,  // 设置回调函数
        .arg = NULL,
    };

    // 创建一个事件
    esp_timer_create(&tim_periodic_arg,&esp_tim_handle);
    // 每周期内触发一次
    esp_timer_start_periodic(esp_tim_handle,tps);
}


/**
 * 定时器回调函数
*/
void esptim_callback(void *arg){
    // 翻转led
    LED_TOGGLE();
}

头文件


#ifndef __ESPTIM_H_
#define __ESPTIM_H_

#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"
#include "esp_timer.h"
#include "led.h"

void esptim_int_init(uint64_t tps);
void esptim_callback(void *arg);


#endif

主函数

/**
 ****************************************************************************************************
 * @file        main.c
 * @author      正点原子团队(ALIENTEK)
 * @version     V1.0
 * @date        2023-08-26
 * @brief       高分辨率定时器(ESP定时器)实验
 * @license     Copyright (c) 2020-2032, 广州市星翼电子科技有限公司
 ****************************************************************************************************
 * @attention
 *
 * 实验平台:正点原子 ESP32-S3 开发板
 * 在线视频:www.yuanzige.com
 * 技术论坛:www.openedv.com
 * 公司网址:www.alientek.com
 * 购买地址:openedv.taobao.com
 *
 ****************************************************************************************************
 */

#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"
#include "nvs_flash.h"
#include "led.h"
#include "esptim.h"


/**
 * @brief       程序入口
 * @param       无
 * @retval      无
 */
void app_main(void)
{
    esp_err_t ret;
    
    ret = nvs_flash_init();         /* 初始化NVS */

    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();
    }
    
    led_init();                     /* 初始化LED */
    esptim_int_init(200000);       /* 初始化高分辨率定时器,此处设置定时器周期为1秒,
                                       但该函数事宜微妙为单位进行计算,
                                       故而1秒钟换算为1000000微秒 */
}

试验现象

  • 以200ms 的计时周期,翻转IO口
    在这里插入图片描述

通用定时器gptimer

这里面在定时器回调函数中,把计数器的值加入到队列中
在主函数中,不断读取队列中的数据,然后打印输出到终端中

/**
 ****************************************************************************************************
 * @file        gtim.c
 * @author      正点原子团队(ALIENTEK)
 * @version     V1.0
 * @date        2023-08-26
 * @brief       通用定时器驱动代码
 * @license     Copyright (c) 2020-2032, 广州市星翼电子科技有限公司
 ****************************************************************************************************
 * @attention
 *
 * 实验平台:正点原子 ESP32-S3 开发板
 * 在线视频:www.yuanzige.com
 * 技术论坛:www.openedv.com
 * 公司网址:www.alientek.com
 * 购买地址:openedv.taobao.com
 * 
 ****************************************************************************************************
 */

#include "gptim.h"


QueueHandle_t queue;

/**
 * @brief       初始化通用定时器
 * @param       counts: 计数值
 * @param       resolution: 定时器周期,resolution = 1s = 1000000μs(此处,定时器以微秒作为计算单位,)
 * @retval      无
 */
void gptim_int_init(uint16_t counts, uint32_t resolution)
{
    gptimer_alarm_config_t alarm_config;

    uint64_t count;

    /* 配置通用定时器 */
    ESP_LOGI("GPTIMER_ALARM", "配置通用定时器");                                 /* 创建通用定时器句柄 */                                 
    
    gptimer_handle_t g_tim = NULL;
    gptimer_config_t g_tim_handle = {
        .clk_src = GPTIMER_CLK_SRC_DEFAULT,                                             /* 选择定时器时钟源 */   
        .direction = GPTIMER_COUNT_UP,                                                  /* 递增计数模式 */
        .resolution_hz = resolution,                                                    /* 计数器分辨率 */
    };
        gptimer_event_callbacks_t g_tim_callbacks = {
        .on_alarm = gptimer_callback,                                                   /* 注册用户回调函数 */ 
    };
    alarm_config.alarm_count = 1000000;                                                 /* 报警目标计数值 */
    ESP_ERROR_CHECK(gptimer_new_timer(&g_tim_handle, &g_tim));                          /* 创建新的通用定时器,并返回句柄 */

    queue = xQueueCreate(10, sizeof(gptimer_event_t));                                  /* 创建一个队列,并引入一个事件 */

    if (!queue)
    {
        ESP_LOGE("GPTIMER_ALARM", "创建队列失败");                                /* 创建队列失败 */

        return;
    }

    /* 设置和获取计数值 */
    ESP_LOGI("GPTIMER_ALARM", "设置计数值");
    ESP_ERROR_CHECK(gptimer_set_raw_count(g_tim, counts));                              /* 设置计数值 */
    ESP_LOGI("GPTIMER_ALARM", "获取计数值");
    ESP_ERROR_CHECK(gptimer_get_raw_count(g_tim, &count));                              /* 获取计数值 */
    ESP_LOGI("GPTIMER_ALARM", "定时器计数值: %llu", count);

    /* 注册事件回调函数 */
    ESP_ERROR_CHECK(gptimer_register_event_callbacks(g_tim, &g_tim_callbacks, queue));  /* 配置通用定时器回调函数 */

    /* 设置报警动作 */
    ESP_LOGI("GPTIMER_ALARM", "使能通用定时器");
    ESP_ERROR_CHECK(gptimer_enable(g_tim));                                             /* 使能通用定时器 */
    ESP_ERROR_CHECK(gptimer_set_alarm_action(g_tim, &alarm_config));                    /* 配置通用定时器报警事件 */
    ESP_ERROR_CHECK(gptimer_start(g_tim));                                              /* 启动通用定时器 */
}

/**
 * @brief       定时器回调函数
 * @param       无
 * @retval      无
 */
bool IRAM_ATTR gptimer_callback(gptimer_handle_t timer, const gptimer_alarm_event_data_t *edata, void *user_data)
{ 
  //  ESP_LOGI("isr done","");
    BaseType_t high_task_awoken = pdFALSE;
    queue = (QueueHandle_t)user_data;

    /* 从事件数据中检索计数值 */
    gptimer_event_t ele = {
        .event_count = edata->count_value
    };
 

    /* 可选:通过操作系统队列将事件数据发送到其他任务 */
    xQueueSendFromISR(queue, &ele, &high_task_awoken);
    
    /* 重新配置报警值 */ 
    gptimer_alarm_config_t alarm_config = {
        .alarm_count = edata->alarm_value + 1000000, /* 在接下来的1秒内报警 */ 
    };
    gptimer_set_alarm_action(timer, &alarm_config);
    
    /* 返回是否需要在ISR结束时让步 */ 
    return high_task_awoken == pdTRUE;
}

头文件

/**
 ****************************************************************************************************
 * @file        gtim.h
 * @author      正点原子团队(ALIENTEK)
 * @version     V1.0
 * @date        2023-08-26
 * @brief       通用定时器驱动代码
 * @license     Copyright (c) 2020-2032, 广州市星翼电子科技有限公司
 ****************************************************************************************************
 * @attention
 *
 * 实验平台:正点原子 ESP32-S3 开发板
 * 在线视频:www.yuanzige.com
 * 技术论坛:www.openedv.com
 * 公司网址:www.alientek.com
 * 购买地址:openedv.taobao.com
 * 
 ****************************************************************************************************
 */

#ifndef __GPTIM_H_
#define __GPTIM_H_

#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "driver/gptimer.h"
#include "esp_log.h"


typedef struct {
    uint64_t event_count;
} gptimer_event_t;

extern QueueHandle_t queue;

/* 函数声明 */
void gptim_int_init(uint16_t counts, uint32_t resolution);                                                          /* 初始化通用定时器 */
bool IRAM_ATTR gptimer_callback(gptimer_handle_t timer, const gptimer_alarm_event_data_t *edata, void *user_data);  /* 定时器回调函数 */


#endif

main.c 文件源代码

/**
 ****************************************************************************************************
 * @file        main.c
 * @author      正点原子团队(ALIENTEK)
 * @version     V1.0
 * @date        2023-08-26
 * @brief       高分辨率定时器(ESP定时器)实验
 * @license     Copyright (c) 2020-2032, 广州市星翼电子科技有限公司
 ****************************************************************************************************
 * @attention
 *
 * 实验平台:正点原子 ESP32-S3 开发板
 * 在线视频:www.yuanzige.com
 * 技术论坛:www.openedv.com
 * 公司网址:www.alientek.com
 * 购买地址:openedv.taobao.com
 *
 ****************************************************************************************************
 */

#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"
#include "nvs_flash.h"
#include "led.h"
#include "esptim.h"
#include "esp_log.h"
#include "gptim.h"


/**
 * @brief       程序入口
 * @param       无
 * @retval      无
 */
void app_main(void)
{
    esp_err_t ret;
    uint8_t record;
    gptimer_event_t g_tim_evente;
    
    ret = nvs_flash_init();         /* 初始化NVS */

    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();
    }
    
    led_init();                     /* 初始化LED */
     /* 初始化高分辨率定时器,此处设置定时器周期为1秒,
                                       但该函数事宜微妙为单位进行计算,
                                       故而1秒钟换算为1000000微秒 */
    // esptim_int_init(200000);      
    gptim_int_init(100, 1000000);                                                             /* 初始化通用定时器 */
    
    while (1)
    {
        record = 4;

        if (xQueueReceive(queue, &g_tim_evente, 2000))
        {
            ESP_LOGI("GPTIMER_ALARM", "定时器报警, 计数值: %llu", g_tim_evente.event_count);   /* 打印通用定时器发生一次计数事件后获取到的值 */
            record--;
        }
        else
        {
            ESP_LOGW("GPTIMER_ALARM", "错过一次计数事件");
        }
    }
    vQueueDelete(queue);
}

idf 基础

组件构成的基础: CmakeList 、main.c

1. sdkconfig

这个配置文件时由根目录下:CmakeList 下的

include($ENV{IDF_PATH}/tools/cmake/project.cmake) 

编译之后产生的。

2. 编译链接

通过组件内部的cmakelist 对main.c 种的代码进行编译,编译后产生的文件存放在build 文件种。

分区表

# Name,   Type, SubType, Offset,  Size, Flags
# Note: if you have increased the bootloader size, make sure to update the offsets to avoid overlap
nvs,      data, nvs,     ,         0x6000,
phy_init, data, phy,     ,         0x1000,
factory,  app,  factory, ,         7M,

ESP32 编程指南 - IDF 分区表介绍

每片 ESP32 的 flash 可以包含多个应用程序,以及多种不同类型的数据(例如校准数据、文件系统数据、参数存储数据等)。因此,我们在 flash 的 默认偏移地址 0x8000 处烧写一张分区表。

分区表的长度为 0xC00 字节,最多可以保存 95 条分区表条目。MD5 校验和附加在分区表之后,用于在运行时验证分区表的完整性。分区表占据了整个 flash 扇区,大小为 0x1000 (4 KB)。因此,它后面的任何分区至少需要位于 (默认偏移地址) + 0x1000 处。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值