前言
1 D+ n5 K+ J+ k& a1 _ 最近在调试STM32F2XX系列ADC多通道DMA采集时,发现采集的AD值大于4095,有的65000多了,这是什么节奏?adc不是12位吗,最大才0xfff,即4095,怎么会出现这种情况呢?难到是adc数据对齐方式出现问题了,adc的对齐明明设置的是右对齐啊,神马情况?
( i7 e7 [7 @! m. X0 F" C3 y/ [0 M: c) r* n
ADC结构体参数分析' _8 u4 f m& _% V' \
百思不得adc之姐,只能keil单步调试,一步一步查看adc结构体的参数。我使用的是adc dma方式采集,共9个通道。初始化程序如下:
1 _ \9 S) {) a" f- void ADC_DMA_Config(void)/ {, ]' s5 V, F. ?/ I* x$ u
- {. b0 s& N3 ]& V! ]. v& N! b) O
- ADC_InitTypeDef ADC_InitStructure;
; X& X" E% q8 d& b S - ADC_CommonInitTypeDef ADC_CommonInitStructure;
& k) R, Z& j' [ - DMA_InitTypeDef DMA_InitStructure;+ b: y5 y/ ^4 t0 K: y
- GPIO_InitTypeDef GPIO_InitStructure;
" Q! R- l% E" V2 @" y& \4 W
: ]4 \( p% z" }8 n; M- c- RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2 | RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOC, ENABLE);
# I7 A& [2 O' L - RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);7 J" P5 q3 [# P6 x
- $ Y. A: o: ?6 q$ k' W+ Q
- DMA_InitStructure.DMA_Channel = DMA_Channel_0;
2 R5 `2 r% k! G i( J9 q- K - DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&ADC1->DR;
4 m5 i) Z& y- Y) a" Q - DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&ADC_ConvertedValue;
# G/ x! Y* C2 c R9 J- c9 E* ? - DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
/ m/ t. z% } g - DMA_InitStructure.DMA_BufferSize = Sample_Num*Channel_Num; / T9 ?7 P8 s8 t4 {0 d* K; ]
- DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;. M0 J& ]7 I, Z7 u: p. h
- DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
: A5 Q# `) ]# o9 K - DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
/ C. q2 W) r! R! }) H - DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;) Y5 D. u% I5 z- @ z0 X0 o
- DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
1 b" Y! c G4 P; `; M } m. B. R# Z - DMA_InitStructure.DMA_Priority = DMA_Priority_High;
$ w& y$ [' _( b! Z# g; F7 Z - DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable; 0 J9 u! G/ J8 [2 `1 M
- DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;/ N3 G+ F! w* g; e* _5 T7 z' I
- DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;; D9 T& w" k) ?' q. g G
- DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
& Q0 \' z/ y1 K: H: z3 O - DMA_Init(DMA2_Stream0, &DMA_InitStructure);
# g+ f& F5 r" g - DMA_Cmd(DMA2_Stream0, ENABLE);
: l+ B( e: U2 n4 f0 ?* @1 ~0 E - 4 b" h) C" b3 n f, ^6 ?
- 6 r: o/ ]" p* o
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 |GPIO_Pin_2 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_7;
z# ?' |: J! R) D2 F+ ? - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
2 y5 t( k- L% m - GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;. B: e/ x1 `" K7 O/ @; }' y% U
- GPIO_Init(GPIOA, &GPIO_InitStructure);: U7 Z1 b7 D8 k D% s& p
- 7 k! o' F* @0 U1 K7 K
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_3 | GPIO_Pin_5; x! m, Z& _( P* N) C5 t/ V
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
9 C7 e. d# L, I m4 L* A( K - GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;: W( O$ D: ], Z7 i8 y5 y2 A
- GPIO_Init(GPIOC, &GPIO_InitStructure);1 d% O) h9 n4 X( a2 Y# i. l
- ! F5 f$ k, O4 g
- /* ADC Common Init **********************************************************/
- t$ U4 ]+ m3 K$ k1 Y: f - ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;1 S' ?! f. q, k4 `) u( e
- ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div2;. E) R' e! P) K( W
- ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;
& R# }( ~/ X: {) z( }3 X8 ] - ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;
/ ?# ^5 x# V3 e5 L4 F - ADC_CommonInit(&ADC_CommonInitStructure);
$ _$ N" `* X0 l; q4 b6 E
6 G% ]( g& A& a$ E9 p- S- ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;' Z- x# ?7 \& g1 M, Q, c
- ADC_InitStructure.ADC_ScanConvMode = ENABLE;2 d3 C* u/ n% F
- ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
$ _- i# @7 U' Q - ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;4 y- b' P K! o7 q
- ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;1 h8 C( Y' }! M" T# O
- ADC_InitStructure.ADC_NbrOfConversion = 9;
: n# R5 `$ E* @: Y3 i) X - ADC_Init(ADC1, &ADC_InitStructure);
7 x1 d2 h/ x, S* a, _7 L0 g4 a
# [% P1 k5 i8 w$ J1 @0 E4 G
3 Q7 s( y1 D6 n8 J# N( d; @0 e! W. d% ^7 [- ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_3Cycles);4 A+ ^5 U* d) b7 n, y. A* A
- ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 2, ADC_SampleTime_3Cycles);* u5 r. A8 z( ]6 C6 E2 G
- ADC_RegularChannelConfig(ADC1, ADC_Channel_2, 3, ADC_SampleTime_3Cycles);
3 q1 a$ k, x, H3 ` - ADC_RegularChannelConfig(ADC1, ADC_Channel_4, 4, ADC_SampleTime_3Cycles);3 y4 v* q& [" m( m. b( |
- ADC_RegularChannelConfig(ADC1, ADC_Channel_5, 5, ADC_SampleTime_3Cycles);
5 K' O( A/ Q( r - ADC_RegularChannelConfig(ADC1, ADC_Channel_7, 6, ADC_SampleTime_3Cycles);/ ]$ J N: _7 ~% G9 R) V) r9 h
- ADC_RegularChannelConfig(ADC1, ADC_Channel_11, 7, ADC_SampleTime_3Cycles);0 m) J, x# u* ?
- ADC_RegularChannelConfig(ADC1, ADC_Channel_13, 8, ADC_SampleTime_3Cycles);
5 s0 I! b+ F6 b/ T3 p - ADC_RegularChannelConfig(ADC1, ADC_Channel_15, 9, ADC_SampleTime_3Cycles);: G" c7 i6 k l8 u1 {! v9 J% U& o
- 3 ?* `) Z- ?6 L Z6 v: c) v2 n
- ADC_DMARequestAfterLastTransferCmd(ADC1, ENABLE);8 u! X3 l9 a( s
- ADC_DMACmd(ADC1, ENABLE);7 ?- n# V4 x6 g: M3 A- b" ?! }& E w: O
- ADC_Cmd(ADC1, ENABLE);# m0 i% @2 T0 v- i8 f: s! k( p
( c! i* G% B p: K3 X9 [- }
复制代码
5 `: B! ?$ I" i7 b 其中涉及adc的初始化结构体代码部分如下:
7 ~0 D7 J0 p. @* }5 J c+ X4 W: _2 H8 L* `# X2 E
ADC_InitTypeDef ADC_InitStructure;2 n! Q2 g$ @. t r
- ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;8 K. A5 t s: a2 j u
- ADC_InitStructure.ADC_ScanConvMode = ENABLE;" [0 g/ {8 F X9 b1 v0 R
- ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;: l( P: K$ r& C% O! F! N0 T) M3 T
- ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
Y# Y. q! X- Z+ o - ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
! m/ s1 Q( K# Y/ E - ADC_InitStructure.ADC_NbrOfConversion = 9;# ?- v$ _! s* v$ f. w: Z2 A
- ADC_Init(ADC1, &ADC_InitStructure);
复制代码 一步一步调式发现结构体有一项ADC_ExternalTrigConv是0x08002d54,这一项并没有初始化对其赋值,忘记给结构体的这一项赋值了。最后这个值通过ADC_Init函数赋值给CR2的时候,第11位(也就是数据对其位)是1了,左对齐了!!!!!
$ o: W V" S k2 F5 p
" K+ K ?4 D" U0 k- J. I0 f
7 C, T) O$ d/ _& ^8 |5 S# r) O" t0 Z6 s
下面来重点分析下adc初始化结构体中的各项参数的意义:
! s8 ]% ?2 F$ `! K( q1 j. ? 对于STM32,在使用ADC的时候需要配置几个参数。. j2 M. h9 x) A( i2 R
(1) 第一个参数是ADC_Mode,这里设置为独立模式:
: c! H. d6 r; n0 z
$ ?$ K, Z2 s1 d- I# ^% H, y- ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
复制代码 " [: |: o, C& N* h% h- y# y
在这个模式下,双ADC不能同步,每个ADC接口独立工作。所以如果不需要ADC同步或者只是用了一个ADC的时候,就应该设成独立模式了。
/ h1 Q8 O( j \1 G: J; Z7 I" J4 g0 g" f- @( V$ K' l
(2) 第二个参数是ADC_ScanConvMode,这里设置为DISABLE。: o( L4 C: C _8 D- `
- ADC_InitStructure.ADC_ScanConvMode = ENABLE;
复制代码
7 D2 C/ E' P/ J, a& h) j如果只是用了一个通道的话,DISABLE就可以了,如果使用了多个通道的话,则必须将其设置为ENABLE。
' B5 X0 j. H! `5 r) @% A0 O
* X' ]+ w: {% f(3) 第三个参数是ADC_ContinuousConvMode,这里设置为ENABLE,即连续转换。: p; J$ w" U s
如果设置为DISABLE,则是单次转换。两者的区别在于连续转换直到所有的数据转换完成后才停止转换,而单次转换则只转换一次数据就停止,要再次触发转换才可以。所以如果需要一次性采集1024个数据或者更多,则采用连续转换。; P) Y; m" {/ ]: Q0 Q" F( K l
% Z8 T+ @4 T4 U7 I5 n* B2 b0 ?8 _
(4) 第四个参数是ADC_ExternalTrigConv,即选择外部触发模式。这里只讲三种:4 [! l! `1 d' Z5 j4 {9 i, l2 t
/ I8 D1 R N2 W# W; B1、第一种是最简单的软件触发,参数一般为ADC_ExternalTrigConv_None(注意STM32F2XX系列这个有点蹊跷,后面会讲这个)。设置好后还要记得调用库函数:
Q$ r+ f2 ~- |8 n9 D- ADC_SoftwareStartConvCmd(ADC1, ENABLE);
复制代码- void ADC_SoftwareStartConv(ADC_TypeDef* ADCx)
+ V M% {( V& i, ^) z/ Q& U" t - {1 e) }6 f- d" x I0 f/ G! Z
- /* Check the parameters */- Z8 M9 [5 u7 S* E
- assert_param(IS_ADC_ALL_PERIPH(ADCx));9 q! \' L* x% x$ `
+ b( g. x2 k( l. F `. J- /* Enable the selected ADC conversion for regular group */& X0 z; F% J, \' X2 J
- ADCx->CR2 |= (uint32_t)ADC_CR2_SWSTART;
. Q, v1 D; H; Q6 W' ?; R r0 \ - }
复制代码- #define ADC_CR2_SWSTART ((uint32_t)0x40000000)
1 ~$ I2 \% N$ x4 N. z) O - /*!<Start Conversion of regular channels */
复制代码
' f8 G2 V x0 G9 T' w: ?6 zADC_SoftwareStartConv函数里直接置位CR2的ADC_CR2_SWSTART位,这样触发就启动了。( j* l4 }) U! I7 @
7 G, S8 b9 d( R1 ^* a. R: O9 N N% v
2、第二种是定时器通道输出触发。共有这几种:ADC_ExternalTrigConv_T1_CC1、ADC_ExternalTrigConv_T1_CC2、ADC_ExternalTrigConv_T2_CC2、
" {8 W8 k3 r( M
8 K+ c2 Z! D3 B, d( \ADC_ExternalTrigConv_T3_T以及ADC_ExternalTrigConv_T4_CC4。定时器输出触发比较麻烦,还需要设置相应的定时器。以
# c8 D/ @* c% E4 f- Y+ V! q6 j' z0 C$ ?+ W1 e# C1 d% z- ^
ADC_ExternalTrigConv_T2_CC2触发为例设置相应的定时器:1 e; R" `# z' ~& c3 B
8 f6 i, g8 D! B# |. X' E" F
- void TIM2_Configuration(void)
: ^% D5 ?, g% e- x$ F5 _6 E - 4 a3 g( j2 R5 ?& Z/ Z& _( Y
- {
/ A, M$ D. m7 i' Y- n6 Q1 J - 2 g+ c5 P$ O. I1 N
- TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;5 S* Q4 m" @# _3 B! M
- 9 o! ^' W6 S; Z+ _5 m7 L
- TIM_OCInitTypeDef TIM_OCInitStructure;
6 t- s+ a/ x& y4 j- Y/ M0 U7 a - # w& ]8 `) y+ T# J2 H9 \
- TIM_TimeBaseStructure.TIM_Prescaler = 4;4 u$ E- g0 z2 @+ N
" b o6 ? A7 `( H% {0 D3 B- TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
8 A( k& s# d Y+ D _3 W& o# W
+ t% f" l8 J' t3 y) n- TIM_TimeBaseStructure.TIM_Period = 0XFF;7 g4 Q: D, f! o* B1 n5 o& Q
- 5 L% t& @1 R1 A5 a3 A3 t. G' p/ K
- TIM_TimeBaseStructure.TIM_ClockDivision = 0;* H; Z) r+ v3 Z H
- D: Z4 x' S' [3 h( Q# H- TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;- E7 `: C- n8 O8 k: {
6 z1 Z' u0 D" a- TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);7 K% l$ ]. Z' ~3 x% D
$ `. v# C+ D& J# y5 o' N
7 ^ P# S4 H/ @# L- w1 h- TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
7 {# N+ a, _0 F - , X# ^2 l( \4 L9 s+ T3 n* h$ H& P
- TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;0 o- D' U' Q( F! R
' ]- c! Z# M) f$ O) V7 t( g, P- TIM_OCInitStructure.TIM_Pulse = 0X7F; V! n% T% {( J
- ) e4 ^' g: N& z: _3 K/ f$ V: h
- TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;
+ l- t1 t+ V% f
8 W% p$ U. [$ g/ U" w! ]) Z* X- TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set; O6 \' g. M# }! l, g5 A
- 5 ?3 m. c' T( g/ I
- //配置CC2的属性。若CC3作为ADC的触发源,则应改为TIM_OC3Init(TIM2, &TIM_OCInitStructure);9 [2 I- H5 y8 ]
- % e& s4 p6 ?) d5 h
- TIM_OC2Init(TIM2, &TIM_OCInitStructure);2 y. y+ U2 ?; e
5 s. Q8 ^6 @" e9 k8 P) t. {2 T- TIM_Cmd(TIM2, ENABLE);. {+ V) T! k' ^- g* b
- TIM_CtrlPWMOutputs(TIM2, ENABLE);: N1 G: C* D1 x6 M
- }
复制代码 ; }* ?! |" _# C* [
! V2 |! f0 \/ }# @& h$ T
这样设置之后就可以用定时器2的输出触发了,至于触发的周期,设置TIM2的时间即可。这里不再赘述。. Q: h' }; B$ h5 r) E, g
8 z4 U) Y+ B5 P( ^& l1 f1 `9 a
3、第三种是外部引脚触发,对于规则通道,选择EXTI线11和TIM8_TRGO作为外部触发事件;而注入通道组则选择EXTI线15和TIM8_CC4作为外部触发事件。: v+ i1 m. [, x/ ]" H
5 `0 O! h; p( ?! C3 ?(5) 第五个参数是ADC_DataAlign,这里设置为ADC_DataAlign_Right右对齐方式。建议采用右对齐方式,因为这样处理数据会比较方便。当然如果要从高位开始传输数据,那么采用左对齐优势就明显了。
. N3 N$ r% W- @, ?2 W# y/ w8 i; r9 s4 |
(6) 第六个参数是ADC_NbrOfChannel,顾名思义:通道的数量。要是到多个通道采集数据的话就得设置一下这个参数。此外在规则通道组的配置函数中也许将各个通道的顺序定义一下,如:
, A# `- H5 q P4 i4 F: m- ADC_RegularChannelConfig(ADC1,ADC_Channel_13,1,ADC_SampleTime_13Cycles5); Q* X3 ~$ K# y% K- p$ E
- 4 h2 N8 w$ F( N
- ADC_RegularChannelConfig(ADC1,ADC_Channel_14,2,ADC_SampleTime_13Cycles5);
复制代码 8 ~) ]' V3 k) I: M& O9 t
: z( c* a+ w5 T0 i 多通道数据传输时有一点还要注意:若一个数组为ADC_ValueTab[4],且设置了两个通道:通道1和通道2,则转换结束后,ADC_ValueTab[0]和ADC_ValueTab[2]存储的是通道1的数据,而ADC_ValueTab[1]和ADC_ValueTab[3]存储的是通道2的数据。如果数组容量大则依次类推。+ J* O+ S; w& @! y4 t
5 `* d6 p& D0 o
补充一点:在使用DMA传输数据的时候,需要设置外设地址和存储器地址,外设地址当然就是ADC的地址了,而存储器的地址如果使用8位数据的话,存储器必须定义为8位缓冲区;如果使用16位数据格式的话,存储器则为16位缓冲器,不可定义为32位或更多,否则,数据将出错。
7 _1 C- z; |4 a$ P F. ]
2 _7 R% \$ n$ R7 q: J: Q问题的解决方法
. Z0 {* f- U# h& w* E: F8 H 上面分析了adc结构体的参数,下面再来单独看看ADC_ExternalTrigConv这一项。- p8 U, J/ D: K6 M P$ a
在stm32f2xx_adc.h文件中有这个成员的参数定义,发现里面并没有ADC_ExternalTrigConv_None这个常见的定义。3 Q. [$ Y" d- A; E" q
) `5 m1 f' i$ I) M0 i9 ~
- /** @defgroup ADC_extrenal_trigger_sources_for_regular_channels_conversion ( r! z- X% z- c) f9 O
- * @{
, g9 q3 ^7 [+ {. r ~ - */
3 b' y; |- i; @7 T# } - #define ADC_ExternalTrigConv_T1_CC1 ((uint32_t)0x00000000)
5 |3 G0 n! y: b! \3 ] - #define ADC_ExternalTrigConv_T1_CC2 ((uint32_t)0x01000000)$ F+ v: B; c! s' m+ x3 E0 H, T' V9 n& Q
- #define ADC_ExternalTrigConv_T1_CC3 ((uint32_t)0x02000000)
( {6 [$ o6 w+ e$ e1 `* M/ D4 I - #define ADC_ExternalTrigConv_T2_CC2 ((uint32_t)0x03000000)+ ~" Y2 j4 ~- n- {
- #define ADC_ExternalTrigConv_T2_CC3 ((uint32_t)0x04000000)
% C2 M/ p8 R; d% }" i- \, ]2 o - #define ADC_ExternalTrigConv_T2_CC4 ((uint32_t)0x05000000)
3 |8 c0 q5 Y W) U4 d - #define ADC_ExternalTrigConv_T2_TRGO ((uint32_t)0x06000000)0 I2 l% Q2 a4 F4 @
- #define ADC_ExternalTrigConv_T3_CC1 ((uint32_t)0x07000000)+ @ H3 M1 i' Y! f% B
- #define ADC_ExternalTrigConv_T3_TRGO ((uint32_t)0x08000000)% z. \3 k* o2 B& z/ D
- #define ADC_ExternalTrigConv_T4_CC4 ((uint32_t)0x09000000)
& d" T/ {& s, M' K - #define ADC_ExternalTrigConv_T5_CC1 ((uint32_t)0x0A000000)
" v; [" l$ d) K: F8 S - #define ADC_ExternalTrigConv_T5_CC2 ((uint32_t)0x0B000000)
6 N2 u, p$ e3 K" o0 }' a - #define ADC_ExternalTrigConv_T5_CC3 ((uint32_t)0x0C000000): A3 j3 D% V: G4 @8 Q0 m, g3 @3 I
- #define ADC_ExternalTrigConv_T8_CC1 ((uint32_t)0x0D000000)! h" H& ^; L7 \' h/ Z% R. |) Q: [$ N6 j6 M
- #define ADC_ExternalTrigConv_T8_TRGO ((uint32_t)0x0E000000)
/ o, y U- U3 S$ ^! i( s+ K: b - #define ADC_ExternalTrigConv_Ext_IT11 ((uint32_t)0x0F000000)
复制代码 % f: p, J! K: F. j U) r) k( L2 M
再来看看stm32f10x_adc.h文件中的ADC_ExternalTrigConv的参数定义:
+ F% |4 H( Y, |- /** @defgroup ADC_external_trigger_sources_for_regular_channels_conversion
) V! m: c( q8 o. |0 f7 Z - * @{
9 g" m2 c( p7 b" V - */
% W+ r# @) [: K# g7 O3 a
9 W1 w7 r5 Z, D r0 N y7 M4 ]4 L- #define ADC_ExternalTrigConv_T1_CC1 ((uint32_t)0x00000000) /*!< For ADC1 and ADC2 */: S: F; J' F: q! t
- #define ADC_ExternalTrigConv_T1_CC2 ((uint32_t)0x00020000) /*!< For ADC1 and ADC2 */+ S, u8 h( P. D
- #define ADC_ExternalTrigConv_T2_CC2 ((uint32_t)0x00060000) /*!< For ADC1 and ADC2 */
& E% n- c% f1 G B: }+ T- v - #define ADC_ExternalTrigConv_T3_TRGO ((uint32_t)0x00080000) /*!< For ADC1 and ADC2 */
/ L. ^6 i5 ]# j - #define ADC_ExternalTrigConv_T4_CC4 ((uint32_t)0x000A0000) /*!< For ADC1 and ADC2 */4 R1 V5 F- u& R4 H# ~
- #define ADC_ExternalTrigConv_Ext_IT11_TIM8_TRGO ((uint32_t)0x000C0000) /*!< For ADC1 and ADC2 */
9 E) `1 Q% A2 a; G* Y - ' X7 r; _# N% |
- #define ADC_ExternalTrigConv_T1_CC3 ((uint32_t)0x00040000) /*!< For ADC1, ADC2 and ADC3 */
5 u2 }$ F- N3 _4 _0 G$ p$ @ - #define ADC_ExternalTrigConv_None ((uint32_t)0x000E0000) /*!< For ADC1, ADC2 and ADC3 */ //f2xx系列并没有这个定义
' ~* A, N/ K) p2 o& r
) E2 i; Z/ z+ ~6 P$ K9 Z- #define ADC_ExternalTrigConv_T3_CC1 ((uint32_t)0x00000000) /*!< For ADC3 only */& h+ V9 u6 U' G2 |; |
- #define ADC_ExternalTrigConv_T2_CC3 ((uint32_t)0x00020000) /*!< For ADC3 only */% I8 o4 C% h1 X" D. l! R) J
- #define ADC_ExternalTrigConv_T8_CC1 ((uint32_t)0x00060000) /*!< For ADC3 only */8 ^0 D9 j7 v/ a/ ~* c
- #define ADC_ExternalTrigConv_T8_TRGO ((uint32_t)0x00080000) /*!< For ADC3 only */" ~* W: @. ?: G; l) ^% G
- #define ADC_ExternalTrigConv_T5_CC1 ((uint32_t)0x000A0000) /*!< For ADC3 only */6 R3 R! j/ G" a
- #define ADC_ExternalTrigConv_T5_CC3 ((uint32_t)0x000C0000) /*!< For ADC3 only */
复制代码
- t- p) f' ^6 X, J( S/ i8 G4 | 对比发现stm32f2xx系列并没有ADC_ExternalTrigConv_None这个定义,很是奇怪,现在还不明白ST的工程师为什么做这个变动。
|4 M* q4 b0 [7 Z" S4 ?/ k0 L% j 那么问题怎么解决呢?& Y+ a0 G6 F) n& L5 [4 s
一种是进行adc结构体的初始化操作,在配置之前恢复默认值。即调用ADC_StructInit(&ADC_InitStructure);修改如下:- ADC_StructInit(&ADC_InitStructure);//新增加的
% I. ~" a5 T& @1 s- ~- V' A& V - ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;" J" F: G4 O/ ?
- ADC_InitStructure.ADC_ScanConvMode = ENABLE;$ W# y9 }8 B2 H3 R. H; |
- ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
* J' `% g" I: T$ R/ K. K9 g - ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;9 A( [6 j- b7 L3 Q7 M" t3 ?& m* [. l
- ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;) a4 A' ]! m4 S7 p; d; Q& a1 _, K9 u
- ADC_InitStructure.ADC_NbrOfConversion = 9;
9 e1 Q% ^( K3 [1 d) N - ADC_Init(ADC1, &ADC_InitStructure);
复制代码 调用ADC_StructInit(&ADC_InitStructure)语句,ADC_ExternalTrigConv会恢复默认值0。如下:8 |1 g W5 S1 y4 U" d9 F
+ ?: U$ N1 d( K" A$ Z. T& m/ z. t# ?
1 J2 }1 t9 d z7 }4 W+ o* ~# B 另一种方法是直接配置该参数为0,如下: B$ T7 e, t* u. c4 Y* _
- ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
8 E, A6 N( `( p* f" q - ADC_InitStructure.ADC_ScanConvMode = ENABLE;
5 n0 z' P+ M1 h( Y0 o; Q# m6 ` - ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
1 \; q l" V6 \9 P" E - ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
! E( o# O ^- \! |9 \) N - ADC_InitStructure.ADC_ExternalTrigConv= 0;//新增加的
( ~! }+ m5 b- `* \" ~ K - ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;$ r6 Q+ l4 C2 v- w: P4 b+ g3 d; G
- ADC_InitStructure.ADC_NbrOfConversion = 9;1 V- b. f) ?# m9 k
- ADC_Init(ADC1, &ADC_InitStructure);
复制代码 " m ~) c4 T- g$ M! N* A+ }
这两种方法都可以解决adc采样对齐方式异常问题。 J) D0 I% h6 f$ c- K( S+ f
但是ADC_ExternalTrigConv= 0在stm32f2xx_adc.h中其实是对应ADC_ExternalTrigConv_T1_CC1的。2 O+ r5 q, u E E- _ z
& O/ i' @8 H2 x) F/ Y9 e
9 V5 S9 h8 @* o" Q0 U6 e* P, T4 z" [
也就是说调用软件触发函数ADC_SoftwareStartConv函数里直接置位CR2的ADC_CR2_SWSTART位也可以触发定时器触发方式的adc通道。1 k3 H9 |; V4 w# k
8 z7 e/ M/ [0 F6 |
( Z( @ D* [3 x2 A( {$ x5 k, k! {+ E% \( d, G! ~7 p3 j9 y
|