stm32 文件系统dma大小_stm32 DMA 的 buffersize 意义与设置?

最近也在学习,个人见解。

1、DMA_BufferSize到底是什么?

Specifies the buffer size, in data unit, of the specified Channel. The data unit is equal to the configuration set in DMA_PeripheralDataSize or DMA_MemoryDataSize members depending in the transfer direction

其实,这个缓冲区概念不是很准确,准确的应该是每次DMA传输的数据数量。在库函数stm32f10x_dma.c中可以找到:

DMAy_Channelx->CNDTR = DMA_InitStruct->DMA_BufferSize;

那这个 CNDTR 是什么呢?在STM32参考手册里有说明, Number of data to be transferred (0 up to 65535). The transfer stops once the DMA_CNDTRx register reaches zero. 它就是一个计数器,这个计数器的值就是DMA_BufferSize,每传送一个数据就减一,变成0的时候,从ADC外设到内存的传输(或相反)停止。此时可产生中断信号。假设DMA_BufferSize=10,那么ADC采集10次后,DMA就停止传输ADC的采集数据了。

那为啥取名叫buffer 呢,我猜是为了和DMA_MemoryInc_Enable配合。虽然传输计数是减少的,但是内存地址是增长的。在声明DMA_MemoryBaseAddr时候,其实DMA的就指向(是指向,不是开辟!)一个大小为DMA_BufferSize的数组,数组的开始地址为DMA_MemoryBaseAddr。这个数组就是缓冲区。

每次ADC采样后,就通过DMA把数据放在内存中,从DMA_MemoryBaseAddr+0地址开始放,直到DMA_MemoryBaseAddr+DMA_BufferSize-1,此时CNDTR变成0,传输结束。

2、DMA_BufferSize的大小应该取多少?

上面的讨论很多同学就疑惑了,这个大小应该取多少呢?暂时我建议你需要多少数据就写多少。

__IO uint16_t ADC_ConvertedValue[NUM];

一般,我们会定义一个变量存我们的数据,然后

DMA_InitStruct.DMA_BufferSize = NUM;

DMA_InitStruct.DMA_MemoryBaseAddr = (u32)&ADC_ConvertedValue;

这时候,缓冲区的大小和我们定义的数组一致,也方便我们操作。

但是如果DMA_BufferSize大于NUM会怎么样?根据上面问题1的解释,缓冲区地址其实就是我们的ADC_ConvertedValue地址,如果DMA_BufferSize为NUM+N,其实缓冲区就是ADC_ConvertedValue[NUM+N],再说一遍,Buffer的首地址和ADC_ConvertedValue相同,如果我们用指针访问,可以很好的验证。

__IO uint16_t *p;

p=ADC_ConvertedValue;

省略代码,printf是串口通信改写的函数….

printf(“%4x\n”,ADC_ConvertedValue[NUM-1]);

printf(“%4x\n”,*(p+NUM));

printf(“%4x\n”,*(p+NUM+1));

你会很吃惊的发现,*(p+NUM)里面也有我们采样的数据。如果我们用ADC_ConvertedValue[NUM]访问则会出错,因为超出数组范围了。也就是说DMA_BufferSize可以大于NUM,但是大于NUM的地址属于不被定义的内容。从编程角度,它使用了未知的区域,如果这个地址定义别的变量,那么就会误操作这个变量。

__IO uint16_t ADC_ConvertedValue[NUM];

__IO uint16_t a[N];

比如我们定义时候,紧跟ADC_ConvertedValue定义一个a;一般编译器会把这两个变量的地址连在一起。那么在运行程序时候:

printf(“%4x\n”,ADC_ConvertedValue[NUM-1]);

printf(“%4x\n”,*(p+NUM));

printf(“%4x\n”,ADC_ConvertedValue[NUM-1]);

printf(“%4x\n”,a[0]);

是一样的数据。

很危险吧。a[0]的数据就被DMA覆盖了。

  • 7
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
STM32F4的DMA乒乓缓冲区是一种用于数据传输的缓冲区。它使用两个缓冲区,一个用于DMA传输,另一个用于CPU处理。当DMA传输完成后,它会切换到另一个缓冲区,以便CPU可以开始处理数据,同时DMA可以使用另一个缓冲区开始传输。这种技术可以显著提高数据传输效率,并减少CPU的负担。 在STM32F4中,可以使用CubeMX生成代码来配置DMA乒乓缓冲区。以下是一个简单的示例: 1. 打开CubeMX并选择您的STM32F4设备。 2. 转到“Pinout & Configuration”选项卡,并启用您要使用的DMA通道。 3. 转到“DMA Settings”选项卡,并启用“Double Buffer Mode”选项。 4. 选择要使用的DMA缓冲区大小。 5. 生成代码并在您的项目中使用它。 以下是一个示例代码片段,演示如何使用DMA乒乓缓冲区进行数据传输: ```c // 设置DMA传输的源和目的地 HAL_DMA_Start_IT(&hdma_memtomem_dma2_stream0, (uint32_t)src_buffer, (uint32_t)dst_buffer, BUFFER_SIZE); // 在DMA传输期间处理数据 for (int i = 0; i < BUFFER_SIZE; i++) { // 处理数据 } // DMA传输完成后切换到另一个缓冲区 void HAL_DMA_MultiBufferTransferComplete(DMA_HandleTypeDef *hdma) { if (hdma == &hdma_memtomem_dma2_stream0) { if (hdma->Instance->CR & DMA_SxCR_CT) { // DMA传输完成,切换到第一个缓冲区 HAL_DMAEx_ChangeMemory(&hdma_memtomem_dma2_stream0, (uint32_t)src_buffer, (uint32_t)dst_buffer); } else { // DMA传输完成,切换到第二个缓冲区 HAL_DMAEx_ChangeMemory(&hdma_memtomem_dma2_stream0, (uint32_t)dst_buffer, (uint32_t)src_buffer); } } } ``` 在上面的示例中,我们使用了一个名为“hdma_memtomem_dma2_stream0”的DMA句柄来启动DMA传输,并在传输期间处理数据。一旦DMA传输完成,我们使用“HAL_DMAEx_ChangeMemory”函数切换到另一个缓冲区。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值