STM32_ADC_摘自<STM32库开发实战指南>

裸机--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

猜你喜欢

转载自www.cnblogs.com/RcBlog/p/11886498.html