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