ESP32-S3学习笔记<5>:SPI的应用

1. 头文件包含

#include "driver/spi_common.h"
#include "driver/spi_master.h"

2. SPI的配置

SPI配置,分两步进行。第一步是配置外设。第二步是添加挂载在SPI总线上的片外设备(如外部ADC等)。ESP32-S3有4个SPI外设,但是SPI0和SPI1保留给Flash或者PSRAM使用。因此一般可用的是SPI2和SPI3。
SPI设备是点对点传输的。但是通过多个CS片选线,可以将一条SPI总线应用在多个外围设备上。不同的外围设备受控于不同的SPI CS片选控制线,并且可能需要不同的速率。因此,第一步配置外设时,主要是设定SPI总线的SCLK、MOSI和MISO线,因为不论外围有几个设备, 这几个信号线是不变的。第二步配置时,则可以在该SPI外设上添加多个设备,该步骤则可指定CS控制线、速率等,并生成一个专用于该外围设备的句柄。

2.1 配置SPI外设

通过以下函数配置SPI外设:

esp_err_t spi_bus_initialize(spi_host_device_t host_id, const spi_bus_config_t *bus_config, spi_dma_chan_t dma_chan);

其中各个参数释义如下:

2.1.1 host_id/选择外设

host_id 设置要使用芯片的哪一个SPI外设。可用的选项有:

typedef enum {
   
   
//SPI1 can be used as GPSPI only on ESP32
    SPI1_HOST=0,    ///< SPI1
    SPI2_HOST=1,    ///< SPI2
#if SOC_SPI_PERIPH_NUM > 2
    SPI3_HOST=2,    ///< SPI3
#endif
    SPI_HOST_MAX,   ///< invalid host value
} spi_host_device_t;

可以看到,SPI0是完全选择不了的。SPI1可能是受限使用,应用中最好使用SPI2和SPI3。

2.1.2 spi_bus_config_t/外设部分参数

spi_bus_config_t 设定外设的几个参数。其定义如下:

typedef struct {
   
   
    union {
   
   
        int mosi_io_num;    ///< GPIO pin for Master Out Slave In (=spi_d) signal, or -1 if not used.
        int data0_io_num;   ///< GPIO pin for spi data0 signal in quad/octal mode, or -1 if not used.
    };
    union {
   
   
        int miso_io_num;    ///< GPIO pin for Master In Slave Out (=spi_q) signal, or -1 if not used.
        int data1_io_num;   ///< GPIO pin for spi data1 signal in quad/octal mode, or -1 if not used.
    };
    int sclk_io_num;      ///< GPIO pin for SPI Clock signal, or -1 if not used.
    union {
   
   
        int quadwp_io_num;  ///< GPIO pin for WP (Write Protect) signal, or -1 if not used.
        int data2_io_num;   ///< GPIO pin for spi data2 signal in quad/octal mode, or -1 if not used.
    };
    union {
   
   
        int quadhd_io_num;  ///< GPIO pin for HD (Hold) signal, or -1 if not used.
        int data3_io_num;   ///< GPIO pin for spi data3 signal in quad/octal mode, or -1 if not used.
    };
    int data4_io_num;     ///< GPIO pin for spi data4 signal in octal mode, or -1 if not used.
    int data5_io_num;     ///< GPIO pin for spi data5 signal in octal mode, or -1 if not used.
    int data6_io_num;     ///< GPIO pin for spi data6 signal in octal mode, or -1 if not used.
    int data7_io_num;     ///< GPIO pin for spi data7 signal in octal mode, or -1 if not used.
    int max_transfer_sz;  ///< Maximum transfer size, in bytes. Defaults to 4092 if 0 when DMA enabled, or to `SOC_SPI_MAXIMUM_BUFFER_SIZE` if DMA is disabled.
    uint32_t flags;       ///< Abilities of bus to be checked by the driver. Or-ed value of ``SPICOMMON_BUSFLAG_*`` flags.
    esp_intr_cpu_affinity_t  isr_cpu_id;    ///< Select cpu core to register SPI ISR.
    int intr_flags;       /**< Interrupt flag for the bus to set the priority, and IRAM attribute, see
                           *  ``esp_intr_alloc.h``. Note that the EDGE, INTRDISABLED attribute are ignored
                           *  by the driver. Note that if ESP_INTR_FLAG_IRAM is set, ALL the callbacks of
                           *  the driver, and their callee functions, should be put in the IRAM.
                           */
} spi_bus_config_t;
  1. mosi_io_num:指定MOSI的GPIO。由于SPI外设最多支持8数据线线模式,所以也可能是data0_io_num。对于一般的4线SPI,则只有MOSI线和MISO线。以下相同。
  2. miso_io_num:指定MISO的GPIO。
  3. sclk_io_num:指定SCLK的GPIO。
  4. quadwp_io_num:HOLD信号。一般SPI总线中不需要这个,则设置为-1。一些Flash(如25Q Flash)带有这个引脚。
  5. quadhd_io_num:同上,不需要时设置为-1。
  6. data4_io_num、data5_io_num、data6_io_num、data7_io_num:在8数据线时使用。4线SPI,均设置为-1。
  7. max_transfer_sz:设置最大传输大小。
  8. flags:指定驱动的一些特殊功能,定义在文件 spi_common.h 文件中,以前缀 SPICOMMON_BUSFLAG_ 开头。
  9. isr_cpu_id:指定中断服务程序注册到哪个CPU核心。一般设置为 ESP_INTR_CPU_AFFINITY_AUTO。不过如果带有WIFI应用等,则可能需要按情况考虑。
  10. intr_flags:指定中断优先级等。

