STM32_ADC_DMA_中斷_多通道_


裸機--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 }
 
 
 
View Code
  • 流程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
View Code
  • 雙重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 }
View Code


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM