裸機--ADC
- 簡介
- STM32f103 系列有 3 個 ADC,精度為 12 位,每個 ADC 最多有 16 個外部通道。
- 其中ADC1 和 ADC2 都有 16 個外部通道,ADC3 根據 CPU 引腳的不同通道數也不同,一般都有8 個外部通道。
- 功能
- 電壓輸入范圍:
- ADC 輸入范圍為:VREF- ≤ VIN ≤ VREF+。由 VREF-、VREF+ 、VDDA 、VSSA、這四個外部引腳決定.
- 一般把 VSSA 和 VREF-接地,把 VREF+和 VDDA 接 3V3,得到ADC 的輸入電壓范圍為:0~3.3V。
- 電壓范圍變寬
- 外部電壓轉換為0-3.3V.
- 輸入通道
- 外部通道(最多16道)
- ADCx_IN0~~ADCx_IN15
- 內部通道
- ADC1 的通道 16 連接到了芯片內部的溫度傳感器,Vrefint 連接到了通道 17。
- ADC2 的模擬通道 16 和 17 連接到了內部的 VSS。
- ADC3 的模擬通道 9、14、15、16 和 17 連接到了內部的 VSS。

- 規則通道
- 注入通道
- 觸發源
- ADC控制寫0/1
- 定時器觸發
- 外部IO觸發
- 轉換時間
- 時鍾
- ADC 輸入時鍾 ADC_CLK 由 PCLK2 經過分頻產生,最大是 14M,
- 采樣時間
- 采樣周期最小1.5個周期
- Tconv = 采樣時間 +12.5 個周期。當 ADCLK = 14MHZ (最高),采樣時間設置為 1.5 周期(最快),
- 那么總的轉換時間(最短)Tconv = 1.5 周期 + 12.5 周期 = 14 周期 = 1us。
- 一般我們設置 PCLK2=72M,經過 ADC 預分頻器能分頻到最大的時鍾只能是 12M,采樣周期設置為 1.5 個周期,算出最短的轉換時間為 1.17us,這個才是最常用的。
- 中斷
- 轉換結束中斷
- 規則通道轉換結束中斷和注入轉換通道轉換結束中斷
- 規則和注入通道轉換結束后,除了產生中斷外,還可以產生 DMA 請求,把轉換好的數據直接存儲在內存里面。要注意的是只有 ADC1 和 ADC3 可以產生 DMA 請求.
- 模擬看門狗中斷
- 當被 ADC 轉換的模擬電壓低於低閾值或者高於高閾值時,就會產生中斷,前提是我們開啟了模擬看門狗中斷,其中低閾值和高閾值由 ADC_LTR 和 ADC_HTR 設置。例如我們設置高閾值是 2.5V,那么模擬電壓超過 2.5V 的時候,就會產生模擬看門狗中斷,反之低閾值也一樣。
- 電壓轉換
- ADC是 12 位的,那么 12 位滿量程對應的就是 3.3V,12 位滿量程對應的數字值是:2^12。數值0 對應的就是 0V。如果轉換后的數值為 X ,X 對應的模擬電壓為 Y,那么會有這么一個等式成立: 2^12 / 3.3 = X / Y,=> Y = (3.3 * X ) / 2^12。
- 流程--獨立模式單通道
- 1) 初始 ADC 用到的 GPIO;
- 2) 設置 ADC 的工作參數並初始化;
- 3) 設置 ADC 工作時鍾;
- 4) 設置 ADC 轉換通道順序及采樣時間;
- 5) 配置使能 ADC 轉換完成中斷,在中斷內讀取轉換完數據;
- 6) 使能 ADC;
- 7) 使能軟件觸發 ADC 轉換。
- ADC 轉換結果數據使用中斷方式讀取,這里沒有使用 DMA 進行數據傳輸。

