你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【经验分享】STM32F2XX——ADC多通道DMA采集时AD值大于4095的问题解决方法

[复制链接]
STMCU小助手 发布时间:2021-12-2 16:03
前言, F1 z7 W# m: B5 M0 j; F: F
  最近在调试STM32F2XX系列ADC多通道DMA采集时,发现采集的AD值大于4095,有的65000多了,这是什么节奏?adc不是12位吗,最大才0xfff,即4095,怎么会出现这种情况呢?难到是adc数据对齐方式出现问题了,adc的对齐明明设置的是右对齐啊,神马情况?
1 X6 M1 X% j$ O) Y- U) ~4 W7 ]
8 n" I6 s; `5 d! jADC结构体参数分析
6 z" a2 G+ c/ p6 f2 ^
  百思不得adc之姐,只能keil单步调试,一步一步查看adc结构体的参数。我使用的是adc dma方式采集,共9个通道。初始化程序如下:( C( z( p" q( [1 J
  1. void ADC_DMA_Config(void)
    * I$ H. k  a6 h9 _, B
  2. {2 i) P6 Q8 y* X
  3.     ADC_InitTypeDef       ADC_InitStructure;7 \6 J7 v9 h- B; B& n- M
  4.     ADC_CommonInitTypeDef ADC_CommonInitStructure;3 @; }( {4 R4 K! N
  5.     DMA_InitTypeDef       DMA_InitStructure;- U6 h* G6 t4 J
  6.     GPIO_InitTypeDef      GPIO_InitStructure;
    ( ?( q. k% E, O, H# n$ E

  7. ( [# Q6 u% T; \
  8.     RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2 | RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOC, ENABLE);4 o9 s: d0 Y6 D! U* }
  9.     RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
    ) p# f6 U/ o: S: Z' J5 l

  10. 0 W" M2 P  l7 \$ V% H
  11.     DMA_InitStructure.DMA_Channel = DMA_Channel_0;  ' D. o- ?* c$ P3 k, g7 Z
  12.     DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&ADC1->DR;
    ) }' P* }; t" `1 q, S5 H! P
  13.     DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&ADC_ConvertedValue;  - C" ?/ ?% J$ w* f0 j7 Q
  14.     DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
    7 X, u. Q9 E  `# Y( k  R
  15.     DMA_InitStructure.DMA_BufferSize = Sample_Num*Channel_Num;         3 k% i6 M6 ]2 e* S2 n( A" Y( j6 m1 u4 f
  16.     DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;! _  ~: q, v& h
  17.     DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
    8 G9 k% o* K, G' i! Z% T$ v
  18.     DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
    ' e; }) m" q% N. W9 l( n
  19.     DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;( @5 r$ E- G8 x
  20.     DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;2 u% ~( c+ f0 K& D- q) \7 ?
  21.     DMA_InitStructure.DMA_Priority = DMA_Priority_High;
    $ l. ~2 }4 O- W
  22.     DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;         1 K+ [# c. @# |. r% P5 ~
  23.     DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;7 A6 [6 D0 a4 P( s3 ^
  24.     DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
    7 D2 C, d" t: w2 N0 e
  25.     DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;1 X+ W9 C" U  \. i* G
  26.     DMA_Init(DMA2_Stream0, &DMA_InitStructure);$ y) J7 x: t+ `* Y# V0 M" |# n
  27.     DMA_Cmd(DMA2_Stream0, ENABLE);! C' R& B& X; {
  28. " B1 |! n8 J* }

  29. 3 A+ a. y3 @: `
  30.     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 |GPIO_Pin_2 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_7;, ~/ Q+ F' E1 R
  31.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;3 x- a0 V  l* ^. F* p$ P* ]1 ?1 V
  32.     GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;3 Y8 I' R, y7 i! c( ~
  33.     GPIO_Init(GPIOA, &GPIO_InitStructure);
    - \$ X; H/ p/ I6 K0 v$ }/ u

  34. ( B- r- M; b6 F
  35.     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_3 | GPIO_Pin_5;4 ~) f0 X# V+ z/ e3 {; d
  36.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;4 Q- I3 p/ u2 g  B# ]$ s
  37.     GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;5 ?6 e7 h3 i: R, t+ m
  38.     GPIO_Init(GPIOC, &GPIO_InitStructure);
    . f6 Q3 I0 t1 _
  39. ( ]5 i' ~& C! J: i( ~6 Q9 }
  40.     /* ADC Common Init **********************************************************/
    : l* N& Z% u4 b: c
  41.     ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;5 G  q, K8 F7 G8 v3 T/ b* D( `0 S
  42.     ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div2;* U' u, h8 a, D& K
  43.     ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;
    / y. h5 i( r' W' d- r- S1 Z
  44.     ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;
    ) J! A; j. |6 m
  45.     ADC_CommonInit(&ADC_CommonInitStructure);0 B( P) b1 M! g2 J: h& k0 J/ T

  46. ) [7 o6 A+ F1 K: b' N6 h, ?
  47.     ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;+ H6 C- n1 l( d, A, V
  48.     ADC_InitStructure.ADC_ScanConvMode = ENABLE;
    ; o7 [7 Y) w( N  d) z
  49.     ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;! K3 Y! L% V$ f
  50.     ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
    0 U, f5 M% }3 Q. t
  51.     ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
    ! G, s! q1 n! [0 o  _
  52.     ADC_InitStructure.ADC_NbrOfConversion = 9;
    4 M+ `8 ~) R6 Z% a: l
  53.     ADC_Init(ADC1, &ADC_InitStructure);6 Q! q) z( A+ O8 {/ |; D3 M. h

  54. 8 n7 W  v& ]( s* G5 r+ D

  55. & X# n$ @5 \% J3 c& g# U7 t$ B
  56.     ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_3Cycles);: v( N% t" Y9 w5 t& A2 ^, z
  57.     ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 2, ADC_SampleTime_3Cycles);6 \+ w9 @7 [: t' E; D  G6 l
  58.     ADC_RegularChannelConfig(ADC1, ADC_Channel_2, 3, ADC_SampleTime_3Cycles);
    ) B+ i# H6 A4 Z
  59.     ADC_RegularChannelConfig(ADC1, ADC_Channel_4, 4, ADC_SampleTime_3Cycles);
    : ]% ?+ a1 p' |9 I+ L* X+ j% a
  60.     ADC_RegularChannelConfig(ADC1, ADC_Channel_5, 5, ADC_SampleTime_3Cycles);
    / n9 ~- }6 [" h; @/ ~. V
  61.     ADC_RegularChannelConfig(ADC1, ADC_Channel_7, 6, ADC_SampleTime_3Cycles);
    3 P% v- o' ]  c/ c* x
  62.     ADC_RegularChannelConfig(ADC1, ADC_Channel_11, 7, ADC_SampleTime_3Cycles);4 b" H6 @4 N# _& y) x/ a
  63.     ADC_RegularChannelConfig(ADC1, ADC_Channel_13, 8, ADC_SampleTime_3Cycles);
    ( V% x# |" V" P' k( K# d, z! w0 H
  64.     ADC_RegularChannelConfig(ADC1, ADC_Channel_15, 9, ADC_SampleTime_3Cycles);
    / r' _! Y2 a4 x  I7 t

  65. ' o+ K4 _+ c+ K  {+ p- B
  66.     ADC_DMARequestAfterLastTransferCmd(ADC1, ENABLE);
    / O" a1 r6 G3 w( [  o% j; k
  67.     ADC_DMACmd(ADC1, ENABLE);: T3 a% u; t/ M- {" @
  68.     ADC_Cmd(ADC1, ENABLE);
    0 Z' V* k5 c' Y) b! h* x
  69. 0 h! F% U. G! }$ O7 z
  70. }
复制代码

3 H$ g+ t" T1 c1 w  U( q, J- |9 C  其中涉及adc的初始化结构体代码部分如下:% z; i# n$ O2 B6 j! E' M
2 W: `$ o: Q% L  u
    ADC_InitTypeDef       ADC_InitStructure;/ o' p% |6 p+ z; B/ C+ Y
  1.     ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
    1 h2 I: C  m$ f
  2.     ADC_InitStructure.ADC_ScanConvMode = ENABLE;2 C: Y5 f. R2 t1 v/ m1 Z
  3.     ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
    9 ]+ ^# c, o% `2 N
  4.     ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;6 ?, V( o6 d6 i1 k
  5.     ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
    5 L. P$ y: M1 i- E0 }! T5 a* b
  6.     ADC_InitStructure.ADC_NbrOfConversion = 9;
    - C+ O2 F6 U# j. \
  7.     ADC_Init(ADC1, &ADC_InitStructure);
复制代码
  一步一步调式发现结构体有一项ADC_ExternalTrigConv是0x08002d54,这一项并没有初始化对其赋值,忘记给结构体的这一项赋值了。最后这个值通过ADC_Init函数赋值给CR2的时候,第11位(也就是数据对其位)是1了,左对齐了!!!!!* G  j4 F/ R$ N" s5 x# j& `
; `: c" T) {8 v/ [
20180823193630758.png
0 X/ n  z! Q+ w: g( u7 H" }. m

4 Z5 e9 n; y% `% h6 j, G4 q" y! D  下面来重点分析下adc初始化结构体中的各项参数的意义:
! X. z9 T; d/ {9 Y9 P  对于STM32,在使用ADC的时候需要配置几个参数。
( p! d2 k$ d3 i(1) 第一个参数是ADC_Mode,这里设置为独立模式:  M2 C" Y! |5 s

' q6 r3 ^4 t3 O
  1. ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
复制代码

, x1 V7 h1 v/ S: U9 ^: `7 t在这个模式下,双ADC不能同步,每个ADC接口独立工作。所以如果不需要ADC同步或者只是用了一个ADC的时候,就应该设成独立模式了。& l# d2 K4 b8 l, S

( L7 B7 Y& Y/ E: k: |3 j  {6 ](2) 第二个参数是ADC_ScanConvMode,这里设置为DISABLE。
! K% q# g; ~/ W6 {
  1. ADC_InitStructure.ADC_ScanConvMode = ENABLE;
复制代码
; w2 `# T" D" h) e
如果只是用了一个通道的话,DISABLE就可以了,如果使用了多个通道的话,则必须将其设置为ENABLE。& J" U1 w+ f0 G" U/ i# G; t# x1 [

3 Q# K6 m* j* R0 A" H$ A% Y(3) 第三个参数是ADC_ContinuousConvMode,这里设置为ENABLE,即连续转换。
) b4 j9 U4 E8 V4 T如果设置为DISABLE,则是单次转换。两者的区别在于连续转换直到所有的数据转换完成后才停止转换,而单次转换则只转换一次数据就停止,要再次触发转换才可以。所以如果需要一次性采集1024个数据或者更多,则采用连续转换。) a) l4 y: ^" X7 c

: f! X' P1 r" J& B" A* T3 A/ l(4) 第四个参数是ADC_ExternalTrigConv,即选择外部触发模式。这里只讲三种:
( C" Z) I4 Q  P  S- H% b$ ^9 R& K* r3 ?8 q7 i
1、第一种是最简单的软件触发,参数一般为ADC_ExternalTrigConv_None(注意STM32F2XX系列这个有点蹊跷,后面会讲这个)。设置好后还要记得调用库函数:
/ R1 S% Z# O6 ^+ J, Y8 V
  1. ADC_SoftwareStartConvCmd(ADC1, ENABLE);
复制代码
  1. void ADC_SoftwareStartConv(ADC_TypeDef* ADCx)
    $ C  p# ^+ g0 X5 |9 L* X- V/ ?( d
  2. {4 C$ L% o. ?. |% J
  3.   /* Check the parameters */
    2 `0 ^0 z- J3 T& S; n& l' E
  4.   assert_param(IS_ADC_ALL_PERIPH(ADCx));
    4 C, X, J' Z& C

  5. ! c: ?6 v6 z. a7 d! p
  6.   /* Enable the selected ADC conversion for regular group */& i* O7 M1 l" x  i% j
  7.   ADCx->CR2 |= (uint32_t)ADC_CR2_SWSTART;
    2 O0 j6 ^7 W) \8 _  R( @
  8. }
复制代码
  1. #define  ADC_CR2_SWSTART                     ((uint32_t)0x40000000)      / a; t" X; l; T* o) c
  2. /*!<Start Conversion of regular channels */
复制代码
$ H" E+ |  i1 E; j
ADC_SoftwareStartConv函数里直接置位CR2的ADC_CR2_SWSTART位,这样触发就启动了。
6 _2 a1 [2 A% q' v
& X) r% \5 q5 k  w; m1 r2、第二种是定时器通道输出触发。共有这几种:ADC_ExternalTrigConv_T1_CC1、ADC_ExternalTrigConv_T1_CC2、ADC_ExternalTrigConv_T2_CC2、
) S. \5 W9 b5 N: i5 l6 ^
0 t7 v$ @8 O' w5 y. oADC_ExternalTrigConv_T3_T以及ADC_ExternalTrigConv_T4_CC4。定时器输出触发比较麻烦,还需要设置相应的定时器。以
$ H' ~: @8 l+ ?$ @# G, h. S& v2 T- U7 X! \- N$ E" M
ADC_ExternalTrigConv_T2_CC2触发为例设置相应的定时器:- X/ D! r5 P* A4 j8 N
9 E& A! h" d0 i
  1. void TIM2_Configuration(void)0 i0 H$ g3 J- L  M
  2. : U( `/ K9 h, ^) K
  3. {
    " l0 s, Z( Z, L9 A3 P$ x

  4. ! m. R3 g/ p# |' F1 p% i
  5. TIM_TimeBaseInitTypeDef   TIM_TimeBaseStructure;
    & d# H9 I3 s2 H2 |$ @$ W+ l. M- s  i

  6. 1 C# U" E% F5 |! q9 O; x. z; X# U
  7. TIM_OCInitTypeDef         TIM_OCInitStructure;, j( f  s4 H! J- [* a
  8. : V. p. O7 z. c. e# p9 C
  9. TIM_TimeBaseStructure.TIM_Prescaler = 4;
    , [& p: i& K% ?' p! I
  10. 9 C) E# j( }# Q
  11. TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;% v* W" Z  W& T8 ]' Y
  12. $ l9 H# `/ ^1 y: x0 H; L
  13. TIM_TimeBaseStructure.TIM_Period = 0XFF;
    & g; l4 A; Q( G% _/ H4 v, H; L& ?8 b

  14. ! q# i' X4 @9 y( L: z6 ?( Y
  15. TIM_TimeBaseStructure.TIM_ClockDivision = 0;
    3 _( f/ @1 p: D

  16. - ]/ T9 s; g; }# r" g: P. A
  17. TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
    ' e0 B. P0 L7 k* c; ~
  18. ( V5 I, w: n1 e
  19. TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
    ( g, m- q: P( S8 B! ?  w! e, R% s
  20. + [. G# t3 J- I6 w( D6 J
  21. 0 b5 R9 d; T2 Q* r8 D+ g
  22. TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
    ! M9 E+ x3 o7 r) N6 P' o- v. e
  23. 8 ]' U( O4 ?) C/ @# Y
  24. TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;2 F( @6 ?1 u* l0 [% E
  25. ; w5 i$ a2 T% K
  26. TIM_OCInitStructure.TIM_Pulse = 0X7F;
    ( B( u# f0 n2 H0 N; r

  27. $ z. ~' e4 u8 T: e' z/ t0 _0 z
  28. TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;; g+ O0 z& T! W) x* K" a
  29. * c! I8 x8 s% r, @6 W1 M
  30. TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;        6 v, B, O* ]% x: `. E" _# s$ Y
  31. 3 I4 d# k! D6 H, t' b
  32. //配置CC2的属性。若CC3作为ADC的触发源,则应改为TIM_OC3Init(TIM2, &TIM_OCInitStructure);7 f/ A  \5 L" X# g* k& M" ]- f

  33. # }9 X4 v: `" V  L
  34. TIM_OC2Init(TIM2, &TIM_OCInitStructure);
    ! q* N9 l- H4 X2 P( z

  35. $ C# s! S, V0 o5 H, n0 t) G* `. V
  36. TIM_Cmd(TIM2, ENABLE);
    - s) q5 p. z9 Z6 P
  37. TIM_CtrlPWMOutputs(TIM2, ENABLE);% y# B8 d! a; e" u1 F4 n) [
  38. }
复制代码

3 Q8 B! }. y+ z
" N# Y& n6 y6 g. Q- h% r3 [这样设置之后就可以用定时器2的输出触发了,至于触发的周期,设置TIM2的时间即可。这里不再赘述。
5 M$ b! a" ?! j: u# y! t) D
+ l8 u9 Z+ _9 G2 `. j3、第三种是外部引脚触发,对于规则通道,选择EXTI线11和TIM8_TRGO作为外部触发事件;而注入通道组则选择EXTI线15和TIM8_CC4作为外部触发事件。
/ Q, ^& T7 i$ P: B  b0 f
1 D3 W3 C/ L1 O( E7 J( H(5) 第五个参数是ADC_DataAlign,这里设置为ADC_DataAlign_Right右对齐方式。建议采用右对齐方式,因为这样处理数据会比较方便。当然如果要从高位开始传输数据,那么采用左对齐优势就明显了。
. G2 p2 h9 {) T- d; I2 S* M" g- w  Y' i" t  h4 `2 c6 |
(6) 第六个参数是ADC_NbrOfChannel,顾名思义:通道的数量。要是到多个通道采集数据的话就得设置一下这个参数。此外在规则通道组的配置函数中也许将各个通道的顺序定义一下,如:4 O7 @9 h# D- W# z  c
  1.       ADC_RegularChannelConfig(ADC1,ADC_Channel_13,1,ADC_SampleTime_13Cycles5);
    , m+ n& @* e* \$ a/ c& z, c6 W
  2. 7 w: Y& v, V' s+ l3 b
  3.       ADC_RegularChannelConfig(ADC1,ADC_Channel_14,2,ADC_SampleTime_13Cycles5);
复制代码
: J# K& ?- F- G! @* {4 j+ L

  Y* V/ r& C1 w  多通道数据传输时有一点还要注意:若一个数组为ADC_ValueTab[4],且设置了两个通道:通道1和通道2,则转换结束后,ADC_ValueTab[0]和ADC_ValueTab[2]存储的是通道1的数据,而ADC_ValueTab[1]和ADC_ValueTab[3]存储的是通道2的数据。如果数组容量大则依次类推。
7 N+ Z0 B: f+ P$ ]
5 D/ }9 A  g- i8 Q! I: k4 C$ p1 x  补充一点:在使用DMA传输数据的时候,需要设置外设地址和存储器地址,外设地址当然就是ADC的地址了,而存储器的地址如果使用8位数据的话,存储器必须定义为8位缓冲区;如果使用16位数据格式的话,存储器则为16位缓冲器,不可定义为32位或更多,否则,数据将出错。" S) m6 F( Z: |0 @# m5 e
% n& L# j4 i# h: W
问题的解决方法
7 G$ @+ e& T2 P, g6 w
  上面分析了adc结构体的参数,下面再来单独看看ADC_ExternalTrigConv这一项。
, |) P4 T" Z8 ?% J  在stm32f2xx_adc.h文件中有这个成员的参数定义,发现里面并没有ADC_ExternalTrigConv_None这个常见的定义。
* W' O' j8 {& N" N# M+ m. C* X/ I$ w1 |, w0 u( L
  1. /** @defgroup ADC_extrenal_trigger_sources_for_regular_channels_conversion : W( G, F$ C3 D7 O. k- f% Y
  2.   * @{
    ' ^- i/ z( V0 o4 _% r& y
  3.   */
    3 }5 Q) j+ i; B9 O8 C% P+ x% l1 Z( y
  4. #define ADC_ExternalTrigConv_T1_CC1                ((uint32_t)0x00000000)5 e! r2 h' G  I3 i
  5. #define ADC_ExternalTrigConv_T1_CC2                ((uint32_t)0x01000000)0 w, o/ d  M& d7 ~5 x
  6. #define ADC_ExternalTrigConv_T1_CC3                ((uint32_t)0x02000000)/ c. Z. F& X) j
  7. #define ADC_ExternalTrigConv_T2_CC2                ((uint32_t)0x03000000)& L0 H. z& K) N5 G$ C4 s$ T4 r
  8. #define ADC_ExternalTrigConv_T2_CC3                ((uint32_t)0x04000000)
      _+ \+ E( {: x! m7 ?8 t5 u" j
  9. #define ADC_ExternalTrigConv_T2_CC4                ((uint32_t)0x05000000)! P2 l1 g; Z6 t) ^! C; a# t& C( c
  10. #define ADC_ExternalTrigConv_T2_TRGO               ((uint32_t)0x06000000)/ P  k# `* W1 c
  11. #define ADC_ExternalTrigConv_T3_CC1                ((uint32_t)0x07000000)
    ( ^0 c* o7 E* h& k' n
  12. #define ADC_ExternalTrigConv_T3_TRGO               ((uint32_t)0x08000000)/ l0 v8 G0 m  v( x
  13. #define ADC_ExternalTrigConv_T4_CC4                ((uint32_t)0x09000000)# m+ I; u$ H& ]. p* I
  14. #define ADC_ExternalTrigConv_T5_CC1                ((uint32_t)0x0A000000)' m/ w+ M% R- H7 a6 m! I+ |
  15. #define ADC_ExternalTrigConv_T5_CC2                ((uint32_t)0x0B000000)
    2 m( d8 V# H. M- L/ o7 y
  16. #define ADC_ExternalTrigConv_T5_CC3                ((uint32_t)0x0C000000)) u: d4 c$ ?7 V' C
  17. #define ADC_ExternalTrigConv_T8_CC1                ((uint32_t)0x0D000000)/ x: {* x# C/ ^
  18. #define ADC_ExternalTrigConv_T8_TRGO               ((uint32_t)0x0E000000)( q' q# H, D- ?+ Y2 F* l
  19. #define ADC_ExternalTrigConv_Ext_IT11              ((uint32_t)0x0F000000)
复制代码
; e; G5 s) M. ~( V: G
  再来看看stm32f10x_adc.h文件中的ADC_ExternalTrigConv的参数定义:
, L: H% _. t3 x, x
  1. /** @defgroup ADC_external_trigger_sources_for_regular_channels_conversion & V- Y. l% F4 n( L0 m
  2.   * @{  ]# x! I% ^- S
  3.   */* z! ]& H6 S# Q, o, e
  4. $ {, k$ F- u, F. R
  5. #define ADC_ExternalTrigConv_T1_CC1                ((uint32_t)0x00000000) /*!< For ADC1 and ADC2 */- Z/ @9 _$ w& ]$ v
  6. #define ADC_ExternalTrigConv_T1_CC2                ((uint32_t)0x00020000) /*!< For ADC1 and ADC2 */; J8 R$ B8 m, c$ |2 v! b" R
  7. #define ADC_ExternalTrigConv_T2_CC2                ((uint32_t)0x00060000) /*!< For ADC1 and ADC2 */5 N- j' f' L; i; Q9 Q/ l- A& N$ a
  8. #define ADC_ExternalTrigConv_T3_TRGO               ((uint32_t)0x00080000) /*!< For ADC1 and ADC2 */
    . M& z6 O, Y4 D% [# Q
  9. #define ADC_ExternalTrigConv_T4_CC4                ((uint32_t)0x000A0000) /*!< For ADC1 and ADC2 */4 j' N- ^6 X" n' U4 e
  10. #define ADC_ExternalTrigConv_Ext_IT11_TIM8_TRGO    ((uint32_t)0x000C0000) /*!< For ADC1 and ADC2 */
    4 Z0 A6 N) }4 e! s
  11. / e8 B3 J' j8 d) s& A4 B
  12. #define ADC_ExternalTrigConv_T1_CC3                ((uint32_t)0x00040000) /*!< For ADC1, ADC2 and ADC3 */' ^1 Q+ u" k; s* N* G
  13. #define ADC_ExternalTrigConv_None                  ((uint32_t)0x000E0000) /*!< For ADC1, ADC2 and ADC3 */   //f2xx系列并没有这个定义
    " Q4 l/ I" O) @' P: Q
  14. ( P$ Z6 r, D1 ~0 T
  15. #define ADC_ExternalTrigConv_T3_CC1                ((uint32_t)0x00000000) /*!< For ADC3 only */
    5 a8 C) }9 M9 }8 \$ ~7 I" c
  16. #define ADC_ExternalTrigConv_T2_CC3                ((uint32_t)0x00020000) /*!< For ADC3 only */8 T/ s6 R0 Y$ ]% A& F
  17. #define ADC_ExternalTrigConv_T8_CC1                ((uint32_t)0x00060000) /*!< For ADC3 only */( Y+ k! j; `% \  M" `
  18. #define ADC_ExternalTrigConv_T8_TRGO               ((uint32_t)0x00080000) /*!< For ADC3 only */
    ! z$ ^4 l) a+ l' ?! P4 m
  19. #define ADC_ExternalTrigConv_T5_CC1                ((uint32_t)0x000A0000) /*!< For ADC3 only */
    3 e  D8 n' a, |! M
  20. #define ADC_ExternalTrigConv_T5_CC3                ((uint32_t)0x000C0000) /*!< For ADC3 only */
复制代码

1 ^1 H' z+ I0 v/ ?8 {; Y  对比发现stm32f2xx系列并没有ADC_ExternalTrigConv_None这个定义,很是奇怪,现在还不明白ST的工程师为什么做这个变动。
/ M8 |5 b# m5 L( L2 v5 G+ T8 V! z  那么问题怎么解决呢?: i  Q! [; q5 a- F( }! g" J" E
  一种是进行adc结构体的初始化操作,在配置之前恢复默认值。即调用ADC_StructInit(&ADC_InitStructure);修改如下:
  1.     ADC_StructInit(&ADC_InitStructure);//新增加的' ~: }; a- n, l9 q
  2.     ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
    # t" V: ~* d$ i$ c2 W
  3.     ADC_InitStructure.ADC_ScanConvMode = ENABLE;
    $ J3 m; A, l9 E3 O2 N6 T+ ]1 l
  4.     ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;- F" ?. ]# I0 U8 |# }
  5.     ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
    , X2 ?7 N- J6 b9 x9 z
  6.     ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
    1 P1 F5 J% Y% E* r  i
  7.     ADC_InitStructure.ADC_NbrOfConversion = 9;
    ' k0 }; ^  n% ^6 F4 _
  8.     ADC_Init(ADC1, &ADC_InitStructure);
复制代码
  调用ADC_StructInit(&ADC_InitStructure)语句,ADC_ExternalTrigConv会恢复默认值0。如下:
! V- f* l& J2 \6 @& ~) @5 F# \- Q4 P1 t
20180823201211262.png
9 \$ f) I3 F; R" G+ x& i2 e' ^

2 ?& I- @$ p3 {9 b, [  另一种方法是直接配置该参数为0,如下:
) o. `# s$ ~: x# ~% v
  1.     ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
    * U; M8 O* @8 @5 k* g' I  K" M8 _
  2.     ADC_InitStructure.ADC_ScanConvMode = ENABLE;! W2 n( E9 N& \+ q# C# E& L
  3.     ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
    ) A2 e1 Y$ T% U/ [
  4.     ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
    ( M, B5 C1 G9 V6 E
  5.     ADC_InitStructure.ADC_ExternalTrigConv= 0;//新增加的! C/ m5 ^+ x3 ?' j7 D* k0 [
  6.     ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;- l0 f' v7 z, Q3 t7 l$ }
  7.     ADC_InitStructure.ADC_NbrOfConversion = 9;
    ) j, p. g* f: S$ ^# o
  8.     ADC_Init(ADC1, &ADC_InitStructure);
复制代码

. f3 N! [* z) P  k( }1 ~, A0 R; K  这两种方法都可以解决adc采样对齐方式异常问题。
+ }# r1 i# A- y. u: c  但是ADC_ExternalTrigConv= 0在stm32f2xx_adc.h中其实是对应ADC_ExternalTrigConv_T1_CC1的。
* k# U& d4 ]4 Q! W  R, L
5 F+ r2 s1 d- c
20180823201832969.png

* e% B- d5 U# D% n6 C5 @
$ x8 N$ e7 ~  E6 w  也就是说调用软件触发函数ADC_SoftwareStartConv函数里直接置位CR2的ADC_CR2_SWSTART位也可以触发定时器触发方式的adc通道。
! U  a7 [0 |7 q* a% C! k! B, c* t9 x
+ g' e. w- ^3 {6 F: m* p* @3 o
. O" H4 M; T3 j# l1 Y+ n4 F# `6 }% }. m/ v: Q
收藏 评论0 发布时间:2021-12-2 16:03

举报

0个回答
关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32Cube扩展软件包
意法半导体边缘AI套件
ST - 理想汽车豪华SUV案例
ST意法半导体智能家居案例
STM32 ARM Cortex 32位微控制器
关注我们
st-img 微信公众号
st-img 手机版