采樣DMA的原理和配置方法
因為ADC規則組數據寄存器ADC_DR只有一個,如果使用多通道轉換,那轉換的數據就全部都擠在ADC_DR里面了,前一個時間點轉換的通道數據,就會被下一個時間點的另外一個通道轉換的數據覆蓋掉,所以當通道轉換完成后就應該把數據取走,或者開啟DMA模式,把數據傳輸到內存里面,不然就會造成數據的覆蓋。多通道ADC采集一般使用DMA進行數據傳輸,該方法更加高效方便。
注:只有ADC1擁有DMA功能。由ADC2轉化的數據可以通過雙ADC模式,利用ADC1的 DMA功能傳輸。
DMA間接
直接存儲器存取(DMA)用來提供在外設和存儲器之間或者存儲器和存儲器之間的高速數據傳輸。無須CPU干預,數據可以通過DMA快速地移動,這就節省了CPU的資源來做其他操作。兩個DMA控制器有12個通道(DMA1有7個通道,DMA2有5個通道),每個通道專門用來管理來自于一個或多個外設對存儲器訪問的請求。ADC1使用的是DMA1的通道1。
DMA初始化結構體詳解
DMA_InitTypeDef初始化結構體結構體用于設置DMA的工作參數,其具體的定義如下:
typedef struct
{
uint32_t DMA_PeripheralBaseAddr;
uint32_t DMA_MemoryBaseAddr;
uint32_t DMA_DIR;
uint32_t DMA_BufferSize;
uint32_t DMA_PeripheralInc;
uint32_t DMA_MemoryInc;
uint32_t DMA_PeripheralDataSize;
uint32_t DMA_MemoryDataSize;
uint32_t DMA_Mode;
uint32_t DMA_Priority;
uint32_t DMA_M2M;
}DMA_InitTypeDef;
1) DMA_PeripheralBaseAddr:外設地址,設定DMA_CPAR寄存器的值;一般設置為外設的數據寄存器地址,如果是存儲器到存儲器模式則設置為其中一個存儲器地址。我么是把ADC采集到的數據通過DMA傳輸到存儲器上,則外設地址為ADC的數據寄存器。
2) DMA_Memory0BaseAddr:存儲器地址,設定DMA_CMAR寄存器值;一般設置為我們自定義的用來存放ADC數據的數組地址。
3) DMA_DIR:傳輸方向選擇,可選外設到存儲器、存儲器到外設。它設定 DMA_CCR寄存器的DIR[1:0]位的值。這里并沒有存儲器到存儲器的方向選擇,當使用存儲器到存儲器時,只需要把其中一個存儲器當作外設使用即可。本章選擇為外設到存儲器。
4) DMA_Bu?erSize:設定待傳輸數據數目,初始化設定DMA_CNDTR寄存器的值,其大小等于我們定義的存儲ADC數據的數組大小。
5)DMA_PeripheralInc:如果配置為 DMA_PeripheralInc_Enable,使能外設地址自動遞增功能,它設定DMA_CCR寄存器的PINC位的值;因為ADC轉換的數據都存放在一個數據寄存器中,則外設地址不變。
6) DMA_MemoryInc:如果配置為 DMA_MemoryInc_Enable,使能存儲器地址自動遞增功能,它設定DMA_CCR寄存器的MINC位的值;因為我們自定義的數組用來存放兩個數據,所以要使能存儲器地址自動遞增功能。
7) DMA_PeripheralDataSize:外設數據寬度,可選字節(8位)、半字(16位) 和字(32位),它設定DMA_CCR寄存器的PSIZE[1:0]位的值。
8) DMA_MemoryDataSize:存儲器數據寬度,可選字節(8位)、半字(16位) 和字(32位),它設定DMA_CCR寄存器的MSIZE[1:0]位的值。外設和存儲器單位均為兩個字節。
9) DMA_Mode:DMA傳輸模式選擇,可選一次傳輸或者循環傳輸,它設定 DMA_CCR寄存器的CIRC位的值。例程我們的ADC采集是持續循環進行的,所以使用循環傳輸模式。當啟動了循環模式,數據傳輸的數目變為0時,將會自動地被恢復成配置通道時設置的初值,DMA操作將會繼續進行。
ADC的工作參數配置
// 只使用一個ADC,屬于單模式
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
// 掃描模式
ADC_InitStructure.ADC_ScanConvMode = ENABLE ;
// 連續轉換模式
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
// 不用外部觸發轉換,軟件開啟即可
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
// 轉換結果右對齊
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
// 轉換通道個數
ADC_InitStructure.ADC_NbrOfChannel = 2;
// 初始化ADC
ADC_Init(ADC1, &ADC_InitStructure);
// 配置ADC時鐘N狿CLK2的8分頻,即9MHz
RCC_ADCCLKConfig(RCC_PCLK2_Div8);
// 配置ADC 通道的轉換順序和采樣時間
ADC_RegularChannelConfig(ADC1, ADC_CHANNEL1, 1, ADC_SampleTime_55Cycles5);
ADC_RegularChannelConfig(ADC1, ADC_CHANNEL2, 2, ADC_SampleTime_55Cycles5);
// 使能ADC DMA 請求
ADC_DMACmd(ADC1, ENABLE);
// 開啟ADC ,并開始轉換
ADC_Cmd(ADC1, ENABLE);
// 初始化ADC 校準寄存器
ADC_ResetCalibration(ADC1);
// 等待校準寄存器初始化完成
while(ADC_GetResetCalibrationStatus(ADC1));
// ADC開始校準
ADC_StartCalibration(ADC1);
// 等待校準完成
while(ADC_GetCalibrationStatus(ADC1));
// 由于沒有采用外部觸發,所以使用軟件觸發ADC轉換
ADC_SoftwareStartConvCmd(ADC1, ENABLE);
因為只是使用一個 ADC,所以模式配置為獨立模式;例程中使用了ADC1的兩個通道進行采集,因此需要開啟掃描模式,當一個通道轉換結束時,同一組的下一個通道將被自動轉換;例程實現不間斷的對外部模擬數據進行采集,因此使能連續轉換模式。ADC的轉換采用軟件觸發的方式,因此不使用外部觸發轉換信號。轉換結果右對齊;轉換通道數為2;因為是兩個通道進行采集,所以調用ADC_RegularChannelConfig()函數設置每個通道的轉換順序和采樣時間。
-
寄存器
+關注
關注
31文章
5225瀏覽量
118949 -
存儲器
+關注
關注
38文章
7317瀏覽量
162883 -
adc
+關注
關注
97文章
6229瀏覽量
541812 -
dma
+關注
關注
3文章
549瀏覽量
99780
原文標題:MCU微課堂|CKS32F107xx系列 ADC(二)
文章出處:【微信號:中科芯MCU,微信公眾號:中科芯MCU】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論