/* 獨立模式單通道 */ /* ADC 宏定義 */ 1 // ADC 編號選擇 2 // 可以是 ADC1/2,如果使用 ADC3,中斷相關的宏要改成 ADC3 的 3 #define ADC_APBxClock_FUN RCC_APB2PeriphClockCmd 4 #define ADCx ADC2 5 #define ADC_CLK RCC_APB2Periph_ADC2 6 7 // ADC GPIO 宏定義 8 // 注意:用作 ADC 采集的 IO 必須沒有復用,否則采集電壓會有影響 9 #define ADC_GPIO_APBxClock_FUN RCC_APB2PeriphClockCmd 10 #define ADC_GPIO_CLK RCC_APB2Periph_GPIOC 11 #define ADC_PORT GPIOC 12 #define ADC_PIN GPIO_Pin_1 13 // ADC 通道宏定義 14 #define ADC_CHANNEL ADC_Channel_11 15 16 // ADC 中斷相關宏定義 17 #define ADC_IRQ ADC1_2_IRQn 18 #define ADC_IRQHandler ADC1_2_IRQHandler /* ADC GPIO 初始化 */ 1 static void ADCx_GPIO_Config(void) 2 { 3 GPIO_InitTypeDef GPIO_InitStructure; 4 5 // 打開 ADC IO 端口時鍾 6 ADC_GPIO_APBxClock_FUN ( ADC_GPIO_CLK, ENABLE ); 7 8 // 配置 ADC IO 引腳模式 9 // 必須為模擬輸入 10 GPIO_InitStructure.GPIO_Pin = ADC_PIN; 11 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; 12 13 // 初始化 ADC IO 14 GPIO_Init(ADC_PORT, &GPIO_InitStructure); 15 } /* ADC 工作模式配置 */ 1 static void ADCx_Mode_Config(void) 2 { 3 ADC_InitTypeDef ADC_InitStructure; 4 5 // 打開 ADC 時鍾 6 ADC_APBxClock_FUN ( ADC_CLK, ENABLE ); 7 8 // ADC 模式配置 9 // 只使用一個 ADC,屬於獨立模式 10 ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; 11 12 // 禁止掃描模式,多通道才要,單通道不需要 13 ADC_InitStructure.ADC_ScanConvMode = DISABLE ; 14 15 // 連續轉換模式 16 ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; 17 18 // 不用外部觸發轉換,軟件開啟即可 19 ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; 20 21 // 轉換結果右對齊 22 ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; 23 24 // 轉換通道 1 個 25 ADC_InitStructure.ADC_NbrOfChannel = 1; 26 27 // 初始化 ADC 28 ADC_Init(ADCx, &ADC_InitStructure); 29 30 // 配置 ADC 時鍾為 PCLK2 的 8 分頻,即 9MHz 31 RCC_ADCCLKConfig(RCC_PCLK2_Div8); 32 33 // 配置 ADC 通道轉換順序和采樣時間 34 ADC_RegularChannelConfig(ADCx, ADC_CHANNEL, 1, 35 ADC_SampleTime_55Cycles5); 36 37 // ADC 轉換結束產生中斷,在中斷服務程序中讀取轉換值 38 ADC_ITConfig(ADCx, ADC_IT_EOC, ENABLE); 39 40 // 開啟 ADC ,並開始轉換 41 ADC_Cmd(ADCx, ENABLE); 42 43 // 初始化 ADC 校准寄存器 44 ADC_ResetCalibration(ADCx); 45 // 等待校准寄存器初始化完成 46 while (ADC_GetResetCalibrationStatus(ADCx)); 47 48 // ADC 開始校准 49 ADC_StartCalibration(ADCx); 50 // 等待校准完成 51 while (ADC_GetCalibrationStatus(ADCx)); 52 53 // 由於沒有采用外部觸發,所以使用軟件觸發 ADC 轉換 54 ADC_SoftwareStartConvCmd(ADCx, ENABLE); 55 } /* ADC中斷配置 */ 1 static void ADC_NVIC_Config(void) 2 { 3 NVIC_InitTypeDef NVIC_InitStructure; 4 5 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1); 6 7 NVIC_InitStructure.NVIC_IRQChannel = ADC_IRQ; 8 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; 9 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; 10 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; 11 12 NVIC_Init(&NVIC_InitStructure); 13 } /* ADC中斷服務函數 */ 1 void ADC_IRQHandler(void) 2 { 3 if (ADC_GetITStatus(ADCx,ADC_IT_EOC)==SET) { 4 // 讀取 ADC 的轉換值 5 ADC_ConvertedValue = ADC_GetConversionValue(ADCx); 6 7 } 8 ADC_ClearITPendingBit(ADCx,ADC_IT_EOC); 9 10 } /* 主函數 */ 1 int main(void) 2 { 3 // 配置串口 4 USART_Config(); 5 6 // ADC 初始化 7 ADCx_Init(); 8 9 printf("\r\n ----這是一個 ADC 單通道中斷讀取實驗----\r\n"); 10 11 while (1) 12 { 13 ADC_ConvertedValueLocal =(float) ADC_ConvertedValue/4096*3.3; 14 15 printf("\r\n The current AD value = 0x%04X \r\n", 16 ADC_ConvertedValue); 17 printf("\r\n The current AD value = %f V \r\n", 18 ADC_ConvertedValueLocal); 19 printf("\r\n\r\n"); 20 21 Delay(0xffffee); 22 } 23 }
- 流程2--獨立模式多通道
- 1) 初始化 ADC GPIO;
- 2) 初始化 ADC 工作參數;
- 3) 配置 DMA 工作參數;
- 4) 讀取 ADC 采集的數據;
- ADC 轉換結果數據使用 DMA 方式傳輸至指定的存儲區,這樣取代單通道實驗使用中斷服務的讀取方法。實際上,多通道 ADC 采集一般使用 DMA 數據傳輸方式更加高效方便。

