天天看点

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

总结一下:

我的理解是一次传输多个数据,不管你的数据是8位,16位还是32位,也就相当于你接收数据部分缓存的数据量。buf[buf_size],就是这个bufe_size。

1.看库函数中

DMAy_Channelx->CNDTR = DMA_InitStruct->DMA_BufferSize;

而CNDTR即数据传输数量 (Number of data to transfer)

数据传输数量为0至65535。这个寄存器只能在通道不工作(DMA_CCRx的EN=0)时写入。通

道开启后该寄存器变为只读,指示剩余的待传输字节数目。寄存器内容在每次DMA传输后递

减。

数据传输结束后,寄存器的内容或者变为0;或者当该通道配置为自动重加载模式时,寄存

器的内容将被自动重新加载为之前配置时的数值。

当寄存器的内容为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的地址属于不被定义的内容。从编程角度,它使用了未知的区域,如果这个地址定义别的变量,那么就会误操作这个变量。

ysmz4:可以将DMA_SetCurrDataCounter(DMA2_Channel3,R_B_SIZE); //设置传输数据长度

改成DMA_SetCurrDataCounter(DMA2_Channel3,n);    //n为实际用到的大小

我觉得就可以避免这个问题。

__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覆盖了。