STM32
自带1
至3
个ADC
模块,采样精度达到了12
位。在STM32F103RBT6
中,ADC1
和ADC2
共用一组管脚。总体编程思路如下:
- 初始化
RCC
相关,使能系统时钟,使能功能模块如ADC
、DMA
的时钟。 GPIO
相关初始化,比如常用的指示灯,ADC
的引脚要设置为输入。NVIC
向量中断的配置,因为这里使用了DMA
中断和中断服务程序编写(下例中暂不使用)。DMA
配置(下例中暂不使用)。ADC
初始化。
相关的通道如下:
通道 | ADC1 | ADC2 | ADC3 |
---|---|---|---|
通道0 | PA0 | PA0 | PA0 |
通道1 | PA1 | PA1 | PA1 |
通道2 | PA2 | PA2 | PA2 |
通道3 | PA3 | PA3 | PA3 |
通道4 | PA4 | PA4 | PF6 |
通道5 | PA5 | PA5 | PF7 |
通道6 | PA6 | PA6 | PF8 |
通道7 | PA7 | PA7 | PF9 |
通道8 | PB0 | PB0 | PF10 |
通道9 | PB1 | PB1 | |
通道10 | PC0 | PC0 | PC0 |
通道11 | PC1 | PC1 | PC1 |
通道12 | PC2 | PC2 | PC2 |
通道13 | PC3 | PC3 | PC3 |
通道14 | PC4 | PC4 | |
通道15 | PC5 | PC5 | |
通道16 | 温度传感器 | ||
通道17 | 内部参考电压 |
以下是参考代码,使用ADC1
的IN0
脚:
void ADC_GPIO_Init ( void ) {
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd ( RCC_APB2Periph_GPIOA | RCC_APB2Periph_ADC1, ENABLE );
GPIO_DeInit ( GPIOA );
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; /* 设为模拟输入 */
GPIO_Init ( GPIOA, &GPIO_InitStructure );
}
void ADC_configuration ( void ) {
ADC_InitTypeDef ADC_InitStructure;
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; /* 独立模式 */
ADC_InitStructure.ADC_ScanConvMode = DISABLE; /* 连续多通道模式 */
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; /* 单次转换 */
/* 转换由软件而不是外部触发启动 */
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; /* 右对齐 */
ADC_InitStructure.ADC_NbrOfChannel = 1; /* 扫描通道数 */
ADC_Init ( ADC1, &ADC_InitStructure );
// ADC_RegularChannelConfig( ADC1, ADC_Channel_0, 1, ADC_SampleTime_7Cycles5 );
ADC_Cmd ( ADC1, ENABLE ); /* 使能或者失能指定的ADC */
ADC_ResetCalibration ( ADC1 ); /* 重置指定的ADC的校准寄存器 */
while ( ADC_GetResetCalibrationStatus ( ADC1 ) ); /* 等待校准寄存器初始化 */
ADC_StartCalibration ( ADC1 ); /* 开始校准 */
while ( ADC_GetCalibrationStatus ( ADC1 ) ); /* 等待校准完成 */
ADC_SoftwareStartConvCmd ( ADC1, ENABLE ); /* 使能指定的ADC的软件转换启动功能 */
}
u16 GetADCValue ( u8 ADC_Channel ) { /* ADC_Channel_x 0~17 */
u16 adc_value;
ADC_RegularChannelConfig ( ADC1, ADC_Channel, 1, ADC_SampleTime_7Cycles5 );
ADC_SoftwareStartConvCmd ( ADC1, ENABLE ); /* 使能指定的ADC的软件转换启动功能 */
/* 检查制定ADC标志位是否置为1,ADC_FLAG_EOC是转换结束标志位 */
while ( ADC_GetFlagStatus ( ADC1, ADC_FLAG_EOC ) == RESET );
adc_value = ADC_GetConversionValue ( ADC1 );
return adc_value; /* 返回最近一次ADCx规则组的转换结果 */
}
当使用内部温度传感器时,需要使能温度传感器通道:
ADC_TempSensorVrefintCmd ( ENABLE );
温度传感器通道号是ADC_Channel_16
,此通道的采样时间调到最大,来保证精度。温度的计算公式如下:
温 度 ( ∘ C ) = V 25 − V S E N S E A v g _ S l o p e + 25 温度(^{\circ}C) = \frac{V_{25}-V_{SENSE}}{Avg\_Slope} + 25 温度(∘C)=Avg_SlopeV25−VSENSE+25
其中
V
25
V_{25}
V25是
V
S
E
N
S
E
V_{SENSE}
VSENSE在
2
5
∘
C
25^{\circ}C
25∘C时的数值;
A
v
g
_
S
l
o
p
e
Avg\_Slope
Avg_Slope是温度与
V
S
E
N
S
E
V_{SENSE}
VSENSE曲线的平均斜率(单位是
m
V
/
∘
C
mV/^{\circ}C
mV/∘C或
μ
V
/
∘
C
\mu V/^{\circ}C
μV/∘C)。
V
25
V_{25}
V25、
V
S
E
N
S
E
V_{SENSE}
VSENSE的典型值分别为
1.43
1.43
1.43、
4.3
m
V
/
∘
C
4.3mV/^{\circ}C
4.3mV/∘C,则TEMP = (1.43 - Vsense)/0.0043 + 25
。
补充说明:
STM32
的ADC
可以分为注入组(Injected Channel
)和规则组(Regular Channel
),规则组放的是常规情况下的检查所需要的数据,注入组放的是特殊情况下的检查所需要的数据(或者是特殊数据),也可以说规则组是主程序,而注入组是中断程序。- 如果你的
ADC_CLK
越小,即你的AD
转换速度越慢,那么AD
转换的精度就越高。 - 注意
STM32
的ADC
功能的触发模块(可允许外部触发,也可以允许内部定时器触发)。 STM32
的ADC
转换模式:单次(对单个端口只转换一次)、连续(对端口连续转换多次)、扫描(对多个端口进行扫描)和中断。- 自动注入(
IAUTO
)将规则组与注入组规为一组。