總結一下:
我的了解是一次傳輸多個資料,不管你的資料是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覆寫了。