標籤:

ADC模數轉換(二)——獨立模式多通道電壓採集實驗

接上篇文章ADC模數轉換(一)——獨立模式單通道電壓採集實驗,這篇講了ADC的基礎以及獨立模式單通道採集實驗。現在將介紹獨立模式的多通道採集實驗,還會有一篇文章介紹雙重ADC模式的採集實驗。

這個實驗和上篇文章相比,只是通道多了,使用了DMA代替中斷讀取的方式,所以在上個實驗的基礎上,稍加修改即可。

現在我們需要先確定ADC和DMA的配置關係。

查閱參考手冊DMA篇章可得,ADC1對應DMA1的通道1,ADC3對應DMA2的通道5,而ADC2則沒有DMA功能。如圖22-1,圖22-2。所以,這裡我們選擇ADC1,其對應了DMA1的通道1。

圖22-1

圖22-2

接下來確定使用ADC1的哪些通道。查閱數據手冊(Table 5. High-density STM32F103xx pin definitions)可知,PC0~PC3對應ADC1/2/3_IN10~ADC1/2/3_IN13,我們就選這4個引腳。然後可以開始配置了。

ADC的GPIO配置

PC0~PC3四個引腳都需要配置,引腳模式都是模擬輸入。

/** * @brief ADC的GPIO配置 * @param 無 * @retval 無 */static void ADC1_GPIO_Config(void){ GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; // 模擬輸入 GPIO_Init(GPIOC, &GPIO_InitStructure); }

ADC配置

包括DMA和ADC1的配置說明,比較簡單,有關DMA也在之前的文章有介紹,所以直接在下面的程序里通過注釋簡單說明了。

__IO uint16_t ADC_ConvertedValue[4] = {0, 0, 0, 0};/** * @brief ADC配置 * @param 無 * @retval 無 */static void ADC1_Mode_Config(void){ /*------------------- DMA配置 -------------------*/ DMA_InitTypeDef DMA_InitStructure; RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); DMA_DeInit(DMA1_Channel1); // 複位DMA DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)(&(ADC1->DR)); // 外設基地址為ADC1_DR寄存器地址 DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)ADC_ConvertedValue; // 內存存儲地址,即ADC_ConvertedValue數組的首地址 DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; // 數據來源於外設 DMA_InitStructure.DMA_BufferSize = 4; // 緩衝區大小,這裡為ADC_ConvertedValue數組的長度 DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; // 只有ADC1一個外設,所以地址不遞增 DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; // 內存存儲地址遞增 DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; // 外設數據大小為半字,即兩個位元組 DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; // 內存存儲大小也為半字,即兩個位元組 DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; // 循環傳輸 DMA_InitStructure.DMA_Priority = DMA_Priority_High; // DMA通道優先順序為高,當使用一個DMA通道時,優先順序設置不受影響 DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; // 外設到內存模式 DMA_Init(DMA1_Channel1, &DMA_InitStructure); DMA_Cmd(DMA1_Channel1, ENABLE); /*------------------- ADC配置 -------------------*/ ADC_InitTypeDef ADC_InitStruct; RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE); ADC_InitStruct.ADC_Mode = ADC_Mode_Independent; // 獨立模式,只使用一個ADC ADC_InitStruct.ADC_ScanConvMode = ENABLE; // 掃描模式 ADC_InitStruct.ADC_ContinuousConvMode = ENABLE; // 連續轉換 ADC_InitStruct.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; // 不使用外部觸發,用軟體觸發 ADC_InitStruct.ADC_DataAlign = ADC_DataAlign_Right; // 轉換結果右對齊 ADC_InitStruct.ADC_NbrOfChannel = 4; // 轉換通道數量 ADC_Init(ADC1, &ADC_InitStruct); RCC_ADCCLKConfig(RCC_PCLK2_Div8); // 8分頻,9MHz ADC_RegularChannelConfig(ADC1, ADC_Channel_10, 1, ADC_SampleTime_55Cycles5); // ADC轉換通道10,轉換順序1,採樣周期55.5 ADC_RegularChannelConfig(ADC1, ADC_Channel_11, 2, ADC_SampleTime_55Cycles5); // ADC轉換通道11,轉換順序2,採樣周期55.5 ADC_RegularChannelConfig(ADC1, ADC_Channel_12, 3, ADC_SampleTime_55Cycles5); // ADC轉換通道12,轉換順序3,採樣周期55.5 ADC_RegularChannelConfig(ADC1, ADC_Channel_13, 4, ADC_SampleTime_55Cycles5); // ADC轉換通道13,轉換順序4,採樣周期55.5 ADC_DMACmd(ADC1, ENABLE); // 使能ADC的DMA請求 ADC_Cmd(ADC1, ENABLE); ADC_ResetCalibration(ADC1); // 初始化ADC校準寄存器 while(ADC_GetResetCalibrationStatus(ADC1)); // 等待校準寄存器初始化完成 ADC_StartCalibration(ADC1); // ADC開始校準 while(ADC_GetCalibrationStatus(ADC1)); // 等待校準完成 ADC_SoftwareStartConvCmd(ADC1, ENABLE); // 軟體觸發ADC轉換}

配置程序就只是完成ADC和DMA的配置,配置項多了點,其實並不複雜。

由於採用了DMA的方式代替了中斷讀取的方式,所以直接main()函數里將讀取到的值轉換成可讀的模擬電壓值。

extern __IO uint16_t ADC_ConvertedValue[4];float ADC_ConvertedValueLocal[4];ADC_ConvertedValueLocal[0] = (float)ADC_ConvertedValue[0] / 4096 * 3.3;ADC_ConvertedValueLocal[1] = (float)ADC_ConvertedValue[1] / 4096 * 3.3;ADC_ConvertedValueLocal[2] = (float)ADC_ConvertedValue[2] / 4096 * 3.3;ADC_ConvertedValueLocal[3] = (float)ADC_ConvertedValue[3] / 4096 * 3.3;printf("
CH10 value = %f V
", ADC_ConvertedValueLocal[0]);printf("
CH11 value = %f V
", ADC_ConvertedValueLocal[1]);printf("
CH12 value = %f V
", ADC_ConvertedValueLocal[2]);printf("
CH13 value = %f V
", ADC_ConvertedValueLocal[3]);

關於轉換公式,可參考ADC模數轉換(一)——獨立模式單通道電壓採集實驗。

有一點需要注意,每個轉換的ADC通道引腳都需要為其提供電源輸入,以作為待測電壓進行轉換。可以用杜邦線連接開發板上的3V3電源輸入。

-----------------------------------------------------------------------

文章首發於知乎專欄 - stm32,轉載請私信,並註明原文出處。

推薦閱讀:

下路榮耀行刑官德萊文+眾星之子索拉卡的組合怎麼打?
如何公平客觀的評價EDG ADC選手deft?
ADC模數轉換(一)——獨立模式單通道電壓採集實驗
ADC模數轉換(三)——雙重ADC同步規則模式電壓採集實驗

TAG:ADC |