前言
8 y. v2 C8 Y) W5 d, T" v 最近在调试STM32F2XX系列ADC多通道DMA采集时,发现采集的AD值大于4095,有的65000多了,这是什么节奏?adc不是12位吗,最大才0xfff,即4095,怎么会出现这种情况呢?难到是adc数据对齐方式出现问题了,adc的对齐明明设置的是右对齐啊,神马情况?
6 [$ X) d" P" B( E p
( K" {& O2 q6 E3 ZADC结构体参数分析( @! |* G5 B0 }
百思不得adc之姐,只能keil单步调试,一步一步查看adc结构体的参数。我使用的是adc dma方式采集,共9个通道。初始化程序如下:4 I% X# c( O$ s% `
- void ADC_DMA_Config(void)
; Z4 q6 w. u; n+ b4 R" x3 X - {
) S/ c+ @( r* }2 |) Z- D - ADC_InitTypeDef ADC_InitStructure;7 R }2 u& u7 T) x' a( L
- ADC_CommonInitTypeDef ADC_CommonInitStructure;
L0 E4 k& y, `4 w - DMA_InitTypeDef DMA_InitStructure;- ^6 C# B4 J: ?, W& O" F+ H! g l+ b
- GPIO_InitTypeDef GPIO_InitStructure;
6 s* y% K) p% V$ [
. O& j# C5 V- ^0 z7 U- RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2 | RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOC, ENABLE);
9 N& n5 {; E/ D1 [: } - RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
j9 C* s1 T, Y" ^, q3 w
$ m8 V6 E6 P/ g3 q- DMA_InitStructure.DMA_Channel = DMA_Channel_0;
1 f5 O* z# r' z# J - DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&ADC1->DR;; o; B5 q, z9 l" Q1 b
- DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&ADC_ConvertedValue;
- ~$ _" N x( g2 s - DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
3 X2 F; m' _# {: W- w - DMA_InitStructure.DMA_BufferSize = Sample_Num*Channel_Num;
! r; u% z6 `, k; ~ - DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;( I r9 V- d* S) N0 T% b
- DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;4 b, T/ p M1 l) t2 i
- DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;$ ^' j9 M5 _3 J: ^* G; X
- DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
! x6 T8 ]9 l4 ~# W - DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;( R$ C0 j2 B% d; f+ K4 v: U
- DMA_InitStructure.DMA_Priority = DMA_Priority_High;
3 D; P, T4 C' _, q - DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable; 8 m$ w) u+ b T2 N6 G$ V( K
- DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;
4 m0 L: N6 J6 ^5 |% G! ~ - DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;$ b& K) J/ _( A# K1 {
- DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;. l3 m( O: r) g. g7 e
- DMA_Init(DMA2_Stream0, &DMA_InitStructure);
+ v2 f$ I* u6 f, e0 z - DMA_Cmd(DMA2_Stream0, ENABLE);
- a) r4 a3 \ W' K: I [
5 \3 `6 V" D9 k2 T: |/ }' e7 g v- " {( b+ D; z: L) Z4 e2 G
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 |GPIO_Pin_2 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_7;8 W% \8 w" L! `- l5 C( W
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
& [- L$ b( ^1 e - GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
* c( N2 z6 I5 g5 S* V' ]$ J - GPIO_Init(GPIOA, &GPIO_InitStructure);% s. m- t5 g* K- d6 I
& U8 @. k& ^( z/ `- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_3 | GPIO_Pin_5;
3 ^4 n4 \+ w% ~, s B - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;0 i, j3 `8 ^6 X" f8 O% }2 v
- GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;3 a! W& o( |/ i3 k$ I7 h3 |" g
- GPIO_Init(GPIOC, &GPIO_InitStructure);$ T. j! G0 {& K
% r3 [ V0 _8 m$ z3 s3 w `" `( n- A- /* ADC Common Init **********************************************************/
' y/ C/ _- W% o) h$ |- t - ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;
3 S' G4 x- v3 V* Z. M: a* o X - ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div2;9 H$ h! }$ n# w, c* `3 j
- ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;
, M; v# Y0 ^) F3 z9 Z) C8 \ - ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;! O0 ]( p) c3 i5 Q5 Q6 D
- ADC_CommonInit(&ADC_CommonInitStructure);1 R- ?+ v1 r) x+ K( f
- / I1 P) Z/ [- [( m
- ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;% F) b. Z0 w$ J
- ADC_InitStructure.ADC_ScanConvMode = ENABLE;! L1 z( b4 S+ d' w* B9 c
- ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
! p5 V8 x A% v7 |; }1 \ - ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
, S* X" X2 R4 I0 _4 }* U - ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
; q$ R' K3 m1 m* f - ADC_InitStructure.ADC_NbrOfConversion = 9;7 m; T* ~' m' M* N* y/ E- _: i
- ADC_Init(ADC1, &ADC_InitStructure);
4 r- y0 u0 x) L C4 m
6 I$ y6 V7 F8 U5 o7 ~8 E) G$ o8 g1 Y
) |5 \, _! y' ]. }- ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_3Cycles);1 r, J. O, \3 c: F& u) @6 j
- ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 2, ADC_SampleTime_3Cycles);, n: u: X- q3 }1 u. i
- ADC_RegularChannelConfig(ADC1, ADC_Channel_2, 3, ADC_SampleTime_3Cycles);0 ]6 \4 g4 {5 B+ a5 l( `. x7 k
- ADC_RegularChannelConfig(ADC1, ADC_Channel_4, 4, ADC_SampleTime_3Cycles);
* u" @5 }; G1 h% v% ] z1 k6 n - ADC_RegularChannelConfig(ADC1, ADC_Channel_5, 5, ADC_SampleTime_3Cycles);
7 r3 u( @* d! Y- f" Q - ADC_RegularChannelConfig(ADC1, ADC_Channel_7, 6, ADC_SampleTime_3Cycles);
2 s; x0 r. D2 t - ADC_RegularChannelConfig(ADC1, ADC_Channel_11, 7, ADC_SampleTime_3Cycles); j; e: C$ U/ F7 z8 `
- ADC_RegularChannelConfig(ADC1, ADC_Channel_13, 8, ADC_SampleTime_3Cycles);( a" j, O5 T0 E) D4 b) i$ M
- ADC_RegularChannelConfig(ADC1, ADC_Channel_15, 9, ADC_SampleTime_3Cycles);
, b2 V9 ]) S2 ?7 e) j" v& a
0 F: h# z0 L* N$ m: U$ e' k- ADC_DMARequestAfterLastTransferCmd(ADC1, ENABLE);
0 W/ \& q2 m7 y5 z8 M* }5 | - ADC_DMACmd(ADC1, ENABLE);
& h: i0 J3 J7 r @+ p* V% C - ADC_Cmd(ADC1, ENABLE);, l! G7 H x1 t5 ~% r
- ( [ M9 A/ l4 E; M; X3 p2 T' C
- }
复制代码
/ E& i0 R, \ y5 A$ y W 其中涉及adc的初始化结构体代码部分如下:
$ j: l" M% B- e( Y4 Q2 f4 |
1 Z& v d: o2 \$ z+ O4 K, r ADC_InitTypeDef ADC_InitStructure;! F3 R7 R6 z& r: S
- ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
4 `& N' W( F' i - ADC_InitStructure.ADC_ScanConvMode = ENABLE;
) q( f2 o, N) r& W0 O- w' c- f - ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
1 M; `5 `3 _0 p# { - ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;% d" i7 Y6 G, f- U) J% I
- ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
! Y: K" |' B) z& ], p7 B/ Q+ S - ADC_InitStructure.ADC_NbrOfConversion = 9;
' s- [# d+ X0 Q( L2 ?) X - ADC_Init(ADC1, &ADC_InitStructure);
复制代码 一步一步调式发现结构体有一项ADC_ExternalTrigConv是0x08002d54,这一项并没有初始化对其赋值,忘记给结构体的这一项赋值了。最后这个值通过ADC_Init函数赋值给CR2的时候,第11位(也就是数据对其位)是1了,左对齐了!!!!!& Z, {2 y2 ^; f4 y; L
' |/ L, `6 ` X( u* T+ P
: q9 l5 V& z2 L( H+ D0 L/ G
( e# _" I- V) h% t$ e+ O
下面来重点分析下adc初始化结构体中的各项参数的意义:
; o5 f. n9 V, @3 P0 S6 d 对于STM32,在使用ADC的时候需要配置几个参数。6 |5 q: g# F& t4 }4 B/ C2 d5 R! A
(1) 第一个参数是ADC_Mode,这里设置为独立模式:
% _) [& E' U4 B% ]
2 k2 o4 F$ S$ X" r, k- ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
复制代码 ! q; Z3 z8 `, e7 ]3 Q
在这个模式下,双ADC不能同步,每个ADC接口独立工作。所以如果不需要ADC同步或者只是用了一个ADC的时候,就应该设成独立模式了。5 y$ @; U4 c& {9 J5 x, U
' _: K$ m2 Y( I5 a(2) 第二个参数是ADC_ScanConvMode,这里设置为DISABLE。
2 M, @6 ^. |6 h3 R9 L- ADC_InitStructure.ADC_ScanConvMode = ENABLE;
复制代码
% \1 d, h0 @, l1 g3 q如果只是用了一个通道的话,DISABLE就可以了,如果使用了多个通道的话,则必须将其设置为ENABLE。
0 b( e q* N8 s; h) n7 n6 ~2 _7 ~* M! a! y0 M
(3) 第三个参数是ADC_ContinuousConvMode,这里设置为ENABLE,即连续转换。& ?' ]0 v; x; A# g1 L( a- ~+ h! R
如果设置为DISABLE,则是单次转换。两者的区别在于连续转换直到所有的数据转换完成后才停止转换,而单次转换则只转换一次数据就停止,要再次触发转换才可以。所以如果需要一次性采集1024个数据或者更多,则采用连续转换。
$ i/ P# f& ], i4 w$ c0 N7 c, D! d1 s; \9 s6 a5 g% V
(4) 第四个参数是ADC_ExternalTrigConv,即选择外部触发模式。这里只讲三种:5 Y% @, r. j, n
- B: G( n1 K5 `' N+ o, {' q/ m7 v; F1、第一种是最简单的软件触发,参数一般为ADC_ExternalTrigConv_None(注意STM32F2XX系列这个有点蹊跷,后面会讲这个)。设置好后还要记得调用库函数:5 M" V- Q2 p% d& K
- ADC_SoftwareStartConvCmd(ADC1, ENABLE);
复制代码- void ADC_SoftwareStartConv(ADC_TypeDef* ADCx)
# X; U) [5 D, C" k5 R, H! ` - {
( y# U6 s+ ^3 H6 M8 c - /* Check the parameters */, P! _4 l) ~/ g, F( f" k" G
- assert_param(IS_ADC_ALL_PERIPH(ADCx));
8 t- e& s/ D( U3 W0 e5 c - * x( ?) Z, N, r/ i5 c- h, U% P' ?
- /* Enable the selected ADC conversion for regular group */
9 {( G+ I3 G6 k! d - ADCx->CR2 |= (uint32_t)ADC_CR2_SWSTART;% d o' T7 R; ?% `+ T3 b
- }
复制代码- #define ADC_CR2_SWSTART ((uint32_t)0x40000000) 4 F6 i) h- @6 q5 g0 p
- /*!<Start Conversion of regular channels */
复制代码
/ n: d7 N# i$ \ADC_SoftwareStartConv函数里直接置位CR2的ADC_CR2_SWSTART位,这样触发就启动了。. Z1 v( L- l Y" @; k
% F% T3 m; T1 q; q
2、第二种是定时器通道输出触发。共有这几种:ADC_ExternalTrigConv_T1_CC1、ADC_ExternalTrigConv_T1_CC2、ADC_ExternalTrigConv_T2_CC2、1 w- z {5 C, B& G
) e1 S1 g+ z1 \7 xADC_ExternalTrigConv_T3_T以及ADC_ExternalTrigConv_T4_CC4。定时器输出触发比较麻烦,还需要设置相应的定时器。以
+ H, C5 G9 ]1 f a8 O' G2 ?0 M7 R; N- _* C+ S
ADC_ExternalTrigConv_T2_CC2触发为例设置相应的定时器:
5 E8 x* ]7 O: v1 A0 q5 i' r; z: y1 g* \* l
- void TIM2_Configuration(void)- k" j8 d9 M( V; r: p; }
- g/ H) Z" U0 z/ {( n w- {
% F3 v2 @$ j. P7 c6 S1 h2 g
7 b: a1 I q) E- TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;4 B4 P9 G, s1 C) ?0 E. B1 k% k
1 j7 s' l% ?$ N- TIM_OCInitTypeDef TIM_OCInitStructure;7 S; \9 K$ ] n& k7 v: { Y! }
- : ?6 o U8 u5 _8 I$ y
- TIM_TimeBaseStructure.TIM_Prescaler = 4;
, }4 H ]2 X# F( Y$ c1 t
j6 Z# Y6 ]; \6 L O- TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;3 v1 ]% I2 O5 L6 b; W# b& K
- 1 e7 B* m" ` e9 W
- TIM_TimeBaseStructure.TIM_Period = 0XFF;
) U- P# |: O u; s
/ l% t8 c* l9 o; h. ^- TIM_TimeBaseStructure.TIM_ClockDivision = 0;
! w' E6 ^) m5 q! d
* x+ q% }. W8 ~3 l B- TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
" M/ Y# S# B. T% n6 U - $ A: {6 z* s j
- TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
* H( U) M9 W* r) I W( }2 `
+ b' }1 E& z. ]: O2 \0 I) p
0 L/ x, J/ y- B2 H- TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
9 [# j4 D' @7 q. `! q
$ K( f* X, w7 ^- TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
( Z/ ?6 X% G; t9 C! P, h; R
, V6 n) B- Q$ g- TIM_OCInitStructure.TIM_Pulse = 0X7F;" B% I9 z( p; M" \5 b
7 N7 b$ n' l, L$ D- TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;- N% r- j; ]: V+ M! c
- ! X/ {! X, I1 i" H+ o/ S+ j
- TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;
# n; n* P0 j2 r7 q- X3 n - ; Z3 X8 o6 D* k5 r, j0 C9 l g
- //配置CC2的属性。若CC3作为ADC的触发源,则应改为TIM_OC3Init(TIM2, &TIM_OCInitStructure);; m9 E2 M: ?1 L( C- F$ L
- ! t* i8 z. G* ?" n$ `; t# ~: m; B
- TIM_OC2Init(TIM2, &TIM_OCInitStructure);
/ K$ b" i& F! R2 ?) F5 `' Z
. ^0 x. o" B7 j0 x5 X% O( u9 h- TIM_Cmd(TIM2, ENABLE);
2 k% ^6 P; a4 n - TIM_CtrlPWMOutputs(TIM2, ENABLE);
/ J. J4 K; K- M* T. G7 a P - }
复制代码 3 y6 K! s6 [; p0 _1 w* t
+ z; Q' ^3 C; o这样设置之后就可以用定时器2的输出触发了,至于触发的周期,设置TIM2的时间即可。这里不再赘述。
% p) @/ e- p5 V' U1 r4 j
1 }) x: i# U8 s9 w* l1 c. T7 S/ t3、第三种是外部引脚触发,对于规则通道,选择EXTI线11和TIM8_TRGO作为外部触发事件;而注入通道组则选择EXTI线15和TIM8_CC4作为外部触发事件。
, L3 W: h: K; z, k" I# s7 U) p7 {4 h2 k8 p+ v2 i
(5) 第五个参数是ADC_DataAlign,这里设置为ADC_DataAlign_Right右对齐方式。建议采用右对齐方式,因为这样处理数据会比较方便。当然如果要从高位开始传输数据,那么采用左对齐优势就明显了。
" D, I0 F+ p- r2 Z. g5 o: K( b$ p& r' |
(6) 第六个参数是ADC_NbrOfChannel,顾名思义:通道的数量。要是到多个通道采集数据的话就得设置一下这个参数。此外在规则通道组的配置函数中也许将各个通道的顺序定义一下,如:
1 s- C4 P8 V( B4 h- ADC_RegularChannelConfig(ADC1,ADC_Channel_13,1,ADC_SampleTime_13Cycles5);
+ D2 F- u. o/ x) B - / p6 d# W; ^6 K2 ]: g% L. \
- ADC_RegularChannelConfig(ADC1,ADC_Channel_14,2,ADC_SampleTime_13Cycles5);
复制代码 - H' L& v' n( J5 q* T1 r# [3 o, ~( z
4 X4 I' ~3 f) |6 C7 _' F; h
多通道数据传输时有一点还要注意:若一个数组为ADC_ValueTab[4],且设置了两个通道:通道1和通道2,则转换结束后,ADC_ValueTab[0]和ADC_ValueTab[2]存储的是通道1的数据,而ADC_ValueTab[1]和ADC_ValueTab[3]存储的是通道2的数据。如果数组容量大则依次类推。7 @: v$ \. h! ^
, _* s# s# s: F8 }, d+ j5 x% W/ Y
补充一点:在使用DMA传输数据的时候,需要设置外设地址和存储器地址,外设地址当然就是ADC的地址了,而存储器的地址如果使用8位数据的话,存储器必须定义为8位缓冲区;如果使用16位数据格式的话,存储器则为16位缓冲器,不可定义为32位或更多,否则,数据将出错。, M* A1 k. r: R6 z0 K( y
+ U( h" b1 |, Z. A. U" U
问题的解决方法
5 ~8 t5 W } o; Q8 ?; w5 i( p 上面分析了adc结构体的参数,下面再来单独看看ADC_ExternalTrigConv这一项。8 o1 f0 s8 R% Z" v$ s) @
在stm32f2xx_adc.h文件中有这个成员的参数定义,发现里面并没有ADC_ExternalTrigConv_None这个常见的定义。
D$ t2 e7 ^' w2 T7 Y; Z2 O2 ]1 `' f9 Y3 M+ L. Y/ |
- /** @defgroup ADC_extrenal_trigger_sources_for_regular_channels_conversion
1 {! {! S% T; f8 `9 ^0 u: f - * @{
$ p# {8 d6 Q5 i& K - */ 9 t' _5 O' J1 o$ g
- #define ADC_ExternalTrigConv_T1_CC1 ((uint32_t)0x00000000)
! S1 B9 s& W7 u. }! o) ? - #define ADC_ExternalTrigConv_T1_CC2 ((uint32_t)0x01000000)
- c: Z2 n( |; s1 k; R* l - #define ADC_ExternalTrigConv_T1_CC3 ((uint32_t)0x02000000)$ a% {" q% I( p5 g$ Z' h; O$ @
- #define ADC_ExternalTrigConv_T2_CC2 ((uint32_t)0x03000000)- U1 G( }; s- [9 u/ y) A
- #define ADC_ExternalTrigConv_T2_CC3 ((uint32_t)0x04000000). U1 h, U/ [* P' b% |' P# i
- #define ADC_ExternalTrigConv_T2_CC4 ((uint32_t)0x05000000)
& @9 X$ Z0 z; L8 e- l - #define ADC_ExternalTrigConv_T2_TRGO ((uint32_t)0x06000000)
2 B$ A0 { }! z1 n3 \/ j4 i - #define ADC_ExternalTrigConv_T3_CC1 ((uint32_t)0x07000000)1 O; L; b/ ]$ Z1 l4 v
- #define ADC_ExternalTrigConv_T3_TRGO ((uint32_t)0x08000000)
+ _- s+ f8 R8 T7 X5 S - #define ADC_ExternalTrigConv_T4_CC4 ((uint32_t)0x09000000)0 X& ~" D Y: u2 N
- #define ADC_ExternalTrigConv_T5_CC1 ((uint32_t)0x0A000000)+ y+ z( ]0 v9 _6 Q8 \
- #define ADC_ExternalTrigConv_T5_CC2 ((uint32_t)0x0B000000)& R, y1 X" l$ U8 Z
- #define ADC_ExternalTrigConv_T5_CC3 ((uint32_t)0x0C000000)
, R3 ?* j0 A* U7 v, S& N - #define ADC_ExternalTrigConv_T8_CC1 ((uint32_t)0x0D000000)
1 n, W: m. T# q6 l0 D- F - #define ADC_ExternalTrigConv_T8_TRGO ((uint32_t)0x0E000000)
5 D) O e- J( Q* m( M3 p - #define ADC_ExternalTrigConv_Ext_IT11 ((uint32_t)0x0F000000)
复制代码 5 z6 {; \9 K* F1 i0 b2 K/ W7 }) a
再来看看stm32f10x_adc.h文件中的ADC_ExternalTrigConv的参数定义:
6 P% s$ b+ n% T2 I- /** @defgroup ADC_external_trigger_sources_for_regular_channels_conversion 4 h9 I8 E/ @" e( T4 V& g \
- * @{7 Y( Z- z- Y Z Y
- */
* m" m3 O1 A2 t' f$ x - . d" E9 V% E$ p2 d8 ~
- #define ADC_ExternalTrigConv_T1_CC1 ((uint32_t)0x00000000) /*!< For ADC1 and ADC2 */) y3 l. k( T6 \3 R
- #define ADC_ExternalTrigConv_T1_CC2 ((uint32_t)0x00020000) /*!< For ADC1 and ADC2 */- L* S; Y# N: x/ J
- #define ADC_ExternalTrigConv_T2_CC2 ((uint32_t)0x00060000) /*!< For ADC1 and ADC2 */
0 X; T' Y$ P% O2 A3 p' J1 E% \ - #define ADC_ExternalTrigConv_T3_TRGO ((uint32_t)0x00080000) /*!< For ADC1 and ADC2 */
/ }6 [5 x1 W, \9 ?7 r* ~# ^1 K0 Q - #define ADC_ExternalTrigConv_T4_CC4 ((uint32_t)0x000A0000) /*!< For ADC1 and ADC2 */- Z6 Q u b$ b4 ^
- #define ADC_ExternalTrigConv_Ext_IT11_TIM8_TRGO ((uint32_t)0x000C0000) /*!< For ADC1 and ADC2 */0 [) V; x5 V. T, s- h
- ! T% o, c, e; w
- #define ADC_ExternalTrigConv_T1_CC3 ((uint32_t)0x00040000) /*!< For ADC1, ADC2 and ADC3 */+ }; D4 n) N7 z, c' J
- #define ADC_ExternalTrigConv_None ((uint32_t)0x000E0000) /*!< For ADC1, ADC2 and ADC3 */ //f2xx系列并没有这个定义/ r% _0 A/ ^$ Z# V; Y
- 1 H( z, _* u& S6 e
- #define ADC_ExternalTrigConv_T3_CC1 ((uint32_t)0x00000000) /*!< For ADC3 only */3 F$ ?1 {+ e, F
- #define ADC_ExternalTrigConv_T2_CC3 ((uint32_t)0x00020000) /*!< For ADC3 only */4 d) {: d% C; d
- #define ADC_ExternalTrigConv_T8_CC1 ((uint32_t)0x00060000) /*!< For ADC3 only */- [0 V/ u6 j7 c: p3 ^
- #define ADC_ExternalTrigConv_T8_TRGO ((uint32_t)0x00080000) /*!< For ADC3 only */
3 R+ }1 ]+ X9 ^8 Z3 Z& I - #define ADC_ExternalTrigConv_T5_CC1 ((uint32_t)0x000A0000) /*!< For ADC3 only */& S, R$ B5 A; t2 {) o
- #define ADC_ExternalTrigConv_T5_CC3 ((uint32_t)0x000C0000) /*!< For ADC3 only */
复制代码 7 b: p! I) W# K' ]0 \5 w
对比发现stm32f2xx系列并没有ADC_ExternalTrigConv_None这个定义,很是奇怪,现在还不明白ST的工程师为什么做这个变动。
& V1 ^. p+ {; R& d& Q& u j9 y8 s 那么问题怎么解决呢?
) G8 l& F; C, _* b3 r/ \3 A 一种是进行adc结构体的初始化操作,在配置之前恢复默认值。即调用ADC_StructInit(&ADC_InitStructure);修改如下:- ADC_StructInit(&ADC_InitStructure);//新增加的$ x/ P2 k/ \3 F5 C3 V
- ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;) D/ T3 ^7 l. m, K' z! U
- ADC_InitStructure.ADC_ScanConvMode = ENABLE;# @* R/ j$ w& _& A
- ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;! B9 n& f; c4 u* y
- ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
$ c" `6 D0 i& k3 N0 o* d - ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
$ u0 O1 r( [$ r! ?# a0 ?0 N/ n - ADC_InitStructure.ADC_NbrOfConversion = 9;
8 @% n4 H0 y9 S2 N - ADC_Init(ADC1, &ADC_InitStructure);
复制代码 调用ADC_StructInit(&ADC_InitStructure)语句,ADC_ExternalTrigConv会恢复默认值0。如下:
3 p# k* V: k* Z9 I' o5 e& q, \" q: O. R" Y1 b
K, Y$ `/ M t- Y% }9 [
1 l I3 Z0 q: @& ~% i5 i( X# P 另一种方法是直接配置该参数为0,如下:7 n1 u9 `$ Y) ~/ k, [+ J# s# j
- ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;( V* G9 a1 Y! C7 j* i5 c, T2 B$ f
- ADC_InitStructure.ADC_ScanConvMode = ENABLE;
6 d0 @8 ]. ?, [$ `! a! M - ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;. P) ^( w M$ U/ o- J! j. T7 P, A$ v
- ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;. r% I' E1 k' a& h
- ADC_InitStructure.ADC_ExternalTrigConv= 0;//新增加的! u' a, f/ ]2 ~% M1 r. U+ a
- ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;, G" H, E: }5 F1 D
- ADC_InitStructure.ADC_NbrOfConversion = 9;
( A5 E) @' g% D* ~; W1 U4 l( ]! \+ r - ADC_Init(ADC1, &ADC_InitStructure);
复制代码
+ D) n2 k9 i! ~& w 这两种方法都可以解决adc采样对齐方式异常问题。& A, N/ J, L" D+ d/ Y2 i4 B
但是ADC_ExternalTrigConv= 0在stm32f2xx_adc.h中其实是对应ADC_ExternalTrigConv_T1_CC1的。
9 o \: J4 K6 J- h1 I
4 w6 ~5 A/ Q2 q) g9 Q; j3 v& z' L$ K' w8 {4 E: g; z1 O
& F0 _0 ^8 W U7 ~ 也就是说调用软件触发函数ADC_SoftwareStartConv函数里直接置位CR2的ADC_CR2_SWSTART位也可以触发定时器触发方式的adc通道。
- k! |. Y. m* `5 f* E; D5 \1 x: _+ x5 N
. T, Y6 h6 _$ @# U$ g4 g6 t. R! W' t: ?1 k, g. k2 `& d: z7 @ y/ [
9 y* j/ i. m1 F- h1 a! F
|