你观察到的现象非常典型,涉及了SPI+DMA接收数据后如何正确访问内存数据的问题,尤其是当使用DMA传输后,是否可以直接通过指针或变量访问DMA缓冲区中的数据。
我们来一步步分析你的问题:
一、现象简述
你使用 SPI + DMA 接收了200个字节的数据,其中前几个字节是标准WAV文件的头部信息,例如:
前4字节为 'RIFF'(对应十六进制为 52 49 46 46),验证是正确的。
接下来的4个字节是文件长度,为大端格式(Big-endian):00 08 9A 24,理论上应组合为 0x00089A24。
你尝试用一个32位变量(如 uint32t)来读取这4个字节的数据,结果得到错误值。但当你使用 printf 输出时却得到了正确的值。
二、可能的原因分析
1. DMA传输完成后缓存未刷新(Cache Coherency)
如果你的MCU/MPU支持数据缓存(D-Cache),而DMA写入的内存区域是被缓存的区域,那么CPU读取该区域时可能会读到缓存中的旧数据,而不是DMA写入的最新数据。
🔍 关键点:DMA写入的是物理内存,而CPU可能从缓存中读取旧值。
解决办法:
在DMA传输完成之后,手动刷新或无效化缓存(Cache Invalidate)相关内存区域。
例如在STM32 HAL中可以使用:
- c
- SCBInvalidateDCachebyAddr((uint32t )buffer, size);
复制代码
或者在设计DMA缓冲区时将其设置为非缓存(Non-cacheable)区域。
2. 内存对齐问题(Unaligned Access)
某些架构(如ARM Cortex-M7)在访问非对齐的32位数据时会触发硬件异常或返回错误值。
例如你这样读取:- c
- uint32t p = &buffer[4];
- value = p;
复制代码
如果 buffer 是 uint8t 类型数组,且 buffer[4] 没有按4字节对齐,则可能导致未对齐访问错误。
解决办法:
使用 memcpy 强制复制4个字节到变量中:
- c
- uint32t value;
- memcpy(&value, &buffer[4], 4);
复制代码
或者使用联合体(union)方式处理。
3. 大小端(Endianness)转换问题
你在描述中提到是大端(Big-endian)数据,但MCU通常是小端(Little-endian)。如果你直接用指针访问4个字节组成一个 uint32t,那结果会是错误的,除非你手动做大小端转换。
解决办法:
手动拼接:
```c
value = (buffer[4]
[本文内容由国芯人工智能辅助生成,仅供参考] |