1. ADC: Analog to Digital Converter 模/数转换器,或者模拟/数字转换器。
指将连续变量的模拟信号转换为离散的数字信号的器件。
典型的模拟数字转换器将模拟信号转换为表示一定比例电压值的数字信号。
2. stm32f203系列ADC:
3个ADC,
精度为12位,
每个ADC最多16个外部通道
ADC1和ADC2都有16个外部通道,ADC3根据引脚数不同通道数也不同(一般都有8个外部通道)。
3. ADC功能框图
- 电压输入范围: VREF- ≤ VIN ≤ VREF+
- 一般把VSSA 和VREF- 接地,把VREF+ 和VDDA 接电源(如3.3V), 得到ADC的输入电压范围为0~3.3V.
- 如果想扩展电压范围,可以添加外部分压电路。
- 输入通道: 电压传输到ADC的通道
- 18个通道,其中外部通道16个(ADCx_IN0, ADCx_IN1.....ADCx_IN15)
- 16个通道对应不同IO口,具体IO功能从手册查询。
- ADC1,2,3还有内部通道,ADC1通道16连接芯片内部温度传感器;Vrefint连接到通道17.
- ADC2的模拟通道16,17连接到内部的VSS, ADC3的模拟通道9,14,15,16,17连接内部VSS.
- 外部16个通道转换时又分为规则通道和注入通道,其中规则通道最多16路,注入通道最多4路。
- 规则通道:一般使用的通道。
- 注入通道:可以理解为插入,插队。优先级高于规则通道,类似于中断。只有在规则通道存在时注入通道才会出现。
4. 转换顺序
- 转换序列:
- 规则序列寄存器有3个,分别为SQR3, SQR2, SQR1。
- SQR3控制着规则序列中的第1到第6个转换,对应的位为SQ1[4:0]~SQ6[4:0], 第一次转换的是位4:0 SQ1[4:0], 如果通道16想第一次转换,那么在SQ1[4:0]写16即可。
- 注入通道:
- 注入序列寄存器JSQR只有一个,最多支持4个通道,具体多少个由JSQR的JL[2:0]决定。
5. 触发源
- ADC转换可以由ADC控制寄存器2:ADC_CR2的ADON这个位来控制
- 写1:开始转换
- 写0:停止转换
6. 转换时间
- ADC时钟
- ADC输入时钟ADC_CLK由PCLK2经分频产生,最大14M。
- 一般设置PCLK2=HCLK=72M
- 采样时间
- ADC_SMPR2控制通道0~9, ADC_SMPR1控制通道10~17.
- 每个通道可以分别用不同的时间采样。
- 总转换时间如下计算:
- TCONV
- 例如,当ADCCLK = 14MHz,采样时间为1.5周期
- TCONV = 1.5 + 12.5 = 14周期 = 1us
7. 数据寄存器
- ADC转换后的数据根据准换组的不同,规则组的数据放在ADC_DR寄存器,注入组的数据放在JDRx。
- ADC规则数据寄存器: ADC_DR
- 只有1个,是32位寄存器
- 低16位在单ADC时使用,高16位在双ADC模式(ADC1和ADC2同时使用)下保存保存ADC2转换的规则数据
- 由于ADC精度12位,需要左或右对齐。对齐方式由ADC_CR2的11位ALIGN进行设置
- ADC注入数据寄存器
8. 中断
- 规则通道转换结束中断
- 注入转换结束中断
- 模拟看门狗中断
- DMA请求
- 只有ADC1和ADC3可以产生DMA请求;
- 一般我们在使用ADC时会开启DMA传输;
9. 电压转换
- 因为ADC是12位的,12位满量程对应的数字值是:2^12;
- 如果转换后的数值为X,对应的模拟电压为Y,可推出公式: 2^12/3.3 = X/Y => Y= (3.3 *X)/2^12
10. ADC初始化结构体
- ADC_InitTypeDef结构体
typedef struct
{
uint32_t ADC_Mode; //ADC工作模式选择;使用一个ADC为单模式,使用两个为双模式;一般使用单模式
FunctionalState ADC_ScanConvMode; //ADC扫描(多通道)或者单次(单通道)模式选择;单通道DISABLE扫描,多通道ENABLE扫描
FunctionState ADC_ContinousConvMode; //ADC单次转换或者连续转换选择;ENABLE:自动连续转换,DISABLE: 单次转换;一般设置连续转换
uint32_t ADC_ExternalTrigConv; //ADC转换触发信号选择;一般设置软件自动触发
uint32_t ADC_DataAlign; //ADC数据寄存器对齐格式;一般选择右对齐
uint8_t ADC_NbrOfChannel; //ADC采集通道数;根据实际而定
}ADC_InitTypeDef;
11. 独立模式单通道采集实验
- 编程要点
- 初始化ADC用到的GPIO口;
- 设置ADC的工作参数并初始化;
- 设置ADC工作时钟;
- 设置ADC转换通道顺序及采样时间;
- 配置使能ADC转换完成中断,在中断内读取转换完数据;
- 使能ADC;
- 使能软件触发ADC转换;
//*****************ADC GPIO初始化*******************************************************
static void ADCx_GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
//打开ADC IO端口时钟
ADC_GPIO_APBxClock_FUN(ADC_GPIO_CLK, ENABLE);
//配置ADC IO引脚模式
//必须为模拟输入
GPIO_InitStructure.GPIO_Pin = ADC_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
//初始化ADC IO
GPIO_Init(ADC_PORT, &GPIO_InitStructure);
}
//*******************ADC 工作模式配置*******************************************************************
static void ADCx_Mode_Config(void) /*2个作用:(1)配置ADC工作参数; (2)配置DMA工作参数*/
{
DMA_InitTypeDef DMA_InitStructure;
RCC_AHBPeriphClockCmd(ADC_DMA_CLK, ENABLE); /*打开DMA时钟*/
//***********************DMA模式配置****************************
DMA_DeInit(ADC_DMA_CHANNEL); /*复位DMA控制器*/
DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)(&(ADC_x->DR)); /*配置DMA初始化结构体; 外设基址为:ADC数据寄存器地址*/
DMA_InitStructure.DMA_MemoryBaseAddr = (u32)&ADC_ConvertedValue; /*存储器地址*/
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; /*数据源来自外设*/
DMA_InitStructure.DMA_BufferSize = 1; /*缓冲区大小,应该等于数据目的地的大小*/
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_InitStructure.DMA_Priority = DMA_Priority_High; /*DMA传输通道优先级为高,当使用一个DMA通道时,优先级设置不影响*/
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; /*禁止存储器到存储器模式,因为是从外设到存储器*/
DMA_Init(ADC_DMA_CHANNEL, &DMA_InitStructure); /*初始化DMA*/
DMA_Cmd(ADC_DMA_CHANNEL, ENABLE); /*使能DMA通道*/
/*-----------------------ADC 模式配置-------------------------------------------------*/
ADC_InitTypeDef ADC_InitStruct;
ADC_APBxClock_FUN(ADC_CLK, ENABLE); /*打开ADC时钟*/
ADC_InitStruct.ADC_ContinuousConvMode = ENABLE; /*扫描模式*/
ADC_InitStruct.ADC_DataAlign = ADC_DataAlign_Right; /*转换结果右对齐*/
ADC_InitStruct.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; /*不用外部触发转换,软件开启即可*/
ADC_InitStruct.ADC_Mode = ADC_Mode_Independent; /*只使用一个ADC,属于单通道模式*/
ADC_InitStruct.ADC_NbrOfChannel = 1; /*转换通达个数*/
ADC_InitStruct.ADC_ScanConvMode = DISABLE; /*扫描模式*/
ADC_Init(ADC_x, &ADC_InitStruct); /*初始化ADC*/
RCC_ADCCLKConfig(RCC_PCLK2_Div8); /*配置ADC时钟*/
ADC_RegularChannelConfig(ADC_x, ADC_CHANNEL, 1, ADC_SampleTime_55Cycles5); /*配置通道的转换顺序和采样时间*/
//使能ADC DMA请求
ADC_DMACmd(ADC_x, ENABLE);
//开启ADC, 并开始转换
ADC_Cmd(ADC_x, ENABLE);
//ADC开始校准
ADC_StartCalibration(ADC_x);
//等待校准完成
while(ADC_GetCalibrationStatus(ADC_x));
//由于没有采用外部触发,所以使用软件触发ADC转换
ADC_SoftwareStartConvCmd(ADC_x, ENABLE);
}
功能分支图