/* 獨立模式多通道采集 */ /* 宏定義 */ 1 // ADC 宏定義 2 #define ADCx ADC1 3 #define ADC_APBxClock_FUN RCC_APB2PeriphClockCmd 4 #define ADC_CLK RCC_APB2Periph_ADC1 5 6 #define ADC_GPIO_APBxClock_FUN RCC_APB2PeriphClockCmd 7 #define ADC_GPIO_CLK RCC_APB2Periph_GPIOC 8 #define ADC_PORT GPIOC 9 10 // 轉換通道個數 11 #define NOFCHANEL 5 12 13 #define ADC_PIN1 GPIO_Pin_0 14 #define ADC_CHANNEL1 ADC_Channel_10 15 16 #define ADC_PIN2 GPIO_Pin_1 17 #define ADC_CHANNEL2 ADC_Channel_11 18 19 #define ADC_PIN3 GPIO_Pin_3 20 #define ADC_CHANNEL3 ADC_Channel_13 21 22 #define ADC_PIN4 GPIO_Pin_4 23 #define ADC_CHANNEL4 ADC_Channel_14 24 25 #define ADC_PIN5 GPIO_Pin_5 26 #define ADC_CHANNEL5 ADC_Channel_15 27 28 // ADC1 對應 DMA1 通道 1,ADC3 對應 DMA2 通道 5,ADC2 沒有 DMA 功能 29 #define ADC_DMA_CHANNEL DMA1_Channel1 /* ADC GPIO 初始化 */ 1 static void ADCx_GPIO_Config(void) 2 { 3 GPIO_InitTypeDef GPIO_InitStructure; 4 5 // 打開 ADC IO 端口時鍾 6 ADC_GPIO_APBxClock_FUN ( ADC_GPIO_CLK, ENABLE ); 7 8 /* 配置 ADC IO 引腳模式 GPIO用於adc必須模擬輸入模式 */ 9 GPIO_InitStructure.GPIO_Pin = ADC_PIN1 10 |ADC_PIN2 11 |ADC_PIN3 12 |ADC_PIN4 13 |ADC_PIN5; 14 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; 15 // 初始化 ADC IO 16 GPIO_Init(ADC_PORT, &GPIO_InitStructure); 17 } /* ADC 工作模式配置 */ 1 static void ADCx_Mode_Config(void) 2 { 3 DMA_InitTypeDef DMA_InitStructure; 4 ADC_InitTypeDef ADC_InitStructure; 5 6 // 打開 DMA 時鍾 7 RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); 8 // 打開 ADC 時鍾 9 ADC_APBxClock_FUN ( ADC_CLK, ENABLE ); 10 11 /* ------------------DMA 模式配置---------------- */ 12 // 復位 DMA 控制器 13 DMA_DeInit(ADC_DMA_CHANNEL); 14 // 配置 DMA 初始化結構體 15 // 外設基址為:ADC 數據寄存器地址 16 DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)(&( ADCx->DR )); 17 // 存儲器地址 18 DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)ADC_ConvertedValue; 19 // 數據源來自外設 20 DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; 21 // 緩沖區大小,應該等於數據目的地的大小 22 DMA_InitStructure.DMA_BufferSize = NOFCHANEL; 23 // 外設寄存器只有一個,地址不用遞增 24 DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; 25 // 存儲器地址遞增 26 DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; 27 // 外設數據大小為半字,即兩個字節 28 DMA_InitStructure.DMA_PeripheralDataSize = 29 DMA_PeripheralDataSize_HalfWord; 30 // 內存數據大小也為半字,跟外設數據大小相同 31 DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; 32 // 循環傳輸模式 33 DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; 34 // DMA 傳輸通道優先級為高,當使用一個 DMA 通道時,優先級設置不影響 35 DMA_InitStructure.DMA_Priority = DMA_Priority_High; 36 // 禁止存儲器到存儲器模式,因為是從外設到存儲器 37 DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; 38 // 初始化 DMA 39 DMA_Init(ADC_DMA_CHANNEL, &DMA_InitStructure); 40 // 使能 DMA 通道 41 DMA_Cmd(ADC_DMA_CHANNEL , ENABLE); 42 43 /* ----------------ADC 模式配置--------------------- */ 44 // 只使用一個 ADC,屬於單模式 45 ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; 46 // 掃描模式 多通道所以掃描 47 ADC_InitStructure.ADC_ScanConvMode = ENABLE ; 48 // 連續轉換模式 49 ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; 50 // 不用外部觸發轉換,軟件開啟即可 51 ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; 52 // 轉換結果右對齊 53 ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; 54 // 轉換通道個數 55 ADC_InitStructure.ADC_NbrOfChannel = NOFCHANEL; 56 // 初始化 ADC 57 ADC_Init(ADCx, &ADC_InitStructure); 58 // 配置 ADC 時鍾為 PCLK2 的 8 分頻,即 9MHz 59 RCC_ADCCLKConfig(RCC_PCLK2_Div8); 60 // 配置 ADC 通道的轉換順序和采樣時間 61 ADC_RegularChannelConfig(ADCx, ADC_CHANNEL1, 1, 62 ADC_SampleTime_55Cycles5); 63 ADC_RegularChannelConfig(ADCx, ADC_CHANNEL2, 2, 64 ADC_SampleTime_55Cycles5); 65 ADC_RegularChannelConfig(ADCx, ADC_CHANNEL3, 3, 66 ADC_SampleTime_55Cycles5); 67 ADC_RegularChannelConfig(ADCx, ADC_CHANNEL4, 4, 68 ADC_SampleTime_55Cycles5); 69 ADC_RegularChannelConfig(ADCx, ADC_CHANNEL5, 5, 70 ADC_SampleTime_55Cycles5); 71 // 使能 ADC DMA 請求 72 ADC_DMACmd(ADCx, ENABLE); 73 // 開啟 ADC ,並開始轉換 74 ADC_Cmd(ADCx, ENABLE); 75 // 初始化 ADC 校准寄存器 76 ADC_ResetCalibration(ADCx); 77 // 等待校准寄存器初始化完成 78 while (ADC_GetResetCalibrationStatus(ADCx)); 79 // ADC 開始校准 80 ADC_StartCalibration(ADCx); 81 // 等待校准完成 82 while (ADC_GetCalibrationStatus(ADCx)); 83 // 由於沒有采用外部觸發,所以使用軟件觸發 ADC 轉換 84 ADC_SoftwareStartConvCmd(ADCx, ENABLE); 85 } /* 主函數 */ 1 int main(void) 2 { 3 // 配置串口 4 USART_Config(); 5 6 // ADC 初始化 7 ADCx_Init(); 8 9 printf("\r\n ----這是一個 ADC 多通道采集 DMA 讀取實驗----\r\n"); 10 11 while (1) 12 { 13 14 ADC_ConvertedValueLocal[0] =(float) 15 ADC_ConvertedValue[0]/4096*3.3; 16 ADC_ConvertedValueLocal[1] =(float) 17 ADC_ConvertedValue[1]/4096*3.3; 18 ADC_ConvertedValueLocal[2] =(float) 19 ADC_ConvertedValue[2]/4096*3.3; 20 ADC_ConvertedValueLocal[3] =(float) 21 ADC_ConvertedValue[3]/4096*3.3; 22 ADC_ConvertedValueLocal[4] =(float) 23 ADC_ConvertedValue[4]/4096*3.3; 24 25 printf("\r\n CH1 value = %f V \r\n",ADC_ConvertedValueLocal[0]); 26 printf("\r\n CH2 value = %f V \r\n",ADC_ConvertedValueLocal[1]); 27 printf("\r\n CH3 value = %f V \r\n",ADC_ConvertedValueLocal[2]); 28 printf("\r\n CH2 value = %f V \r\n",ADC_ConvertedValueLocal[3]); 29 printf("\r\n CH3 value = %f V \r\n",ADC_ConvertedValueLocal[4]); 30 31 printf("\r\n\r\n"); 32 Delay(0xffffee); 33 34 } 35 } 36
- 雙重ADC同步規則模式采集
- 雙重ADC作用:提高采樣率,彌補單個ADC采樣不夠快的缺點
- 雙重ADC模式
- 同步注入模式
- ADC1 和 ADC2 同時轉換一個注入通道組,其中 ADC1 為主,ADC2 為從。轉換的數據存儲在每個 ADC 接口的 ADC_JDRx 寄存器中。
- 同步規則模式
- ADC1 和 ADC2 同時轉換一個規則通道組,其中 ADC1 為主,ADC2 為從。ADC1 轉換的結果放在 ADC1_DR 的低 16 位,ADC2 轉換的結果放在 ADC1_DR 的高十六位。必須開啟DMA.
- 流程
- 1) 初始化 ADC GPIO;
- 2) 初始化 DMA 配置;
- 3) 初始化 ADC 參數;
- 4) 讀取 ADC 采集的數據,並打印出來校正;
- 注意
- ADC 工作模式要設置為同步規則模式;兩個 ADC 的通道的采樣時間需要一致;ADC1設置為軟件觸發;ADC2 設置為外部觸發。其他的基本一樣,看代碼注釋理解即可。

