STM32----SPI+DMA高效读写外部Flash的配置与实战

1. 为什么需要SPI+DMA来读写外部Flash?

在实际的嵌入式开发中,我们经常需要与外部Flash芯片进行数据交互,尤其是在OTA固件更新、数据存储等场景下。如果你只是偶尔读写几个字节的数据,使用STM32的硬件SPI配合查询方式完全够用,简单直接。但当你需要处理大量数据时,比如一次性写入几百KB的固件文件,如果还让CPU傻傻地等待每个字节的传输完成,那简直就是对处理器资源的极大浪费。

这时候DMA(直接存储器访问)就派上用场了。DMA可以在不需要CPU干预的情况下,直接在存储器和外设之间传输数据。想象一下,你让一个专业的搬运工(DMA)来帮你搬箱子(数据),而你(CPU)可以腾出手来做其他更重要的事情,比如处理用户输入或者运行复杂的算法。这种分工协作的方式大大提高了系统效率。

我最早在OTA项目中使用SPI+DMA方案时,发现系统响应速度明显提升。原本在写入固件时界面会卡顿的问题得到了完美解决,这就是DMA的威力所在。

2. 硬件SPI与DMA的协同工作原理

2.1 SPI全双工通信的特殊性

SPI是一种全双工通信协议,这意味着在通信过程中,数据是同时发送和接收的。这个特性在使用DMA时需要特别注意,因为你不能只配置发送而不配置接收,或者反过来。

在实际配置中,我们需要同时设置两个DMA流:一个用于发送(TX),一个用于接收(RX)。即使你只是想要读取数据,SPI也会在接收数据的同时发送数据,通常是0xFF(空字节)。相反,当你写入数据时,SPI也会同时接收数据,虽然这些接收到的数据可能并不重要。

2.2 DMA通道选择策略

不同的STM32型号在DMA配置上有些差异。以STM32F407为例,打开数据手册的DMA章节,找到请求映射表,我们可以看到SPI1的RX和TX请求都映射到了通道3。这意味着我们可以使用DMA2的Stream0和Stream3来分别处理SPI1的接收和发送。

选择DMA流时需要注意,同一通道的不同流不能同时使用,因为它们共享相同的通道资源。这就好比一条高速公路(通道)上有多个车道(流),但同一时间每个车道只能有一辆车行驶。

我在实际项目中通常这样配置:

  • SPI1_RX使用DMA2_Stream0
  • SPI1_TX使用DMA2_Stream3

这样的配置在实践中表现稳定,中断冲突的概率很小。

3. 详细配置步骤与代码实现

3.1 DMA初始化配置

配置DMA是整个过程中最关键的环节。我们需要仔细设置每个参数,确保数据传输的准确性和效率。以下是我在项目中经过验证的配置代码:

void flash_start_dma(uint8_t *buffer, uint32_t length, uint8_t isread)
{
    uint32_t temp = 0xffffffff;
    DMA_InitTypeDef DMA_InitStructure;
    
    // 初始化DMA结构体
    DMA_StructInit(&DMA_InitStructure);
    DMA_DeInit(DMA2_Stream0);  // RX流
    DMA_DeInit(DMA2_Stream3);  // TX流
    
    // 等待DMA流禁用完成
    while(DMA_GetCmdStatus(DMA2_Stream0) != DISABLE);
    while(DMA_GetCmdStatus(DMA2_Stream3) != DISABLE);

    /* 配置SPI1_RX DMA */
    DMA_InitStructure.DMA_Channel = DMA_Channel_3;
    DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&SPI1->DR;
    
    if (isread == 1) {
        // 读操作:将接收到的数据存储到buffer中
        DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)buffer;
        DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
    } else {
        // 写操作:接收的数据丢弃,地址不递增
        DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&temp;
   
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值