ADC 介绍:

1-三个独立的ADC 1 / 2 / 3
2-分辨率有12/10/8/6 位可选
3-每个ADC具有18个通道,其中外部通道16个

1:电压输入范围

输入电压: VREF- ≤ VIN ≤ VREF+
决定输入电压的引脚: VREF-、 VREF+ 、 VDDA 、 VSSA
VSSA 和 VREF-接地,把 VREF+和 VDDA 接 3V3,
得到ADC 的输入电压范围为: 0~3.3V。数据寄存器 ADC_DR 的满值为0xFFF:

每一刻度值为(3.3/4096),等到值为y=(3.3/4096*ADC_DR)。

2:输入通道

外部的 16 个通道在转换的时候又分为规则通道和注入通道,其中规则通道最多有 16路,注入通道最多有 4 路
规则通道: 顾名思意,规则通道就是很规矩的意思,我们平时一般使用的就是这个通道。
注入通道: 注入,可以理解为插入,插队的意思,是一种不安分的通道。它是一种在规则通道转换的时候强行插入要转换的一种。这点跟中断程序很像,都是不安分的主。所以,注入通道只有在规则通道存在时才会出现

3:通道转换顺序

规则通道

一般要设置有多少个转换通道在寄存器ADC——SQR1 bit【21,23】

转换通道1优先级高

void ADC_RegularChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel, uint8_t Rank, uint8_t ADC_SampleTime)

这函数就是在ADCX 的ADC_Channel 通道插入转换通道(Rank)顺序。

注入通道

4:触发源

1、软件触发: ADC_CR2 :

ADON/SWSTART/JSWSTART
2、外部事件触发: 内部定时器/外部IO
选择: ADC_CR2 :EXTSEL[2:0]和 JEXTSEL[2:0]
激活: ADC_CR2 :EXTEN 和 JEXTEN

5:转换时间

转换时间: Tconv = 采样时间 + 12 个周期( 12位)
The ADC samples the input voltage for a number of ADCCLK cycles that can be modified
using the SMP[2:0] bits in the ADC_SMPR1 and ADC_SMPR2 registers. Each channel can
be sampled with a different sampling time.
The total conversion time is calculated as follows:
Tconv = Sampling time + 12 cycles
Example:
With ADCCLK = 30 MHz and sampling time = 3 cycles:
Tconv = 3 + 12 = 15 cycles = 0.5 μs with APB2 at 60 MHz

ADC_CLK: ADC模拟电路时钟,最大值为36M,由
PCLK2提供,还可分频, 2/4/6/8, ADC_CCR 的
ADCPRE[1:0]设置。 PCLK2=84M
有关ADC_CLK时钟的具体描述参考datasheet:5.3.21

6:快速转换模式

采样时间: ADC 需要若干个 ADC_CLK 周期完成对输入的
模拟量进行采样,采样的周期数可通过ADC 采样时间寄存器
ADC_SMPR1 和 ADC_SMPR2 中的 SMP[2:0]位设置,
ADC_SMPR2控制的是通道 0~9, ADC_SMPR1 控制的是通
道 10~17。每个通道可以分别用不同的时间采样。其中采样
周期最小是 3 个,即如果我们要达到最快的采样,那么应该
设置采样周期为 3 个周期,这里说的周期就是 1/ADC_CLK

采样率,决定了ADC能采集多大频率的信号

最短的转换时间: Tconv = 采样时间 + 12 个周期( 12)
PCLK2 = 84M, ADC_CLK = 84/4 = 21M
Tconv = 3+12 = 15周期 = 15/21us=0.71us

7:转换方式

1、单次转换

2、连续转换
 

Bit 11 DISCEN: Discontinuous mode on regular channels
This bit is set and cleared by software to enable/disable Discontinuous mode on regular
channels.
0: Discontinuous mode on regular channels disabled
1: Discontinuous mode on regular channels enabled

Bits 15:13 DISCNUM[2:0]: Discontinuous mode channel count
These bits are written by software to define the number of regular channels to be converted
in discontinuous mode, after receiving an external trigger.
000: 1 channel
001: 2 channels
...
111: 8 channels

3、扫描模式

This mode is used to scan a group of analog channels.
The Scan mode is selected by setting the SCAN bit in the ADC_CR1 register. Once this bit
has been set, the ADC scans all the channels selected in the ADC_SQRx registers (for
regular channels) or in the ADC_JSQR register (for injected channels). A single conversion
is performed for each channel of the group. After each end of conversion, the next channel
in the group is converted automatically. If the CONT bit is set, regular channel conversion
does not stop at the last selected channel in the group but continues again from the first
selected channel.
If the DMA bit is set, the direct memory access (DMA) controller is used to transfer the data
converted from the regular group of channels (stored in the ADC_DR register) to SRAM
after each regular channel conversion.
The EOC bit is set in the ADC_SR register:
• At the end of each regular group sequence if the EOCS bit is cleared to 0
• At the end of each regular channel conversion if the EOCS bit is set to 1
The data converted from an injected channel are always stored into the ADC_JDRx
registers.

8:数据寄存器

一切准备就绪后, ADC 转换后的数据根据转换组的不同,规则组的数据放在ADC_DR 寄存器,注入组的数据放在 JDRx。 如果是使用双重或者三重模式那规矩组的数据是存放在通用规则寄存器 ADC_CDR 内的

9、中断

10、模拟看门狗

模拟看门狗如何保护多个通道?
 

保证在多少范围内

11、电压转换

多重工作模式:

ADC_CCR:MULTI[4:0]

ADC_CCR:DMA[1:0]

1 :独立模式

2:双重规则同步模式

1、规则指的是只适用于规则通道,注入通道不行
2、同步指的是两个/三个ADC同时采集多个通道,
比如示波器的双通道同时采集。
注意:不要在同步模式时采集同一个通道

如下是ADC 1/2 双重规则同步模式图

ADC1采集ch10 和ch11

ADC2采集ch11 和ch12

ADC 1/2 同步采集 ch10/11  ch11/12

3:多重交替模式

1、交替模式只能用于规则组,通常只有一个通道,在一个ADC转换的时候,另外一个ADC又开始采集,这样可以提高ADC的采样率,最高为6M
2、数据传输时使用DMA模式2,当有两个数据项可用时( 32bit),生成一个DMA请求。

这是三个ADC 交替模式,用模式2,数据组合方式

DMA mode 2: On each DMA request (two data items are available) two halfwords
representing two ADC-converted data items are transferred as a word.
In Dual ADC mode, both ADC2 and ADC1 data are transferred on the first request
(ADC2 data take the upper half-word and ADC1 data take the lower half-word) and
so on.
In Triple ADC mode, three DMA requests are generated. On the first request, both
ADC2 and ADC1 data are transferred (ADC2 data take the upper half-word and
ADC1 data take the lower half-word). On the second request, both ADC1 and
ADC3 data are transferred (ADC1 data take the upper half-word and ADC3 data
take the lower half-word).On the third request, both ADC3 and ADC2 data are
transferred (ADC3 data take the upper half-word and ADC2 data take the lower
half-word) and so on.
DAM mode 2 is used in interleaved mode and in regular simultaneous mode (for
Dual ADC mode only).
Example:
a) Interleaved dual mode: a DMA request is generated each time 2 data items are
available:
1st request: ADC_CDR[31:0] = ADC2_DR[15:0] | ADC1_DR[15:0]
2nd request: ADC_CDR[31:0] = ADC2_DR[15:0] | ADC1_DR[15:0]
b) Interleaved triple mode: a DMA request is generated each time 2 data items are
available//这是上面三个ADC图数据的组合方式,假如用DMA 的时候,用三个32位数组

