1. STM32F103 ADC 本例使用STM32F103芯片的PA1引脚测试模拟输入的电压值。 查看文档《STM32F103X.pdf》第31页,引脚定义图: - Y) a: P4 r# h6 a
6 h& Q1 @5 [% [1 z* b4 n- @
得知PA1使用ADC1的通道1。 查看文档《STM32F103X.pdf》第13页,时钟树图: * C% \. \3 T$ D/ E1 R
8 H* d3 y( C$ @" H2 t
得知ADC1可2,4,6,8分频,又ADC输入时钟不得超过14MHZ(参见STM32参考手册RM0008第11章ADC)。 - //初始化ADC: _ s# z# q% L: @4 S
- //这里我们仅以规则通道为例, q+ s' G5 G9 K) }: l5 o" g+ h
- //我们默认将开启通道0~3
' j8 _4 C7 y. k2 _1 N2 z - void Adc_Init(void)# Z8 p" d3 K6 }$ T! p6 C
- {
) |. \: L2 ~$ h, n- O+ w - ADC_InitTypeDef ADC_InitStructure;
/ G d; W" n) H. h - GPIO_InitTypeDef GPIO_InitStructure; M- x6 e* V1 a
& `6 S, V0 p0 a5 Z2 ^7 K# @' F- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA |RCC_APB2Periph_ADC1, ENABLE ); //使能ADC1通道时钟
1 d: ^. t/ ?) H; w( k - : m! m8 a x9 T" R7 O- Z6 w. T
7 I2 ~8 q {( Y0 y, V" \- o- RCC_ADCCLKConfig(RCC_PCLK2_Div6); //设置ADC分频因子6 72M/6=12,ADC最大时间不能超过14M1 h+ z7 h$ ?1 S: v6 o
- 1 c% U+ K/ k- P# q3 U9 J% a
- //PA1 作为模拟通道输入引脚 3 [; E A$ Q: U2 Y
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;2 X! D) Q$ m4 U# |7 k ?
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; //模拟输入引脚
5 s- Y/ N C: S8 @& x/ \1 Y# X - GPIO_Init(GPIOA, &GPIO_InitStructure); / j7 s/ n! o3 l# d/ t7 y
. S. Y, E% n4 M' l' F$ D- ADC_DeInit(ADC1); //复位ADC1,将外设 ADC1 的全部寄存器重设为缺省值, N1 G$ T; O; G" K$ z/ D3 l
& N. M. r( q. p1 X( H! X" ~- ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; //ADC工作模式:ADC1和ADC2工作在独立模式1 `6 G4 ]. p7 g
- ADC_InitStructure.ADC_ScanConvMode = DISABLE; //模数转换工作在单通道模式; { B5 {2 d5 V5 y
- ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; //模数转换工作在单次转换模式' L2 O3 J3 @/ b# X1 f6 h: E
- ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; //转换由软件而不是外部触发启动
2 S; K% f1 T, r% K7 G+ H5 v - ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //ADC数据右对齐' I$ s- D9 E* N
- ADC_InitStructure.ADC_NbrOfChannel = 1; //顺序进行规则转换的ADC通道的数目
+ n0 p/ H& q/ i: U$ p$ S7 r/ I" l& h - ADC_Init(ADC1, &ADC_InitStructure); //根据ADC_InitStruct中指定的参数初始化外设ADCx的寄存器
% ?. p( J2 W+ |. r6 S# N- A
: q5 k2 i$ J' U F" W- ADC_Cmd(ADC1, ENABLE); //使能指定的ADC1
0 H, b% V7 B0 a( t% T% x - ADC_ResetCalibration(ADC1); //使能复位校准
, `" y- l T* |7 \8 t1 k/ } - while(ADC_GetResetCalibrationStatus(ADC1)); //等待复位校准结束
' {$ U/ Y- S! a5 q; W8 I" H3 _ - ADC_StartCalibration(ADC1); //开启AD校准
/ t$ v" J& k% l \0 H0 R$ u - while(ADC_GetCalibrationStatus(ADC1)); //等待校准结束% p. @9 I) F" ^( K9 g
- ADC_SoftwareStartConvCmd(ADC1, ENABLE); //使能指定的ADC1的软件转换启动功能
# ~. M5 d/ N' D# N - }
复制代码- //获得ADC值0 X- F6 r" H( L* F
- //ch:通道值 0~3
( f- U" Z; Q; u' y4 `' X! Y- q. j - u16 Get_Adc(u8 ch)
( j3 F* B* T# }7 E( @, \7 } - {2 c# O8 n# a% m" t) @" a
- //设置指定ADC的规则组通道,一个序列,采样时间
1 [( E3 y- |) {4 d0 M* E* B" c - ADC_RegularChannelConfig(ADC1, ch, 1, ADC_SampleTime_239Cycles5 ); //ADC1,ADC通道,采样时间为239.5周期 . J* N% a7 H7 g9 o( {
- ADC_SoftwareStartConvCmd(ADC1, ENABLE); //使能指定的ADC1的软件转换启动功能 ; ^# K7 b. H& z6 a% x; {- s
- while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC ));//等待转换结束
4 I5 a( J' g& ^5 X4 G! ] - return ADC_GetConversionValue(ADC1); //返回最近一次ADC1规则组的转换结果8 E3 z: j) T7 | A
- }
' s; \; I4 q/ u7 G - & `" r- T& f' L: t" A
- u16 Get_Adc_Average(u8 ch,u8 times)
& F/ z$ Y$ [" [ - {
; R1 X- V; Q ]1 ` - u32 temp_val=0;8 d K3 c l3 R l ]* B
- u8 t;
* D$ ]2 ]2 c6 H9 j, ^% d - for(t=0;t<times;t++)
: L" x C3 ^; X5 s: Z1 S - {
1 ` t8 p; D4 o. t ^/ i - temp_val+=Get_Adc(ch); N+ ~3 k/ Q4 A
- delay_ms(5);8 b o: a: T: [. d/ m- y; z0 m
- }
# B% K0 W) k8 F - return temp_val/times;
1 B% a" f( c. g& ]. u4 ]& F4 u b - }
8 A& i; |7 D. k& u& g! B9 Q' E
& T/ l' b3 A. g) `, M; \3 s3 g- void ADCTask(void)
. k0 W5 A% Z s5 K - {/ @2 e" r+ h4 ^6 E: J- e( w
- float vol, adcx;
+ i: J: J% I* ` - while(1)
+ D" }, Z# u5 U ~0 ~, v( g) z - {
- F" |& m! E3 P: S$ A! C - adcx=Get_Adc_Average(ADC_Channel_1,10); //ADC的值3 d% A- w" y; N5 ?2 D5 b" ^4 O3 d
- vol=(float)adcx*(3300/4096); //电压值(mv) m6 V! c6 `: q" u
- delay_ms(200);
% ^' l5 }$ S7 i& G - }* }' M O+ `" O& {( G0 G+ [
- }
复制代码
* C( c, _+ W7 e7 k2、 STM32F407 ADC 本例使用STM32F407芯片的PF9引脚测试模拟输入的电压值。 ; m* Z& n7 M- V* T% S: A0 z0 {
9 P* Q( I+ P6 H4 v! M8 `+ z1 Q查看文档《STM32F4x7-Datasheet.pdf》第43页,引脚定义图:
* q9 s4 t; F3 O2 o% W$ O8 ~查看文档《STM32F4x7-Reference manual.pdf》第51页,内存映射:
6 u# J2 O+ c3 z0 {: o; H% S/ d点击链接查看ADC寄存器映射: ! C [4 z( i9 d8 m. t; l9 [# ]/ z
又查看数据寄存器偏移量:
! Q& k4 \& j0 C d7 s' o得知数据寄存器地址:#define ADC3_DR_ADDRESS ((uint32_t)0x4001224C)
8 {1 `# f6 |2 n3 G: j" _4 d8 c% R, [5 h- v3 M
得知使用DMA2 Stream0 通道2映射ADC3。 - #define ADC3_DR_ADDRESS ((uint32_t)0x4001224C)
! C, F6 H% [: q, k& W
, K$ ^: ]1 B. z+ I- __IO uint16_t ADC3ConvertedValue = 0;
# I: I) \- N2 B - __IO uint32_t ADC3ConvertedVoltage = 0;
- Q7 T0 D6 \) O' ^% k0 r
6 \# y) A7 H6 B# F* r3 l- //ADC3 channel07 with DMA configuration
3 g3 M! i- H: S: z, P! t# K5 V - void ADC3_CH7_DMA_Config(void)
2 r% X' E/ O, j4 j1 o$ @9 r - {7 ^6 C" n7 B$ O& O5 e' Z4 ~ Z( a
- ADC_InitTypeDef ADC_InitStructure;3 A" I) o, q* `0 s, ~$ a" U5 b: Q1 Q
- ADC_CommonInitTypeDef ADC_CommonInitStructure;; k( h: `& o2 N/ k2 L* A' y) V2 z# r+ @
- DMA_InitTypeDef DMA_InitStructure;
( y' q. r: B# { - GPIO_InitTypeDef GPIO_InitStructure;* O7 t4 h" f% {- ~, a; K
% w# [! {- O( N2 p7 @ j# ^- g- /* Enable ADC3, DMA2 and GPIO clocks ****************************************/4 M% E+ u- S) ~$ ]* C
- RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2 | RCC_AHB1Periph_GPIOF, ENABLE);
7 K9 H0 N a B! p - RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC3, ENABLE);
/ }* h) {% s1 f( W+ x. Y9 s w3 U
; Y# c1 g2 e: _; t7 D' _4 ]8 u# D- /* DMA2 Stream0 channel2 configuration **************************************/9 {* O: F, s f: d* x) b1 ?0 @
- DMA_InitStructure.DMA_Channel = DMA_Channel_2; ( E, j2 t- a* h" y4 A' R, E. N
- DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)ADC3_DR_ADDRESS;
( k0 j) v4 f" @3 X - DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&ADC3ConvertedValue;
+ x; t; W; V9 l4 B/ ^: }6 X. i - DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;! V6 D( E( B- ~, ~( l
- DMA_InitStructure.DMA_BufferSize = 1;
! v5 V) H/ }9 I# ?& Y* x( X& ? - DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
2 B8 g) b# G9 L2 f. \% K C - DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable;
6 c' H! i, _0 p6 H - DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
! D$ o( Q5 l) w0 u" L% \ - DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
2 ]/ a3 y9 k# j8 v! ?0 D - DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
6 ]0 x+ j% Y+ ?/ ~7 N3 {% ^ - DMA_InitStructure.DMA_Priority = DMA_Priority_High;
3 A' f% [+ A* d' h! v - DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
4 w1 B6 w7 s1 z) Q - DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;$ L- f+ A/ v F& F, W
- DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single; t/ |; X9 b: x6 n6 g+ A4 `! c
- DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
- q! {+ H$ d; b- p' ^ - DMA_Init(DMA2_Stream0, &DMA_InitStructure);
/ q* U0 H$ O7 t0 |* B- T2 k2 U# c - DMA_Cmd(DMA2_Stream0, ENABLE);
) K, w9 ^4 {" U4 l* L3 G - # S% ]" l" U+ T
- /* Configure ADC3 Channel7 pin as analog input ******************************/# O# L+ b5 g2 v: f
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
7 r" h& W2 j/ }9 O - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
% ]- Q3 Z8 A3 Q. U0 O- r+ Y' O - GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ; e$ v% Q! _. J& G9 ?9 N
- GPIO_Init(GPIOF, &GPIO_InitStructure);
) m# A W0 c4 T: E" [2 n1 h' g$ a
% m. r* J* D" s; y* n- /* ADC Common Init **********************************************************/, l2 v! ]5 Y. h4 ~4 P# y. j
- ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;
3 O; P/ H' S; h& C( ?2 h' z4 Z9 {3 w/ X! B - ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div2;" a) z A7 i7 @1 p/ p
- ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;" z2 M$ E7 }" v; Y X3 q
- ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;5 z1 m$ P9 O+ r, s+ l6 I$ ]# ^
- ADC_CommonInit(&ADC_CommonInitStructure);
* L2 C0 ^ q# f& {: Y O% j* X
' H) p" Q7 n! U: ]5 z k# G- /* ADC3 Init ****************************************************************/7 A6 b, C9 H, W0 y6 ?
- ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;/ p! r. S. a" q. g; |6 b
- ADC_InitStructure.ADC_ScanConvMode = DISABLE;( x4 X, z! }8 D3 ?# ~) I7 ?1 f
- ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;6 ]9 \. j- S9 O* C# E
- ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
# `5 J5 b- M3 a - ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC1;; _$ {+ Q3 e. J) l& ]; J ~
- ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;+ U+ q# ?4 ^1 i$ l# s" T: i% h
- ADC_InitStructure.ADC_NbrOfConversion = 1;
2 L# T" W/ r+ f6 W5 X0 Q1 o - ADC_Init(ADC3, &ADC_InitStructure);
9 a) C2 [9 Y1 I& J4 T! w2 y
- g. ~+ i6 n4 M% X; Y- /* ADC3 regular channel7 configuration *************************************/+ x J: S; {: ]
- ADC_RegularChannelConfig(ADC3, ADC_Channel_7, 1, ADC_SampleTime_3Cycles);
" z( P$ s9 w8 M& |7 n# D - , _! S. h7 d# _9 ?% m! n5 I% |) f
- /* Enable DMA request after last transfer (Single-ADC mode) */
% v3 r# b4 |$ @4 L# x7 U$ [ - ADC_DMARequestAfterLastTransferCmd(ADC3, ENABLE);$ `. ]4 n( l0 }0 i0 Y' ^/ o
! j1 t O, e# O% }- /* Enable ADC3 DMA */
& O3 f& V; F% |" r- r- C7 d% }$ L7 { - ADC_DMACmd(ADC3, ENABLE);9 N" I- n4 @0 K! J
- k* d' E7 x0 r9 B
- /* Enable ADC3 */
1 [* ]" d( F8 M! ?6 N - ADC_Cmd(ADC3, ENABLE);3 n9 O6 J# Q# f6 Y- k7 o Z* T
- }# U9 u5 P: a' v7 I
- 0 P6 a# Y6 f; F3 u- L. c( m
- int main(void)! \1 ?- x) s' d8 s2 y5 ]( B
- {
0 _4 b, @' q( \. Y* q7 }& Q - /* ADC3 configuration *******************************************************/
8 T# ?* j& t, L% d+ J - /* - Enable peripheral clocks */
3 Y1 ~1 P; X; {" z& b W+ t - /* - DMA2_Stream0 channel2 configuration */
; W! Z. f! f8 K - /* - Configure ADC Channel7 pin as analog input */
7 k$ y! i+ j) U* u7 P - /* - Configure ADC3 Channel7 */ ?2 s1 Z! I7 S2 @1 x) d
- ADC3_CH7_DMA_Config();$ q* X* C& m4 d% [. G
- 5 B+ ` N/ m4 X1 S
- /* Start ADC3 Software Conversion */
3 F- Z! w8 |! Z - ADC_SoftwareStartConv(ADC3);7 z( L1 o A+ o* U
3 B! S8 C) L: |2 Y- while (1)5 a. S7 _) S6 l8 F! f
- {7 e6 {5 Y* n$ ~; \ f/ W9 x! z
- ADC3ConvertedVoltage = ADC3ConvertedValue *3300/0xFFF;
( X+ L% X1 f% Q+ w1 q
9 @/ ^/ X, h! `+ ?- delay_ms(200);+ G+ X2 }1 f2 ?! b) }# R
- }7 d( k# \( c7 Z9 k& ?
- }
复制代码 $ F1 ?- Z1 ]% M* n0 f
4 o9 u4 H3 w n+ ]; |. q0 ~ |