/* 宏定義 */ 1 // 雙模式時,ADC1 和 ADC2 轉換的數據都存放在 ADC1 的數據寄存器, 2 // ADC1 的在低十六位,ADC2 的在高十六位 3 // 雙 ADC 模式的第一個 ADC,必須是 ADC1 4 #define ADCx_1 ADC1 5 #define ADCx_1_APBxClock_FUN RCC_APB2PeriphClockCmd 6 #define ADCx_1_CLK RCC_APB2Periph_ADC1 7 8 #define ADCx_1_GPIO_APBxClock_FUN RCC_APB2PeriphClockCmd 9 #define ADCx_1_GPIO_CLK RCC_APB2Periph_GPIOC 10 #define ADCx_1_PORT GPIOC 11 #define ADCx_1_PIN GPIO_Pin_1 12 #define ADCx_1_CHANNEL ADC_Channel_11 13 14 // 雙 ADC 模式的第二個 ADC,必須是 ADC2 15 #define ADCx_2 ADC2 16 #define ADCx_2_APBxClock_FUN RCC_APB2PeriphClockCmd 17 #define ADCx_2_CLK RCC_APB2Periph_ADC2 18 19 #define ADCx_2_GPIO_APBxClock_FUN RCC_APB2PeriphClockCmd 20 #define ADCx_2_GPIO_CLK RCC_APB2Periph_GPIOC 21 #define ADCx_2_PORT GPIOC 22 #define ADCx_2_PIN GPIO_Pin_4 23 #define ADCx_2_CHANNEL ADC_Channel_14 24 25 #define NOFCHANEL 1 26 27 // ADC1 對應 DMA1 通道 1,ADC3 對應 DMA2 通道 5,ADC2 沒有 DMA 功能 28 #define ADC_DMA_CHANNEL DMA1_Channel1 /* ADC GPIO 初始化 */ 1 static void ADCx_GPIO_Config(void) 2 { 3 GPIO_InitTypeDef GPIO_InitStructure; 4 5 // ADCx_1 GPIO 初始化 6 ADCx_1_GPIO_APBxClock_FUN ( ADCx_1_GPIO_CLK, ENABLE ); 7 GPIO_InitStructure.GPIO_Pin = ADCx_1_PIN; 8 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; 9 GPIO_Init(ADCx_1_PORT, &GPIO_InitStructure); 10 11 // ADCx_2 GPIO 初始化 12 ADCx_1_GPIO_APBxClock_FUN ( ADCx_2_GPIO_CLK, ENABLE ); 13 GPIO_InitStructure.GPIO_Pin = ADCx_2_PIN; 14 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; 15 GPIO_Init(ADCx_2_PORT, &GPIO_InitStructure); 16 } /* 規則同步模式配置 */ 1 static void ADCx_Mode_Config(void) 2 { 3 DMA_InitTypeDef DMA_InitStructure; 4 ADC_InitTypeDef ADC_InitStructure; 5 6 // 打開 DMA 時鍾 7 RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); 8 // 打開 ADC 時鍾 9 ADCx_1_APBxClock_FUN ( ADCx_1_CLK, ENABLE ); 10 ADCx_2_APBxClock_FUN ( ADCx_2_CLK, ENABLE ); 11 12 /* ------------------DMA 模式配置---------------- */ 13 // 復位 DMA 控制器 14 DMA_DeInit(ADC_DMA_CHANNEL); 15 // 配置 DMA 初始化結構體 16 // 外設基址為:ADC 數據寄存器地址 17 DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)(&( ADCx_1->DR )); 18 // 存儲器地址 19 DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)ADC_ConvertedValue; 20 // 數據源來自外設 21 DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; 22 // 緩沖區大小,應該等於數據目的地的大小 23 DMA_InitStructure.DMA_BufferSize = NOFCHANEL; 24 // 外設寄存器只有一個,地址不用遞增 25 DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; 26 // 存儲器地址遞增 27 DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; 28 // 外設數據大小 29 DMA_InitStructure.DMA_PeripheralDataSize = 30 DMA_PeripheralDataSize_Word; 31 // 內存數據大小,跟外設數據大小相同 32 DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word; 33 // 循環傳輸模式 34 DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; 35 // DMA 傳輸通道優先級為高,當使用一個 DMA 通道時,優先級設置不影響 36 DMA_InitStructure.DMA_Priority = DMA_Priority_High; 37 // 禁止存儲器到存儲器模式,因為是從外設到存儲器 38 DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; 39 // 初始化 DMA 40 DMA_Init(ADC_DMA_CHANNEL, &DMA_InitStructure); 41 // 使能 DMA 通道 42 DMA_Cmd(ADC_DMA_CHANNEL , ENABLE); 43 44 /* ----------------ADCx_1 模式配置--------------------- */ 45 // 雙 ADC 的規則同步 46 ADC_InitStructure.ADC_Mode = ADC_Mode_RegSimult; 47 // 掃描模式 48 ADC_InitStructure.ADC_ScanConvMode = ENABLE ; 49 // 連續轉換模式 50 ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; 51 // 不用外部觸發轉換,軟件開啟即可 52 ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; 53 // 轉換結果右對齊 54 ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; 55 // 轉換通道個數 56 ADC_InitStructure.ADC_NbrOfChannel = NOFCHANEL; 57 // 初始化 ADC 58 ADC_Init(ADCx_1, &ADC_InitStructure); 59 // 配置 ADC 時鍾為 PCLK2 的 8 分頻,即 9MHz 60 RCC_ADCCLKConfig(RCC_PCLK2_Div8); 61 // 配置 ADC 通道的轉換順序和采樣時間 62 ADC_RegularChannelConfig(ADCx_1, ADCx_1_CHANNEL, 1, 63 ADC_SampleTime_239Cycles5); 64 // 使能 ADC DMA 請求 65 ADC_DMACmd(ADCx_1, ENABLE); 66 67 68 /* ----------------ADCx_2 模式配置--------------------- */ 69 // 雙 ADC 的規則同步 70 ADC_InitStructure.ADC_Mode = ADC_Mode_RegSimult; 71 // 掃描模式 72 ADC_InitStructure.ADC_ScanConvMode = ENABLE ; 73 // 連續轉換模式 74 ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; 75 // 不用外部觸發轉換,軟件開啟即可 76 ADC_InitStructure.ADC_ExternalTrigConv = 77 ADC_ExternalTrigConv_None; 78 // 轉換結果右對齊 79 ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; 80 // 轉換通道個數 81 ADC_InitStructure.ADC_NbrOfChannel = NOFCHANEL; 82 // 初始化 ADC 83 ADC_Init(ADCx_2, &ADC_InitStructure); 84 // 配置 ADC 時鍾為 PCLK2 的 8 分頻,即 9MHz 85 RCC_ADCCLKConfig(RCC_PCLK2_Div8); 86 // 配置 ADC 通道的轉換順序和采樣時間 87 ADC_RegularChannelConfig(ADCx_2, ADCx_2_CHANNEL, 1, 88 ADC_SampleTime_239Cycles5); 89 /* 使能 ADCx_2 的外部觸發轉換 */ 90 ADC_ExternalTrigConvCmd(ADC2, ENABLE); 91 92 /* ----------------ADCx_1 校准--------------------- */ 93 // 開啟 ADC ,並開始轉換 94 ADC_Cmd(ADCx_1, ENABLE); 95 // 初始化 ADC 校准寄存器 96 ADC_ResetCalibration(ADCx_1); 97 // 等待校准寄存器初始化完成 98 while (ADC_GetResetCalibrationStatus(ADCx_1)); 99 // ADC 開始校准 100 ADC_StartCalibration(ADCx_1); 101 // 等待校准完成 102 while (ADC_GetCalibrationStatus(ADCx_1)); 103 104 /* ----------------ADCx_2 校准--------------------- */ 105 // 開啟 ADC ,並開始轉換 106 ADC_Cmd(ADCx_2, ENABLE); 107 // 初始化 ADC 校准寄存器 108 ADC_ResetCalibration(ADCx_2); 109 // 等待校准寄存器初始化完成 110 while (ADC_GetResetCalibrationStatus(ADCx_2)); 111 // ADC 開始校准 112 ADC_StartCalibration(ADCx_2); 113 // 等待校准完成 114 while (ADC_GetCalibrationStatus(ADCx_2)); 115 116 // 由於沒有采用外部觸發,所以使用軟件觸發 ADC 轉換 117 ADC_SoftwareStartConvCmd(ADCx_1, ENABLE); 118 } /* 主函數 */ 1 int main(void) 2 { 3 uint16_t temp=0 ,temp1=0; 4 // 配置串口 5 USART_Config(); 6 7 // ADC 初始化 8 ADCx_Init(); 9 10 printf("\r\n ----這是一個雙 ADC 規則同步采集實驗----\r\n"); 11 printf("歡迎使用野火 STM32 開發板\n"); 12 while (1) 13 { 14 // 取出 ADC1 數據寄存器的高 16 位,這個是 ADC2 的轉換數據 15 temp0 = (ADC_ConvertedValue[0]&0XFFFF0000) >> 16; 16 // 取出 ADC1 數據寄存器的低 16 位,這個是 ADC1 的轉換數據 17 temp1 = (ADC_ConvertedValue[0]&0XFFFF); 18 19 ADC_ConvertedValueLocal[0] =(float) temp0/4096*3.3; 20 ADC_ConvertedValueLocal[1] =(float) temp1/4096*3.3; 21 22 printf("\r\n ADCx_1 value = %f V \r\n", 23 ADC_ConvertedValueLocal[1]); 24 printf("\r\n ADCx_2 value = %f V \r\n", 25 ADC_ConvertedValueLocal[0]); 26 27 printf("\r\n\r\n"); 28 Delay(0xffffee); 29 30 } 31 }