2.1.3 dma_chan/是否使能DMA功能,以及DMA通道信息

可用的选项有:

typedef enum {
   
   
    SPI_DMA_DISABLED = 0,     ///< Do not enable DMA for SPI
#
<think>嗯,用户要求详细解析ESP32-S3外部PSRAM的配置和使用方法,看来是个嵌入式开发者。从引用内容看,用户可能正在开发摄像头或需要大内存的应用,因为引用4提到了图像处理中的PSRAM使用。用户应该需要具体的技术细节而非概念说明。 用户提供的引用很有价值:引用1展示了基础检测和分配代码,引用2提到GPIO限制(特别是26-32管脚与PSRAM冲突),引用3是禁用PSRAM的配置方法(但用户需要的是启用),引用4则验证了PSRAM在图像处理中的实际应用。需要整合这些信息。 重点要覆盖三方面:硬件配置注意事项(GPIO冲突问题)、软件启用方法(sdkconfig配置)、实际应用代码示例(分配/释放)。用户可能特别关心大块内存分配的性能,比如引用4中"多级缓存管理"的实现思路。 需要强调几个易错点:一是Strapping管脚配置(引用2的GPIO限制),二是malloc()与ps_malloc()的区别(引用1的示例),三是双核访问的同步问题(引用4提到"双核协同处理")。对于摄像头应用,可以补充循环缓冲区的实现思路。 考虑到用户可能进行低功耗开发,还要提醒PSRAM的功耗数据(手册标注的70mA峰值电流)。最后用存储照片的案例呼应引用4的需求,展示从分配到写入SD卡的全流程。</think>以下是关于ESP32-S3配置和使用外部PSRAM的详细技术解析: --- ### **一、PSRAM基础概念** 1. **作用** PSRAM(伪静态随机存储器)为ESP32-S3提供额外内存(通常4-16MB),解决片上RAM(512KB)不足问题,适用于图像处理、音频缓冲等场景[^4]。 2. **硬件接口** 通过SPI或QSPI总线连接,最高支持120MHz时钟频率。 --- ### **二、配置步骤** #### **1. 启用硬件支持** 在ESP-IDF环境中修改`sdkconfig`文件: ```ini CONFIG_ESP32S3_SPIRAM_SUPPORT=y # 启用PSRAM CONFIG_SPIRAM_MODE_OCT=y # 八线模式(推荐) CONFIG_SPIRAM_SPEED_120M=y # 设置120MHz时钟 ``` #### **2. GPIO避坑指南** - **禁止占用管脚**:GPIO26-32用于内部Flash/PSRAM通信,不可复用[^2] - **Strapping管脚**:GPIO0/3/45/46影响启动模式,慎用 - **USB管脚**:GPIO19/20专用于USB --- ### **三、代码实现** #### **1. 检测与初始化** ```cpp #include <esp_spiram.h> void init_psram() { if (esp_spiram_init() != ESP_OK) { printf("PSRAM初始化失败!"); } printf("PSRAM大小: %d MB", esp_spiram_get_size() / 1048576); } ``` #### **2. 内存分配** ```cpp // 在PSRAM中分配1MB缓冲区 uint8_t *buffer = (uint8_t *)heap_caps_malloc(1024*1024, MALLOC_CAP_SPIRAM); if(buffer) { // 使用PSRAM内存 process_image(buffer); heap_caps_free(buffer); // 必须手动释放! } ``` --- ### **四、关键注意事项** 1. **性能优化** - 启用缓存加速:`CONFIG_SPIRAM_FETCH_INSTRUCTIONS=y` - 使用32字节对齐访问提升速度 ```cpp // 对齐分配示例 uint8_t *aligned_buf = heap_caps_aligned_alloc(32, size, MALLOC_CAP_SPIRAM); ``` 2. **多核安全** - 双核访问需加锁: ```cpp portMUX_TYPE mux = portMUX_INITIALIZER_UNLOCKED; taskENTER_CRITICAL(&mux); // 临界区操作PSRAM taskEXIT_CRITICAL(&mux); ``` 3. **功耗控制** - 空闲时调用`esp_psram_extram_power_down()`休眠 - 唤醒延迟约100μs,实时性要求高场景慎用 --- ### **五、典型应用场景** 1. **图像处理** ```cpp // 存储320x240 RGB图像(约150KB) uint16_t *frame_buffer = heap_caps_malloc(320*240*2, MALLOC_CAP_SPIRAM); ``` 2. **语音缓冲** ```cpp // 分配10秒44.1kHz音频缓冲 int16_t *audio_buf = heap_caps_malloc(44100*10*2, MALLOC_CAP_SPIRAM); ``` 3. **机器学习模型** ```cpp // 加载TensorFlow Lite模型 uint8_t *model_data = heap_caps_malloc(MODEL_SIZE, MALLOC_CAP_SPIRAM); ``` --- ### **六、常见问题解决** 1. **分配失败检查** ```cpp ESP_ERROR_CHECK( heap_caps_get_free_size(MALLOC_CAP_SPIRAM) ); ``` 2. **内存泄漏检测** 启用`CONFIG_HEAP_TRACING`记录分配历史 3. **稳定性提升** - 添加ECC校验:`CONFIG_SPIRAM_ECC_ENABLE=y` - 降低时钟频率至80MHz(长线布线时) > 重要提示:PSRAM访问延迟约100ns(比片内RAM慢8倍),频繁访问数据应优先存放片内RAM[^4]。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值