第一个存储的是1st request:  ,二个是2nd request,三个是3rd request
1st request: ADC_CDR[31:0] = ADC2_DR[15:0] | ADC1_DR[15:0]

2nd request: ADC_CDR[31:0] = ADC1_DR[15:0] | ADC3_DR[15:0]
3rd request: ADC_CDR[31:0] = ADC3_DR[15:0] | ADC2_DR[15:0]
4th request: ADC_CDR[31:0] = ADC2_DR[15:0] | ADC1_DR[15:0]

固件结构介绍:

ADC_InitTypeDef

ADC_Resolution: 配置 ADC 的分辨率,可选的分辨率有12 位、 10 位、 8 位和 6 位。 ADC_CR1:RES[1:0]
ScanConvMode: 配置是否使用扫描模式,单通道DISABLE,多通道 ENABLE。 ADC_CR1:SCAN
ADC_ContinuousConvMode: 配置连续转换还是单次转换。 ADC_CR1: CONT
 ADC_ExternalTrigConvEdge: 外部触发极性选择,如果使用外部触发,可以选择触发的极性,可选有禁止触发检测、上升沿触发检测、下降沿触发检测以及上升沿和下降沿均可触发检测。 ADC_CR2: EXTEN/ JEXTEN

ADC_ExternalTrigConv: 外部触发选择,实际上,我们一般使用软件自动触发。 ADC_CR2: EXTSEL[3:0]/ JEXTSEL[3:0]

ADC_DataAlign: 转换结果数据对齐模式,可选ADC_DataAlign_Right 或ADC_DataAlign_Left。ADC_CR2:ALIGN
ADC_NbrOfChannel: AD 转换通道数目。 ADC_SQR1:L[3:0]/ADC_JSQR:JL[1:0]

ADC_CommonInitTypeDef 这是ADC共用初始化结构体

ADC_Mode: ADC模工作式选择,有独立模式、双重模式以及三重模式。 ADC_CCR:MULTI
 ADC_Prescaler: ADC 时钟分频系数选择, ADC 时钟是有 PCLK2 分频而来,分频系数决定 ADC 时钟频率,可选的分频系数为 2、 4、 6 和 8。 ADC 最大时钟配置为36MHz。 ADC_CCR:ADCPRE

ADC_DMAAccessMode: DMA 模式设置,只有在双重或者三重模式才需要设置,可以设置三种模式,具体可参考参考手册11.9章节的说明。 ADC_CCR:DMA
Bits 15:14 DMA: Direct memory access mode for multi ADC mode
This bit-field is set and cleared by software. Refer to the DMA controller section for more
details.
00: DMA mode disabled
01: DMA mode 1 enabled (2 / 3 half-words one by one - 1 then 2 then 3)
10: DMA mode 2 enabled (2 / 3 half-words by pairs - 2&1 then 1&3 then 3&2)
11: DMA mode 3 enabled (2 / 3 bytes by pairs - 2&1 then 1&3 then 3&2)

ADC_TwoSamplingDelay: 2 个采样阶段之间的延迟,仅适用于双重或三重交错模式。 ADC_CCR:DELAY

Bit 11:8 DELAY: Delay between 2 sampling phases
Set and cleared by software. These bits are used in dual or triple interleaved modes.
0000: 5 * TADCCLK
0001: 6 * TADCCLK
0010: 7 * TADCCLK
...
1111: 20 * TADCCLK
Bits 7:5 Reserved, must be kept at reset value.

1-配置规则通道的转换顺序

ADC_RegularChannelConfig
(ADC_TypeDef* ADCx,    // 使用哪个ADC
uint8_t ADC_Channel,      // 使用哪个通道
uint8_t Rank,                      // 通道的转换顺序
uint8_t ADC_SampleTime) // 采样时间
2、使能ADC

ADC_Cmd(ADC_TypeDef* ADCx, FunctionalState NewState)
ADC_CR2:ADON

3-软件触发转换
ADC_SoftwareStartConv(ADC_TypeDef* ADCx)
ADC_CR2:SWSTART

4-单重ADC DMA 请求
ADC_DMARequestAfterLastTransferCmd(ADC_TypeDef* ADCx,
FunctionalState NewState)
ADC_CR2:DDS
ADC_DMACmd(RHEOSTAT_ADC, ENABLE);
ADC_CR2:DMA

5-多重ADC DMA 请求
ADC_MultiModeDMARequestAfterLastTransferCmd(FunctionalState
NewState)
ADC_CCR:DDS, ADC_CCR:DMA

编程

#ifndef __BSP_ADC_H
#define __BSP_ADC_H#include "stm32f4xx.h"// ADC GPIO 宏定义
#define RHEOSTAT_ADC_GPIO_PORT    GPIOB
#define RHEOSTAT_ADC_GPIO_PIN     GPIO_Pin_0
#define RHEOSTAT_ADC_GPIO_CLK     RCC_AHB1Periph_GPIOB// ADC 序号宏定义
#define RHEOSTAT_ADC              ADC1
#define RHEOSTAT_ADC_CLK          RCC_APB2Periph_ADC1
#define RHEOSTAT_ADC_CHANNEL      ADC_Channel_8// ADC 中断宏定义
#define Rheostat_ADC_IRQ            ADC_IRQn
#define Rheostat_ADC_INT_FUNCTION   ADC_IRQHandlervoid Rheostat_Init(void);#endif /* __BSP_ADC_H */void Rheostat_Init(void)
{Rheostat_ADC_GPIO_Config();Rheostat_ADC_Mode_Config();Rheostat_ADC_NVIC_Config();
}static void Rheostat_ADC_GPIO_Config(void)
{GPIO_InitTypeDef GPIO_InitStructure;// 使能 GPIO 时钟RCC_AHB1PeriphClockCmd(RHEOSTAT_ADC_GPIO_CLK, ENABLE);// 配置 IOGPIO_InitStructure.GPIO_Pin = RHEOSTAT_ADC_GPIO_PIN;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;     GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ; //不上拉不下拉GPIO_Init(RHEOSTAT_ADC_GPIO_PORT, &GPIO_InitStructure);
}static void Rheostat_ADC_Mode_Config(void)
{ADC_InitTypeDef ADC_InitStructure;ADC_CommonInitTypeDef ADC_CommonInitStructure;// 开启ADC时钟RCC_APB2PeriphClockCmd(RHEOSTAT_ADC_CLK , ENABLE);// -------------------ADC Common 结构体 参数 初始化------------------------// 独立ADC模式ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;// 时钟为fpclk x分频  ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div4;// 禁止DMA直接访问模式  ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;// 采样时间间隔   ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_20Cycles;  ADC_CommonInit(&ADC_CommonInitStructure);// -------------------ADC Init 结构体 参数 初始化--------------------------ADC_StructInit(&ADC_InitStructure);// ADC 分辨率ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;// 禁止扫描模式,多通道采集才需要   ADC_InitStructure.ADC_ScanConvMode = DISABLE; // 连续转换  ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; //禁止外部边沿触发ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;//外部触发通道,本例子使用软件触发,此值随便赋值即可ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC1;//数据右对齐    ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;//转换通道 1个ADC_InitStructure.ADC_NbrOfConversion = 1;                                    ADC_Init(RHEOSTAT_ADC, &ADC_InitStructure);//---------------------------------------------------------------------------// 配置 ADC 通道转换顺序为1,第一个转换,采样时间为3个时钟周期ADC_RegularChannelConfig(RHEOSTAT_ADC, RHEOSTAT_ADC_CHANNEL, 1, ADC_SampleTime_56Cycles);// ADC 转换结束产生中断,在中断服务程序中读取转换值ADC_ITConfig(RHEOSTAT_ADC, ADC_IT_EOC, ENABLE);// 使能ADCADC_Cmd(RHEOSTAT_ADC, ENABLE);  //开始adc转换,软件触发ADC_SoftwareStartConv(RHEOSTAT_ADC);
}// 配置中断优先级
static void Rheostat_ADC_NVIC_Config(void)
{NVIC_InitTypeDef NVIC_InitStructure;NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);NVIC_InitStructure.NVIC_IRQChannel = Rheostat_ADC_IRQ;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&NVIC_InitStructure);
}中断函数
extern __IO uint16_t ADC_ConvertedValue;// ADC 转换完成中断服务程序
void ADC_IRQHandler(void)
{if(ADC_GetITStatus(RHEOSTAT_ADC,ADC_IT_EOC)==SET){// 读取ADC的转换值ADC_ConvertedValue = ADC_GetConversionValue(RHEOSTAT_ADC);}ADC_ClearITPendingBit(RHEOSTAT_ADC,ADC_IT_EOC);}   int main(void)
{   /*初始化USART 配置模式为 115200 8-N-1,中断接收*/Debug_USART_Config();Rheostat_Init();    while (1){ADC_Vol =(float) ADC_ConvertedValue/4096*(float)3.3; // 读取转换的AD值printf("\r\n The current AD value = 0x%04X \r\n", ADC_ConvertedValue); printf("\r\n The current AD value = %f V \r\n",ADC_Vol);     Delay(0xffffee);  }
}

ADC—独立模式-单通道-DMA

#ifndef __BSP_ADC_H
#define __BSP_ADC_H#include "stm32f4xx.h"// ADC GPIO 宏定义
#define RHEOSTAT_ADC_GPIO_PORT    GPIOB
#define RHEOSTAT_ADC_GPIO_PIN     GPIO_Pin_0
#define RHEOSTAT_ADC_GPIO_CLK     RCC_AHB1Periph_GPIOB// ADC 序号宏定义
#define RHEOSTAT_ADC              ADC1
#define RHEOSTAT_ADC_CLK          RCC_APB2Periph_ADC1
#define RHEOSTAT_ADC_CHANNEL      ADC_Channel_8// ADC DR寄存器宏定义,ADC转换后的数字值则存放在这里
#define RHEOSTAT_ADC_DR_ADDR    ((u32)ADC1+0x4c)// ADC DMA 通道宏定义,这里我们使用DMA传输
#define RHEOSTAT_ADC_DMA_CLK      RCC_AHB1Periph_DMA2
#define RHEOSTAT_ADC_DMA_CHANNEL  DMA_Channel_0
#define RHEOSTAT_ADC_DMA_STREAM   DMA2_Stream0void Rheostat_Init(void);#endif /* __BSP_ADC_H *//********************************************************************************* @file    bsp_bsp_adc.c* @author  fire* @version V1.0* @date    2015-xx-xx* @brief   adc驱动******************************************************************************* @attention** 实验平台:野火  STM32 F407 开发板  * 论坛    :http://www.firebbs.cn* 淘宝    :https://fire-stm32.taobao.com********************************************************************************/
#include "./adc/bsp_adc.h"__IO uint16_t ADC_ConvertedValue;static void Rheostat_ADC_GPIO_Config(void)
{GPIO_InitTypeDef GPIO_InitStructure;// 使能 GPIO 时钟RCC_AHB1PeriphClockCmd(RHEOSTAT_ADC_GPIO_CLK, ENABLE);// 配置 IOGPIO_InitStructure.GPIO_Pin = RHEOSTAT_ADC_GPIO_PIN;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;     GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ; //不上拉不下拉GPIO_Init(RHEOSTAT_ADC_GPIO_PORT, &GPIO_InitStructure);
}static void Rheostat_ADC_Mode_Config(void)
{DMA_InitTypeDef DMA_InitStructure;ADC_InitTypeDef ADC_InitStructure;ADC_CommonInitTypeDef ADC_CommonInitStructure;// ------------------DMA Init 结构体参数 初始化--------------------------// ADC1使用DMA2,数据流0,通道0,这个是手册固定死的// 开启DMA时钟RCC_AHB1PeriphClockCmd(RHEOSTAT_ADC_DMA_CLK, ENABLE); // 外设基址为:ADC 数据寄存器地址DMA_InitStructure.DMA_PeripheralBaseAddr = RHEOSTAT_ADC_DR_ADDR;   // 存储器地址,实际上就是一个内部SRAM的变量    DMA_InitStructure.DMA_Memory0BaseAddr = (u32)&ADC_ConvertedValue;  // 数据传输方向为外设到存储器    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;    // 缓冲区大小为,指一次传输的数据量DMA_InitStructure.DMA_BufferSize = 1;    // 外设寄存器只有一个,地址不用递增DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;// 存储器地址固定DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable; // // 外设数据大小为半字,即两个字节 DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; // 存储器数据大小也为半字,跟外设数据大小相同DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;    // 循环传输模式DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;// DMA 传输通道优先级为高,当使用一个DMA通道时,优先级设置不影响DMA_InitStructure.DMA_Priority = DMA_Priority_High;// 禁止DMA FIFO   ,使用直连模式DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;  // FIFO 大小,FIFO模式禁止时,这个不用配置    DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;  // 选择 DMA 通道,通道存在于流中DMA_InitStructure.DMA_Channel = RHEOSTAT_ADC_DMA_CHANNEL; //初始化DMA流,流相当于一个大的管道,管道里面有很多通道DMA_Init(RHEOSTAT_ADC_DMA_STREAM, &DMA_InitStructure);// 使能DMA流DMA_Cmd(RHEOSTAT_ADC_DMA_STREAM, ENABLE);// 开启ADC时钟RCC_APB2PeriphClockCmd(RHEOSTAT_ADC_CLK , ENABLE);// -------------------ADC Common 结构体 参数 初始化------------------------// 独立ADC模式ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;// 时钟为fpclk x分频 ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div4;// 禁止DMA直接访问模式  ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;// 采样时间间隔   ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_20Cycles;  ADC_CommonInit(&ADC_CommonInitStructure);// -------------------ADC Init 结构体 参数 初始化--------------------------ADC_StructInit(&ADC_InitStructure);// ADC 分辨率ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;// 禁止扫描模式,多通道采集才需要   ADC_InitStructure.ADC_ScanConvMode = DISABLE; // 连续转换  ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; //禁止外部边沿触发ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;//外部触发通道,本例子使用软件触发,此值随便赋值即可ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC1;//数据右对齐    ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;//转换通道 1个ADC_InitStructure.ADC_NbrOfConversion = 1;                                    ADC_Init(RHEOSTAT_ADC, &ADC_InitStructure);//---------------------------------------------------------------------------// 配置 ADC 通道转换顺序为1,第一个转换,采样时间为3个时钟周期ADC_RegularChannelConfig(RHEOSTAT_ADC, RHEOSTAT_ADC_CHANNEL, 1, ADC_SampleTime_56Cycles);// 使能DMA请求 after last transfer (Single-ADC mode)ADC_DMARequestAfterLastTransferCmd(RHEOSTAT_ADC, ENABLE);// 使能ADC DMAADC_DMACmd(RHEOSTAT_ADC, ENABLE);// 使能ADCADC_Cmd(RHEOSTAT_ADC, ENABLE);  //开始adc转换,软件触发ADC_SoftwareStartConv(RHEOSTAT_ADC);
}void Rheostat_Init(void)
{Rheostat_ADC_GPIO_Config();Rheostat_ADC_Mode_Config();
}int main(void)
{   /*初始化USART 配置模式为 115200 8-N-1,中断接收*/Debug_USART_Config();Rheostat_Init();    while (1){printf("\r\n The current AD value = 0x%04X \r\n", ADC_ConvertedValue); printf("\r\n The current AD value = %f V \r\n",ADC_Vol);     ADC_Vol =(float) ADC_ConvertedValue/4096*(float)3.3; // 读取转换的AD值Delay(0xffffee);  }
}

ADC—独立模式-多通道-DMA  scan模式 三根个引脚采集

#ifndef __BSP_ADC_H
#define __BSP_ADC_H#include "stm32f4xx.h"#define RHEOSTAT_NOFCHANEL      3/*=====================通道1 IO======================*/
// PB0 通过调帽接电位器
// ADC IO宏定义
#define RHEOSTAT_ADC_GPIO_PORT1    GPIOB
#define RHEOSTAT_ADC_GPIO_PIN1     GPIO_Pin_0
#define RHEOSTAT_ADC_GPIO_CLK1     RCC_AHB1Periph_GPIOB
#define RHEOSTAT_ADC_CHANNEL1      ADC_Channel_8
/*=====================通道2 IO ======================*/
// PB1 通过调帽接光敏电阻
// ADC IO宏定义
#define RHEOSTAT_ADC_GPIO_PORT2    GPIOB
#define RHEOSTAT_ADC_GPIO_PIN2     GPIO_Pin_1
#define RHEOSTAT_ADC_GPIO_CLK2     RCC_AHB1Periph_GPIOB
#define RHEOSTAT_ADC_CHANNEL2      ADC_Channel_9
/*=====================通道3 IO ======================*/
// PA6 悬空,可用杜邦线接3V3或者GND来实验
// ADC IO宏定义
#define RHEOSTAT_ADC_GPIO_PORT3    GPIOA
#define RHEOSTAT_ADC_GPIO_PIN3     GPIO_Pin_6
#define RHEOSTAT_ADC_GPIO_CLK3     RCC_AHB1Periph_GPIOA
#define RHEOSTAT_ADC_CHANNEL3     ADC_Channel_6// ADC 序号宏定义
#define RHEOSTAT_ADC              ADC1
#define RHEOSTAT_ADC_CLK          RCC_APB2Periph_ADC1
// ADC DR寄存器宏定义,ADC转换后的数字值则存放在这里
#define RHEOSTAT_ADC_DR_ADDR    ((u32)ADC1+0x4c)// ADC DMA 通道宏定义,这里我们使用DMA传输
#define RHEOSTAT_ADC_DMA_CLK      RCC_AHB1Periph_DMA2
#define RHEOSTAT_ADC_DMA_CHANNEL  DMA_Channel_0
#define RHEOSTAT_ADC_DMA_STREAM   DMA2_Stream0void Rheostat_Init(void);#endif /* __BSP_ADC_H *//********************************************************************************* @file    bsp_bsp_adc.c* @author  fire* @version V1.0* @date    2015-xx-xx* @brief   adc驱动******************************************************************************* @attention** 实验平台:野火  STM32 F407 开发板  * 论坛    :http://www.firebbs.cn* 淘宝    :https://fire-stm32.taobao.com********************************************************************************/ #include "./adc/bsp_adc.h"__IO uint16_t ADC_ConvertedValue[RHEOSTAT_NOFCHANEL]={0};static void Rheostat_ADC_GPIO_Config(void)
{GPIO_InitTypeDef GPIO_InitStructure;   /*=====================通道1======================*/   // 使能 GPIO 时钟RCC_AHB1PeriphClockCmd(RHEOSTAT_ADC_GPIO_CLK1,ENABLE);     // 配置 IOGPIO_InitStructure.GPIO_Pin = RHEOSTAT_ADC_GPIO_PIN1;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;//不上拉不下拉    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;GPIO_Init(RHEOSTAT_ADC_GPIO_PORT1, &GPIO_InitStructure);/*=====================通道2======================*/// 使能 GPIO 时钟RCC_AHB1PeriphClockCmd(RHEOSTAT_ADC_GPIO_CLK2,ENABLE);      // 配置 IOGPIO_InitStructure.GPIO_Pin = RHEOSTAT_ADC_GPIO_PIN2;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;//不上拉不下拉    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;GPIO_Init(RHEOSTAT_ADC_GPIO_PORT2, &GPIO_InitStructure);  /*=====================通道3=======================*/// 使能 GPIO 时钟RCC_AHB1PeriphClockCmd(RHEOSTAT_ADC_GPIO_CLK3,ENABLE);      // 配置 IOGPIO_InitStructure.GPIO_Pin = RHEOSTAT_ADC_GPIO_PIN3;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;//不上拉不下拉    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;GPIO_Init(RHEOSTAT_ADC_GPIO_PORT3, &GPIO_InitStructure);
}static void Rheostat_ADC_Mode_Config(void)
{DMA_InitTypeDef DMA_InitStructure;ADC_InitTypeDef ADC_InitStructure;ADC_CommonInitTypeDef ADC_CommonInitStructure;// ------------------DMA Init 结构体参数 初始化--------------------------// ADC1使用DMA2,数据流0,通道0,这个是手册固定死的// 开启DMA时钟RCC_AHB1PeriphClockCmd(RHEOSTAT_ADC_DMA_CLK, ENABLE); // 外设基址为:ADC 数据寄存器地址DMA_InitStructure.DMA_PeripheralBaseAddr = RHEOSTAT_ADC_DR_ADDR;   // 存储器地址,实际上就是一个内部SRAM的变量    DMA_InitStructure.DMA_Memory0BaseAddr = (u32)ADC_ConvertedValue;  // 数据传输方向为外设到存储器 DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;    // 缓冲区大小为,指一次传输的数据量DMA_InitStructure.DMA_BufferSize = RHEOSTAT_NOFCHANEL;   // 外设寄存器只有一个,地址不用递增DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;// 存储器地址固定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 传输通道优先级为高,当使用一个DMA通道时,优先级设置不影响DMA_InitStructure.DMA_Priority = DMA_Priority_High;// 禁止DMA FIFO   ,使用直连模式DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;  // FIFO 大小,FIFO模式禁止时,这个不用配置    DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;  // 选择 DMA 通道,通道存在于流中DMA_InitStructure.DMA_Channel = RHEOSTAT_ADC_DMA_CHANNEL; //初始化DMA流,流相当于一个大的管道,管道里面有很多通道DMA_Init(RHEOSTAT_ADC_DMA_STREAM, &DMA_InitStructure);// 使能DMA流DMA_Cmd(RHEOSTAT_ADC_DMA_STREAM, ENABLE);// 开启ADC时钟RCC_APB2PeriphClockCmd(RHEOSTAT_ADC_CLK , ENABLE);// -------------------ADC Common 结构体 参数 初始化------------------------// 独立ADC模式ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;// 时钟为fpclk x分频 ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div4;// 禁止DMA直接访问模式  ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;// 采样时间间隔   ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_20Cycles;  ADC_CommonInit(&ADC_CommonInitStructure);// -------------------ADC Init 结构体 参数 初始化--------------------------ADC_StructInit(&ADC_InitStructure);// ADC 分辨率ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;// 扫描模式,多通道采集需要  ADC_InitStructure.ADC_ScanConvMode = ENABLE; // 连续转换   ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; //禁止外部边沿触发ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;//外部触发通道,本例子使用软件触发,此值随便赋值即可ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC1;//数据右对齐    ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;//转换通道 1个ADC_InitStructure.ADC_NbrOfConversion = RHEOSTAT_NOFCHANEL;                                    ADC_Init(RHEOSTAT_ADC, &ADC_InitStructure);//---------------------------------------------------------------------------// 配置 ADC 通道转换顺序和采样时间周期ADC_RegularChannelConfig(RHEOSTAT_ADC, RHEOSTAT_ADC_CHANNEL1, 1, ADC_SampleTime_3Cycles);ADC_RegularChannelConfig(RHEOSTAT_ADC, RHEOSTAT_ADC_CHANNEL2, 2, ADC_SampleTime_3Cycles); ADC_RegularChannelConfig(RHEOSTAT_ADC, RHEOSTAT_ADC_CHANNEL3, 3, ADC_SampleTime_3Cycles); // 使能DMA请求 after last transfer (Single-ADC mode)ADC_DMARequestAfterLastTransferCmd(RHEOSTAT_ADC, ENABLE);// 使能ADC DMAADC_DMACmd(RHEOSTAT_ADC, ENABLE);// 使能ADCADC_Cmd(RHEOSTAT_ADC, ENABLE);  //开始adc转换,软件触发ADC_SoftwareStartConv(RHEOSTAT_ADC);
}void Rheostat_Init(void)
{Rheostat_ADC_GPIO_Config();Rheostat_ADC_Mode_Config();
}/********************************************************************************* @file    main.c* @author  fire* @version V1.0* @date    2015-xx-xx* @brief   ADC例程******************************************************************************* @attention** 实验平台:野火  STM32 F407 开发板* 论坛    :http://www.firebbs.cn* 淘宝    :https://fire-stm32.taobao.com********************************************************************************/#include "stm32f4xx.h"
#include "./usart/bsp_debug_usart.h"
#include "./adc/bsp_adc.h"// ADC转换的电压值通过MDA方式传到SRAM
extern __IO uint16_t ADC_ConvertedValue[RHEOSTAT_NOFCHANEL];// 局部变量,用于保存转换计算后的电压值
float ADC_ConvertedValueLocal[RHEOSTAT_NOFCHANEL]={0}; static void Delay(__IO uint32_t nCount)  //简单的延时函数
{for(; nCount != 0; nCount--);
}/*** @brief  主函数* @param  无* @retval 无*/
int main(void)
{   /*初始化USART 配置模式为 115200 8-N-1,中断接收*/Debug_USART_Config();Rheostat_Init();    while (1){ADC_ConvertedValueLocal[0] =(float) ADC_ConvertedValue[0]/4096*(float)3.3;ADC_ConvertedValueLocal[1] =(float) ADC_ConvertedValue[1]/4096*(float)3.3;ADC_ConvertedValueLocal[2] =(float) ADC_ConvertedValue[2]/4096*(float)3.3;printf("\r\n CH1_C3 value = %f V \r\n",ADC_ConvertedValueLocal[0]);printf("\r\n CH2_PA4 value = %f V \r\n",ADC_ConvertedValueLocal[1]);printf("\r\n CH3_PA6 value = %f V \r\n",ADC_ConvertedValueLocal[2]);printf("\r\n\r\n");Delay(0xffffff);  }
}/*********************************************END OF FILE**********************/

ADC—双重ADC-多通道-规则同步   可以是SCAN模式,每个ADCX的多个通道

现在是ADC1 和2 的每一个通道

/********************************************************************************* @file    main.c* @author  fire* @version V1.0* @date    2015-xx-xx* @brief   ADC例程******************************************************************************* @attention** 实验平台:野火  STM32 F407 开发板* 论坛    :http://www.firebbs.cn* 淘宝    :https://fire-stm32.taobao.com********************************************************************************/#include "stm32f4xx.h"
#include "./usart/bsp_debug_usart.h"
#include "./adc/bsp_adc.h"// ADC1转换的电压值通过MDA方式传到SRAM
extern __IO uint16_t ADC_ConvertedValue[2];// 局部变量,用于保存转换计算后的电压值
float ADC_ConvertedValueLocal[2]; static void Delay(__IO uint32_t nCount)    //简单的延时函数
{for(; nCount != 0; nCount--);
}/*** @brief  主函数* @param  无* @retval 无*/
int main(void)
{   /*初始化USART 配置模式为 115200 8-N-1,中断接收*/Debug_USART_Config();Rheostat_Init();    while (1){Delay(0xffffee);  ADC_ConvertedValueLocal[0] =(float)((uint16_t)ADC_ConvertedValue[0]*3.3/4096); ADC_ConvertedValueLocal[1] =(float)((uint16_t)ADC_ConvertedValue[1]*3.3/4096);    printf("\r\n The current AD value = 0x%08X \r\n", ADC_ConvertedValue[0]); printf("\r\n The current AD value = 0x%08X \r\n", ADC_ConvertedValue[1]);     printf("\r\n The current ADC1 value = %f V \r\n",ADC_ConvertedValueLocal[0]); printf("\r\n The current ADC2 value = %f V \r\n",ADC_ConvertedValueLocal[1]);    }
}/*********************************************END OF FILE**********************/#ifndef __BSP_ADC_H
#define __BSP_ADC_H#include "stm32f4xx.h"/*=====================通道1 IO======================*/
// PB0 通过调帽接电位器
// ADC IO宏定义
#define RHEOSTAT_ADC_GPIO_PORT1    GPIOB
#define RHEOSTAT_ADC_GPIO_PIN1     GPIO_Pin_0
#define RHEOSTAT_ADC_GPIO_CLK1     RCC_AHB1Periph_GPIOB// ADC 序号宏定义
#define RHEOSTAT_ADC1             ADC1
#define RHEOSTAT_ADC1_CLK         RCC_APB2Periph_ADC1
#define RHEOSTAT_ADC_CHANNEL1     ADC_Channel_8
/*=====================通道2 IO ======================*/
// PB1 通过调帽接光敏电阻
// ADC IO宏定义
#define RHEOSTAT_ADC_GPIO_PORT2    GPIOB
#define RHEOSTAT_ADC_GPIO_PIN2     GPIO_Pin_1
#define RHEOSTAT_ADC_GPIO_CLK2     RCC_AHB1Periph_GPIOB#define RHEOSTAT_ADC2             ADC2
#define RHEOSTAT_ADC2_CLK         RCC_APB2Periph_ADC2
#define RHEOSTAT_ADC_CHANNEL2     ADC_Channel_9// ADC CDR寄存器宏定义,ADC转换后的数字值则存放在这里
#define RHEOSTAT_ADC_CDR_ADDR    ((uint32_t)0x40012308)// ADC DMA 通道宏定义,这里我们使用DMA传输
#define RHEOSTAT_ADC_DMA_CLK      RCC_AHB1Periph_DMA2
#define RHEOSTAT_ADC_DMA_CHANNEL  DMA_Channel_0
#define RHEOSTAT_ADC_DMA_STREAM   DMA2_Stream0void Rheostat_Init(void);#endif /* __BSP_ADC_H *//********************************************************************************* @file    bsp_bsp_adc.c* @author  fire* @version V1.0* @date    2015-xx-xx* @brief   adc驱动******************************************************************************* @attention** 实验平台:野火  STM32 F407 开发板  * 论坛    :http://www.firebbs.cn* 淘宝    :https://fire-stm32.taobao.com********************************************************************************/
#include "./adc/bsp_adc.h"__IO uint16_t ADC_ConvertedValue[2];static void Rheostat_ADC_GPIO_Config(void)
{GPIO_InitTypeDef GPIO_InitStructure;// 使能 GPIO 时钟RCC_AHB1PeriphClockCmd(RHEOSTAT_ADC_GPIO_CLK1, ENABLE);RCC_AHB1PeriphClockCmd(RHEOSTAT_ADC_GPIO_CLK2, ENABLE);// 配置 IOGPIO_InitStructure.GPIO_Pin = RHEOSTAT_ADC_GPIO_PIN1;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;        GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ; //不上拉不下拉GPIO_Init(RHEOSTAT_ADC_GPIO_PORT1, &GPIO_InitStructure);// 配置 IOGPIO_InitStructure.GPIO_Pin = RHEOSTAT_ADC_GPIO_PIN2;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;     GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ; //不上拉不下拉GPIO_Init(RHEOSTAT_ADC_GPIO_PORT2, &GPIO_InitStructure);
}static void Rheostat_ADC_Mode_Config(void)
{DMA_InitTypeDef DMA_InitStructure;ADC_InitTypeDef ADC_InitStructure;ADC_CommonInitTypeDef ADC_CommonInitStructure;// ------------------DMA Init 结构体参数 初始化--------------------------// ADC1使用DMA2,数据流0,通道0,这个是手册固定死的// 开启DMA时钟RCC_AHB1PeriphClockCmd(RHEOSTAT_ADC_DMA_CLK, ENABLE); // 外设基址为:ADC 数据寄存器地址DMA_InitStructure.DMA_PeripheralBaseAddr = RHEOSTAT_ADC_CDR_ADDR;  // 存储器地址,实际上就是一个内部SRAM的变量    DMA_InitStructure.DMA_Memory0BaseAddr = (u32)ADC_ConvertedValue;  // 数据传输方向为外设到存储器 DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;    // 缓冲区大小为,指一次传输的数据量DMA_InitStructure.DMA_BufferSize = 2;    // 外设寄存器只有一个,地址不用递增DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;// 存储器地址固定DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; // // 外设数据大小为半字,即两个字节 DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; //  存储器数据大小也为半字,跟外设数据大小相同DMA_InitStructure.DMA_MemoryDataSize = DMA_PeripheralDataSize_HalfWord;    // 循环传输模式DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;// DMA 传输通道优先级为高,当使用一个DMA通道时,优先级设置不影响DMA_InitStructure.DMA_Priority = DMA_Priority_High;// 禁止DMA FIFO   ,使用直连模式DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;  // FIFO 大小,FIFO模式禁止时,这个不用配置    DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;  // 选择 DMA 通道,通道存在于流中DMA_InitStructure.DMA_Channel = RHEOSTAT_ADC_DMA_CHANNEL; //初始化DMA流,流相当于一个大的管道,管道里面有很多通道DMA_Init(RHEOSTAT_ADC_DMA_STREAM, &DMA_InitStructure);// 使能DMA流DMA_Cmd(RHEOSTAT_ADC_DMA_STREAM, ENABLE);// 开启ADC时钟RCC_APB2PeriphClockCmd(RHEOSTAT_ADC1_CLK , ENABLE);RCC_APB2PeriphClockCmd(RHEOSTAT_ADC2_CLK , ENABLE);// -------------------ADC Common 结构体 参数 初始化------------------------// 独立ADC模式ADC_CommonInitStructure.ADC_Mode = ADC_DualMode_RegSimult;// 时钟为fpclk x分频   ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div4;// 禁止DMA直接访问模式  ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_1;// 采样时间间隔  ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;  ADC_CommonInit(&ADC_CommonInitStructure);// -------------------ADC Init 结构体 参数 初始化--------------------------ADC_StructInit(&ADC_InitStructure);// ADC 分辨率ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;// 禁止扫描模式,多通道采集才需要    ADC_InitStructure.ADC_ScanConvMode = DISABLE; // 连续转换  ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; //禁止外部边沿触发ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;//外部触发通道,本例子使用软件触发,此值随便赋值即可ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC1;//数据右对齐    ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;//转换通道 1个ADC_InitStructure.ADC_NbrOfConversion = 1;//---------------------------------------------------------------------------    ADC_Init(RHEOSTAT_ADC1, &ADC_InitStructure);    // 配置 ADC 通道转换顺序为1,第一个转换,采样时间为3个时钟周期ADC_RegularChannelConfig(RHEOSTAT_ADC1, RHEOSTAT_ADC_CHANNEL1, 1, ADC_SampleTime_3Cycles);   //---------------------------------------------------------------------------ADC_Init(RHEOSTAT_ADC2, &ADC_InitStructure);// 配置 ADC 通道转换顺序为1,第一个转换,采样时间为3个时钟周期ADC_RegularChannelConfig(RHEOSTAT_ADC2, RHEOSTAT_ADC_CHANNEL2, 1, ADC_SampleTime_3Cycles);   //---------------------------------------------------------------------------// 使能DMA请求 after last transfer (multi-ADC mode)ADC_MultiModeDMARequestAfterLastTransferCmd(ENABLE);
// 使能ADC DMAADC_DMACmd(RHEOSTAT_ADC1, ENABLE);// 使能ADCADC_Cmd(RHEOSTAT_ADC1, ENABLE);  ADC_Cmd(RHEOSTAT_ADC2, ENABLE);   //开始adc转换,软件触发ADC_SoftwareStartConv(RHEOSTAT_ADC1);//ADC_SoftwareStartConv(RHEOSTAT_ADC2);
}void Rheostat_Init(void)
{Rheostat_ADC_GPIO_Config();Rheostat_ADC_Mode_Config();
}

ADC—三重ADC-单通道-交替采集  只能每一个ADCX一个通道


#include "stm32f4xx.h"
#include "./usart/bsp_debug_usart.h"
#include "./adc/bsp_adc.h"// ADC1转换的电压值通过MDA方式传到SRAM
extern __IO uint32_t ADC_ConvertedValue[3];// 局部变量,用于保存转换计算后的电压值
float ADC_ConvertedValueLocal[3]; static void Delay(__IO uint32_t nCount)    //简单的延时函数
{for(; nCount != 0; nCount--);
}/*** @brief  主函数* @param  无* @retval 无*/
int main(void)
{   /*初始化USART 配置模式为 115200 8-N-1,中断接收*/Debug_USART_Config();Rheostat_Init();    while (1){Delay(0xffffee);  ADC_ConvertedValueLocal[0] =(float)((uint16_t)ADC_ConvertedValue[0]*3.3/4096); ADC_ConvertedValueLocal[1] =(float)((uint16_t)ADC_ConvertedValue[1]*3.3/4096);ADC_ConvertedValueLocal[2] =(float)((uint16_t)ADC_ConvertedValue[2]*3.3/4096);printf("\r\n The current AD value = 0x%08X \r\n", ADC_ConvertedValue[0]); printf("\r\n The current AD value = 0x%08X \r\n", ADC_ConvertedValue[1]); printf("\r\n The current AD value = 0x%08X \r\n", ADC_ConvertedValue[2]); printf("\r\n The current ADC1 value = %f V \r\n",ADC_ConvertedValueLocal[0]); printf("\r\n The current ADC2 value = %f V \r\n",ADC_ConvertedValueLocal[1]);printf("\r\n The current ADC3 value = %f V \r\n",ADC_ConvertedValueLocal[2]);}
}/*********************************************END OF FILE**********************/#ifndef __BSP_ADC_H
#define __BSP_ADC_H#include "stm32f4xx.h"// ADC GPIO 宏定义
#define RHEOSTAT_ADC_GPIO_PORT    GPIOC
#define RHEOSTAT_ADC_GPIO_PIN     GPIO_Pin_2
#define RHEOSTAT_ADC_GPIO_CLK     RCC_AHB1Periph_GPIOC// ADC 序号宏定义
#define RHEOSTAT_ADC1             ADC1
#define RHEOSTAT_ADC1_CLK         RCC_APB2Periph_ADC1
#define RHEOSTAT_ADC2             ADC2
#define RHEOSTAT_ADC2_CLK         RCC_APB2Periph_ADC2
#define RHEOSTAT_ADC3             ADC3
#define RHEOSTAT_ADC3_CLK         RCC_APB2Periph_ADC3
#define RHEOSTAT_ADC_CHANNEL      ADC_Channel_12
// ADC CDR寄存器宏定义,ADC转换后的数字值则存放在这里
#define RHEOSTAT_ADC_CDR_ADDR    ((uint32_t)0x40012308)// ADC DMA 通道宏定义,这里我们使用DMA传输
#define RHEOSTAT_ADC_DMA_CLK      RCC_AHB1Periph_DMA2
#define RHEOSTAT_ADC_DMA_CHANNEL  DMA_Channel_0
#define RHEOSTAT_ADC_DMA_STREAM   DMA2_Stream0void Rheostat_Init(void);#endif /* __BSP_ADC_H *//********************************************************************************* @file    bsp_bsp_adc.c* @author  fire* @version V1.0* @date    2015-xx-xx* @brief   adc驱动******************************************************************************* @attention** 实验平台:野火  STM32 F407 开发板  * 论坛    :http://www.firebbs.cn* 淘宝    :https://fire-stm32.taobao.com********************************************************************************/
#include "./adc/bsp_adc.h"__IO uint32_t ADC_ConvertedValue[3];static void Rheostat_ADC_GPIO_Config(void)
{GPIO_InitTypeDef GPIO_InitStructure;// 使能 GPIO 时钟RCC_AHB1PeriphClockCmd(RHEOSTAT_ADC_GPIO_CLK, ENABLE);// 配置 IOGPIO_InitStructure.GPIO_Pin = RHEOSTAT_ADC_GPIO_PIN;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;     GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ; //不上拉不下拉GPIO_Init(RHEOSTAT_ADC_GPIO_PORT, &GPIO_InitStructure);
}static void Rheostat_ADC_Mode_Config(void)
{DMA_InitTypeDef DMA_InitStructure;ADC_InitTypeDef ADC_InitStructure;ADC_CommonInitTypeDef ADC_CommonInitStructure;// ------------------DMA Init 结构体参数 初始化--------------------------// ADC1使用DMA2,数据流0,通道0,这个是手册固定死的// 开启DMA时钟RCC_AHB1PeriphClockCmd(RHEOSTAT_ADC_DMA_CLK, ENABLE); // 外设基址为:ADC 数据寄存器地址DMA_InitStructure.DMA_PeripheralBaseAddr = RHEOSTAT_ADC_CDR_ADDR;  // 存储器地址,实际上就是一个内部SRAM的变量    DMA_InitStructure.DMA_Memory0BaseAddr = (u32)ADC_ConvertedValue;  // 数据传输方向为外设到存储器 DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;    // 缓冲区大小为,指一次传输的数据量DMA_InitStructure.DMA_BufferSize = 3;    // 外设寄存器只有一个,地址不用递增DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;// 存储器地址固定DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; // // 外设数据大小为半字,即两个字节 DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word; //  存储器数据大小也为半字,跟外设数据大小相同DMA_InitStructure.DMA_MemoryDataSize = DMA_PeripheralDataSize_Word;    // 循环传输模式DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;// DMA 传输通道优先级为高,当使用一个DMA通道时,优先级设置不影响DMA_InitStructure.DMA_Priority = DMA_Priority_High;// 禁止DMA FIFO   ,使用直连模式DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;  // FIFO 大小,FIFO模式禁止时,这个不用配置    DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;  // 选择 DMA 通道,通道存在于流中DMA_InitStructure.DMA_Channel = RHEOSTAT_ADC_DMA_CHANNEL; //初始化DMA流,流相当于一个大的管道,管道里面有很多通道DMA_Init(RHEOSTAT_ADC_DMA_STREAM, &DMA_InitStructure);// 使能DMA流DMA_Cmd(RHEOSTAT_ADC_DMA_STREAM, ENABLE);// 开启ADC时钟RCC_APB2PeriphClockCmd(RHEOSTAT_ADC1_CLK , ENABLE);RCC_APB2PeriphClockCmd(RHEOSTAT_ADC2_CLK , ENABLE);RCC_APB2PeriphClockCmd(RHEOSTAT_ADC3_CLK , ENABLE);// -------------------ADC Init 结构体 参数 初始化--------------------------ADC_StructInit(&ADC_InitStructure);// 独立ADC模式ADC_CommonInitStructure.ADC_Mode = ADC_TripleMode_Interl;// 时钟为fpclk x分频  ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div4;// 禁止DMA直接访问模式  ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_2;// 采样时间间隔  ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_20Cycles;  ADC_CommonInit(&ADC_CommonInitStructure);// -------------------ADC Init 结构体 参数 初始化--------------------------// ADC 分辨率ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;// 禁止扫描模式,多通道采集才需要  ADC_InitStructure.ADC_ScanConvMode = DISABLE; // 连续转换  ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; //禁止外部边沿触发ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;//外部触发通道,本例子使用软件触发,此值随便赋值即可ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC1;//数据右对齐    ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;//转换通道 1个ADC_InitStructure.ADC_NbrOfConversion = 1; ADC_Init(RHEOSTAT_ADC1, &ADC_InitStructure);//---------------------------------------------------------------------------// 配置 ADC 通道转换顺序为1,第一个转换,采样时间为3个时钟周期ADC_RegularChannelConfig(RHEOSTAT_ADC1, RHEOSTAT_ADC_CHANNEL, 1, ADC_SampleTime_3Cycles);   //---------------------------------------------------------------------------ADC_Init(RHEOSTAT_ADC2, &ADC_InitStructure);// 配置 ADC 通道转换顺序为1,第一个转换,采样时间为3个时钟周期ADC_RegularChannelConfig(RHEOSTAT_ADC2, RHEOSTAT_ADC_CHANNEL, 1, ADC_SampleTime_3Cycles);   //---------------------------------------------------------------------------ADC_Init(RHEOSTAT_ADC3, &ADC_InitStructure);// 配置 ADC 通道转换顺序为1,第一个转换,采样时间为3个时钟周期ADC_RegularChannelConfig(RHEOSTAT_ADC3, RHEOSTAT_ADC_CHANNEL, 1, ADC_SampleTime_3Cycles); // 使能DMA请求 after last transfer (multi-ADC mode)ADC_MultiModeDMARequestAfterLastTransferCmd(ENABLE);// 使能ADC DMAADC_DMACmd(RHEOSTAT_ADC1, ENABLE);// 使能ADCADC_Cmd(RHEOSTAT_ADC1, ENABLE);  ADC_Cmd(RHEOSTAT_ADC2, ENABLE);  ADC_Cmd(RHEOSTAT_ADC3, ENABLE);  //开始adc转换,软件触发ADC_SoftwareStartConv(RHEOSTAT_ADC1);
//  ADC_SoftwareStartConv(RHEOSTAT_ADC2);
//  ADC_SoftwareStartConv(RHEOSTAT_ADC3);
}void Rheostat_Init(void)
{Rheostat_ADC_GPIO_Config();Rheostat_ADC_Mode_Config();
}

stm32F407 ADC相关推荐

  1. STM32F407 ADC+DMA+定时器 定时采样模拟量

    STM32F407 ADC+DMA+定时器 定时采样模拟量 文章目录 STM32F407 ADC+DMA+定时器 定时采样模拟量 前言 一.硬件原理 1.1 ADC 1.2 定时器 3. DMA 二. ...

  2. 基于STM32F407 ADC双通道 PS2游戏机摇杆ADC采集

    基于STM32F407 ADC双通道 PS2游戏机摇杆ADC采集 一.PS2游戏机摇杆概述 1.1PS2游戏机摇杆概述 1.2PS2游戏机摇杆图解 二.硬件连接分析 三.代码实现 3.1 ADC代码 ...

  3. [STM32F4]STM32F407 ADC采集+DMA传输

    前言        有的项目中需要对多个通道的电压进行一定频率的AD采样. 第一种:是使用定时器去读取,通过检查转换完成标志位来读取,但这样就会加重整个系统的负担,占用CPU资源. 第二种:是采用定时 ...

  4. STM32F407 HAL库 ADC笔记

    STM32F407 ADC简介 stm32f407系列有3个12位精度的逐次趋近型ADC,每个ADC具有多达 19 个复用通道,可测量来自 16 个外部 源.两个内部源和VBATV_{BAT}VBAT ...

  5. 基于STM32F407使用ADC采集电压实验

    核心板:STM32F407 实验目的:使用ADC采集电压值将其打印在串口助手上 目录 ADC简介 STM32F407 ADC通道对应的引脚 STM32F407中的数据寄存器 ADC 规则数据寄存器 ( ...

  6. STM32F407关于ADC 性能问题讨论

    最近在开发一个产品,使用STM32F407的ADC功能,在调试前期,ADC极其不稳定,波动很大.就连原子哥也对其ADC性能提出质疑.结果果真如此吗? 在软件调试之前,一个良好的硬件设计是保证ADC性能 ...

  7. STM32-F407入门学习专题(九) STM32外设之ADC

    目录 1  ADC介绍 1.1 模拟信号&数字信号 1.2 模数转换ADC 1.3 ADC分类 2 STM32 ADC 2.1 功能框图 2.1.1 ADC电源和参考电压 2.1.2 输入通道 ...

  8. STM32F407 DMA采集多通道ADC

    STM32F407和STM32F103在HAL库使用的时候有较大的差别,同时407取消掉了ADC校准,在使用DMA进行多通道采集时需要打开DMA连续请求:hadc1.Init.DMAContinuou ...

  9. ADC模数转换器(基于STM32F407)

    简介 Analog-to-digital converters(模拟数字转换器),我的STM32F407中内置3个ADC,每个 ADC 有 12 位.10 位.8 位和 6 位可选,ADC 具有独立模 ...

最新文章

  1. 中国黑客自揭黑色产业链条:做病毒一定要低调
  2. linux下导入、导出mysql数据库命令
  3. strcat()函数常见问题
  4. [python爬虫] BeautifulSoup和Selenium简单爬取知网信息测试
  5. ole2高级编程技术 pdf_21天快速掌握Python语言,《21天学通Python》PDF版送给你去学...
  6. mysqldump 忽略视图_Mysql备份迁移——Mysqldump(.NET调用Mysqldump.exe方式)——(解决视图嵌视图报错)...
  7. mysql binlog 多少_今天才知道,MySQL 的 binlog 编号可以这么大!
  8. 创建数据库company写出语句_MySQL中最实用的SQL语句
  9. Zend Studio小技巧:自动生成版本信息
  10. Beautiful Sequence
  11. UVC协议CT_ZOOM_RELATIVE_CONTROL选择子放大缩小停止的问题
  12. 关于 RESTFUL API 安全认证方式的一些总结
  13. html播放器参数,sewise HTML5开源播放器参数说明
  14. Papervision 3D的简介
  15. css改变透明背景png图片的图标颜色
  16. 定积分的性质——积分中值定理
  17. 画思维导图的注意事项有哪些?怎样画思维导图?
  18. nodejs之二维码扫描-实现兑换码自动核销
  19. java ftp上传文件相关代码梳理
  20. rg1 蓝光危害rg0_LED蓝光危害评估的最新标准IEC/TR 62778:2014

热门文章

  1. 一个免费全格式MP3音乐播放器的工具
  2. Windows10系统Qt调试ffmpeg.c
  3. 小米随身wif linux平台配置
  4. 105道 CSS 面试题,助你查漏补缺
  5. 怎么压缩图片200k以下?这个压缩工具,3秒无损完成
  6. asp毕业设计—— 基于asp+access的论坛网站设计与实现(毕业论文+程序源码)——论坛网站
  7. 2019.11.10
  8. 通过编程求解炉石传说酒馆战旗最佳血量和攻击力分配方式
  9. 组装机架式服务器,第35讲 组装一台2U机架式服务器演示(2)
  10. imp导入时遇到的问题及解决方式