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

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

[复制链接]
STMCU小助手 发布时间:2021-12-2 16:03
前言' d7 j$ A2 z7 X6 a# I0 T9 a
  最近在调试STM32F2XX系列ADC多通道DMA采集时,发现采集的AD值大于4095,有的65000多了,这是什么节奏?adc不是12位吗,最大才0xfff,即4095,怎么会出现这种情况呢?难到是adc数据对齐方式出现问题了,adc的对齐明明设置的是右对齐啊,神马情况?
" Q* L: y$ e. A, R' _& }: o. g$ o9 t! k6 v: m% F+ L0 T
ADC结构体参数分析

& k5 X$ ]8 j( Q: X9 X/ I  百思不得adc之姐,只能keil单步调试,一步一步查看adc结构体的参数。我使用的是adc dma方式采集,共9个通道。初始化程序如下:
% s8 @! `4 w' ?& F! e
  1. void ADC_DMA_Config(void)2 R1 [0 `! G' ?3 n
  2. {
    % }  R4 P: L3 }
  3.     ADC_InitTypeDef       ADC_InitStructure;
    ( t" l% k* n8 s1 g; k
  4.     ADC_CommonInitTypeDef ADC_CommonInitStructure;: v8 v6 D! t. _* ~
  5.     DMA_InitTypeDef       DMA_InitStructure;
      v$ ~# }9 o- f3 Z4 m9 X  p$ T
  6.     GPIO_InitTypeDef      GPIO_InitStructure;) ]1 M, y0 d' ?2 S# e
  7. & o- @, [7 Q8 d+ Z5 b/ E
  8.     RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2 | RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOC, ENABLE);
    ) v/ _+ I- p5 e3 M% f. n, Z* ~
  9.     RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);: B+ J" j0 d; F) V, D2 e. }! H: s0 H
  10. - m8 T( z  f( v% J
  11.     DMA_InitStructure.DMA_Channel = DMA_Channel_0;  + ~5 o6 q1 ~5 b' B' ?! k
  12.     DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&ADC1->DR;3 m7 S! A1 L& N$ M8 V
  13.     DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&ADC_ConvertedValue;  ; m4 n; q! I1 B: Z% d
  14.     DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
    # Z& i# ?5 N2 r$ n5 W$ R& C
  15.     DMA_InitStructure.DMA_BufferSize = Sample_Num*Channel_Num;         2 c, N/ V: _3 `* i  M% F7 k1 c
  16.     DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;5 B% d: O: @" B" w+ r9 o
  17.     DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;. G+ ?2 X, [  z: j( S* H) S  x
  18.     DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;3 T0 h" u, e  U4 ]; a5 T
  19.     DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
    ' O( J; K' I% t! t( j5 a2 s
  20.     DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;$ n2 o& W5 \  U5 k7 g
  21.     DMA_InitStructure.DMA_Priority = DMA_Priority_High;
    * N' q( m- N) r* d' [$ b
  22.     DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;         
    - n7 J. A+ ~/ a. f: J: J' C/ |
  23.     DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;* Q$ y0 V+ L! W5 t9 Q
  24.     DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;) L4 ~4 ?5 ?2 I$ Z
  25.     DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;% Z' Z- ]% Q3 q9 v. _
  26.     DMA_Init(DMA2_Stream0, &DMA_InitStructure);
    1 f; k, R- Z2 V  _  P& Q
  27.     DMA_Cmd(DMA2_Stream0, ENABLE);. M& f; T6 L4 Q* s
  28. * K0 c- {2 I! ]* H! V$ f
  29.   q6 c8 q5 d! X. E1 M0 ~" ^
  30.     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 |GPIO_Pin_2 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_7;" z0 f" i! U6 c  y
  31.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;" H) F) L% ]( p: V+ N3 @! e
  32.     GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;9 Z6 R% Q( Z1 X+ c6 k3 l: r9 P
  33.     GPIO_Init(GPIOA, &GPIO_InitStructure);, d5 M* l4 {* h& b7 D: t. F
  34. ; {  }  M& ?. B- u  X8 R
  35.     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_3 | GPIO_Pin_5;# I- u. Q+ a8 T7 C, S5 x7 g4 j
  36.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;( y, b# z) m' p4 D7 e1 w+ t6 |1 Y
  37.     GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
    , r* w' H7 h+ G9 O
  38.     GPIO_Init(GPIOC, &GPIO_InitStructure);
    5 r; W) q" O& R" C% ?8 s8 c% ?" a
  39. $ K3 J( Y. |1 u
  40.     /* ADC Common Init **********************************************************/0 d* n  V3 ]% y% H1 u$ q
  41.     ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;
    0 v- ~3 w% E0 @5 }+ I) J
  42.     ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div2;' _7 u$ ?) |1 ]& m+ R. @9 X
  43.     ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;
    ( H) T" Y1 V" M3 j3 u: h
  44.     ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;
    : ?7 b: o" v; _/ w, X8 P: A
  45.     ADC_CommonInit(&ADC_CommonInitStructure);' N# c2 m- Y% ~, q, T5 b) f
  46. + _8 |7 t! A$ k; I- Z
  47.     ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;9 S+ B% |6 c( J( ]6 D
  48.     ADC_InitStructure.ADC_ScanConvMode = ENABLE;7 H/ u* d" x6 l8 t3 t% b# T
  49.     ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
    : s  u; S; D' b8 o, P+ j/ [
  50.     ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
    ( o: F3 @4 ]2 S$ }* R, |
  51.     ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;, m, W8 p# L. h& f
  52.     ADC_InitStructure.ADC_NbrOfConversion = 9;$ B+ A+ s% N$ [3 p# _) W9 r& O
  53.     ADC_Init(ADC1, &ADC_InitStructure);/ U4 E, K$ q6 e  g$ ?. r6 _9 f

  54. ( W! q+ O% m# k0 b/ s7 J

  55. 0 p: b: ~! |! u2 x2 d
  56.     ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_3Cycles);
    2 j) n: v% e, h
  57.     ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 2, ADC_SampleTime_3Cycles);7 ]1 ^* U; v: D% k3 w6 G- c9 M
  58.     ADC_RegularChannelConfig(ADC1, ADC_Channel_2, 3, ADC_SampleTime_3Cycles);. R6 m8 M* R& X/ D& ~
  59.     ADC_RegularChannelConfig(ADC1, ADC_Channel_4, 4, ADC_SampleTime_3Cycles);
    & N# L- O: J0 O7 L: e
  60.     ADC_RegularChannelConfig(ADC1, ADC_Channel_5, 5, ADC_SampleTime_3Cycles);$ {6 w7 U* ]# D6 L
  61.     ADC_RegularChannelConfig(ADC1, ADC_Channel_7, 6, ADC_SampleTime_3Cycles);
    9 \, N! G7 u. I) b+ }, q' o: b
  62.     ADC_RegularChannelConfig(ADC1, ADC_Channel_11, 7, ADC_SampleTime_3Cycles);* [) J/ W- x  m* X: e
  63.     ADC_RegularChannelConfig(ADC1, ADC_Channel_13, 8, ADC_SampleTime_3Cycles);, `. B) g2 N9 p
  64.     ADC_RegularChannelConfig(ADC1, ADC_Channel_15, 9, ADC_SampleTime_3Cycles);. Z; e; b" `: H
  65.   M7 E8 E. c3 t# m" O
  66.     ADC_DMARequestAfterLastTransferCmd(ADC1, ENABLE);
    9 ~  e( e2 G- Z$ |# ^
  67.     ADC_DMACmd(ADC1, ENABLE);( G. r" z- _6 c. Q7 ^: |; z8 y5 V
  68.     ADC_Cmd(ADC1, ENABLE);; d9 M8 j' ^+ y* t- [
  69. + b/ r  G& J( ?" u- H  _
  70. }
复制代码
' l: v$ B' Y% N. e, Q* M
  其中涉及adc的初始化结构体代码部分如下:& @/ l5 T3 _3 X/ `4 {+ M' `9 ^0 F. N
; ?5 k2 l+ s6 {5 i. [; |
    ADC_InitTypeDef       ADC_InitStructure;4 Z" q5 G4 W/ B) {/ o5 ]' {
  1.     ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;% ?8 E; F7 O5 G% r3 E+ a( g' P
  2.     ADC_InitStructure.ADC_ScanConvMode = ENABLE;
    ( @5 r7 P) b/ x0 H! Q+ a+ ?
  3.     ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
    5 R5 i- A: T7 F: L' s
  4.     ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;, x. `$ u! @: J" c9 \7 E# m' _4 n
  5.     ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
    ( a: s6 U% H$ i- q/ v* p; B
  6.     ADC_InitStructure.ADC_NbrOfConversion = 9;3 `% e9 ~/ K' ?) `! x. l! {. T' }
  7.     ADC_Init(ADC1, &ADC_InitStructure);
复制代码
  一步一步调式发现结构体有一项ADC_ExternalTrigConv是0x08002d54,这一项并没有初始化对其赋值,忘记给结构体的这一项赋值了。最后这个值通过ADC_Init函数赋值给CR2的时候,第11位(也就是数据对其位)是1了,左对齐了!!!!!
; e7 \/ P8 p5 S# }6 S8 ]) X: z2 m% }
20180823193630758.png
7 K/ m1 o/ W* Y# i
; ^, A5 h2 y) ]6 w+ f
  下面来重点分析下adc初始化结构体中的各项参数的意义:8 ?' ^7 n* c- l, l7 v3 x3 F
  对于STM32,在使用ADC的时候需要配置几个参数。4 ]% }, `* [  \+ M3 p
(1) 第一个参数是ADC_Mode,这里设置为独立模式:
3 q, @: U, i0 G6 h0 G- |
, y$ b0 v3 K- e, X
  1. ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
复制代码

2 }7 z' G, Q& z$ p8 G在这个模式下,双ADC不能同步,每个ADC接口独立工作。所以如果不需要ADC同步或者只是用了一个ADC的时候,就应该设成独立模式了。
) H* V: g6 d8 g7 c3 ?
; V7 f7 k9 o4 Z  I(2) 第二个参数是ADC_ScanConvMode,这里设置为DISABLE。: f0 j6 v* b9 R9 W/ z! k+ H2 ?
  1. ADC_InitStructure.ADC_ScanConvMode = ENABLE;
复制代码
1 _4 g6 w1 W9 t; M1 {
如果只是用了一个通道的话,DISABLE就可以了,如果使用了多个通道的话,则必须将其设置为ENABLE。
6 j( B0 o3 a4 u( J- k7 _5 G' H( C7 G  K0 A+ n$ ?/ Z
(3) 第三个参数是ADC_ContinuousConvMode,这里设置为ENABLE,即连续转换。& o3 x+ b5 {; f  v
如果设置为DISABLE,则是单次转换。两者的区别在于连续转换直到所有的数据转换完成后才停止转换,而单次转换则只转换一次数据就停止,要再次触发转换才可以。所以如果需要一次性采集1024个数据或者更多,则采用连续转换。
4 r! C" ^! R1 C% z
. A% M: ~8 C: T( U6 L- \(4) 第四个参数是ADC_ExternalTrigConv,即选择外部触发模式。这里只讲三种:5 z% r8 v8 ~4 O
" }9 ]! y* w# w2 U1 u. Q' w
1、第一种是最简单的软件触发,参数一般为ADC_ExternalTrigConv_None(注意STM32F2XX系列这个有点蹊跷,后面会讲这个)。设置好后还要记得调用库函数:
6 U! c* O" A" {+ d* \* T
  1. ADC_SoftwareStartConvCmd(ADC1, ENABLE);
复制代码
  1. void ADC_SoftwareStartConv(ADC_TypeDef* ADCx)8 U6 @) P0 u9 _9 U3 F1 s
  2. {1 B4 ~6 D8 v2 H+ j
  3.   /* Check the parameters */
    9 S* u' C$ Q7 ]8 N5 u- g# w8 _. |
  4.   assert_param(IS_ADC_ALL_PERIPH(ADCx));5 y7 s5 E- U& T/ K) M* K& H
  5. . x5 \$ A, ^" g0 J' N6 f
  6.   /* Enable the selected ADC conversion for regular group */- o) y: S4 y1 z- k9 H& w- |$ O' Y
  7.   ADCx->CR2 |= (uint32_t)ADC_CR2_SWSTART;
    0 c) A% x6 P' \" k' |2 y
  8. }
复制代码
  1. #define  ADC_CR2_SWSTART                     ((uint32_t)0x40000000)      
    . q  a( ?+ ~  }$ D, ~- _& ^% B
  2. /*!<Start Conversion of regular channels */
复制代码
8 q! u7 `# E7 P4 y: O
ADC_SoftwareStartConv函数里直接置位CR2的ADC_CR2_SWSTART位,这样触发就启动了。
' b( ?8 Q! l, q. S1 `: h/ ^) A5 w( w9 H0 j% ]! f
2、第二种是定时器通道输出触发。共有这几种:ADC_ExternalTrigConv_T1_CC1、ADC_ExternalTrigConv_T1_CC2、ADC_ExternalTrigConv_T2_CC2、4 M% @2 H7 m( Y; W
. o: @$ P2 A: _7 y& v* K3 k
ADC_ExternalTrigConv_T3_T以及ADC_ExternalTrigConv_T4_CC4。定时器输出触发比较麻烦,还需要设置相应的定时器。以
7 i1 B/ O. [( x
+ c9 f1 p8 w, X$ ZADC_ExternalTrigConv_T2_CC2触发为例设置相应的定时器:
5 e. B4 o3 @/ v8 w. B
3 H# _6 H2 T2 I5 y: j7 k
  1. void TIM2_Configuration(void)( Z' D9 p& N8 _5 L3 ?) s5 o& F

  2. 7 i# i" U5 W3 g- A; E# ^
  3. {
    6 e& M& {: h1 U  Q! W4 b( [3 f
  4. * k8 o2 V: B7 q
  5. TIM_TimeBaseInitTypeDef   TIM_TimeBaseStructure;7 a$ X' G3 @* Z6 \2 T$ G

  6. , H- g4 S3 v6 ]4 a8 \
  7. TIM_OCInitTypeDef         TIM_OCInitStructure;
    3 E2 j* S$ \3 {- I
  8. 0 [" G" J! a" o6 d4 Y# x2 b) H
  9. TIM_TimeBaseStructure.TIM_Prescaler = 4;
    , e3 u& o7 ^- w

  10. * |  ^" S  [, R2 K
  11. TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;* z, H  ?6 i% a! x* w
  12. 3 B) o: k" z3 |0 }3 n  f
  13. TIM_TimeBaseStructure.TIM_Period = 0XFF;: A1 l+ Q/ U. \
  14. 8 Y8 d0 D; ?, m- J3 B! B8 m
  15. TIM_TimeBaseStructure.TIM_ClockDivision = 0;& Y" I  m3 S* ~3 @" Q3 M

  16. 3 Y3 X* Z8 i4 A. M% W  ?# m
  17. TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;/ y4 z5 ?6 {( i* K  f4 Q

  18. ! u, _, }3 k5 v( \: F
  19. TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
    . }8 ]' {5 K. j- |0 j
  20. ; B  L) l& A3 n2 S

  21. 0 |. F/ G) D- Q0 M; b" f. ^4 Y8 l
  22. TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
    7 U3 P' [* s' A6 X0 o; s

  23. 8 h1 K9 ?9 z' o4 R4 o3 G& x# Y
  24. TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;8 O, {5 O8 ]' \* E: B7 W. ^
  25. 6 T! I& F: Q0 U/ v/ N
  26. TIM_OCInitStructure.TIM_Pulse = 0X7F;8 ]$ K' Q$ }# B* e+ e

  27. " f. }6 k4 t# b) `+ a
  28. TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;
    " Z3 L) o5 I: P: H' i
  29. % Y; I+ ^- N# k
  30. TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;        * ]6 i0 ]& @# Y! u$ a% _
  31. 1 v1 a- V" R. N4 U5 h
  32. //配置CC2的属性。若CC3作为ADC的触发源,则应改为TIM_OC3Init(TIM2, &TIM_OCInitStructure);4 \: H& E3 [7 q: \) D
  33. , Y; ^0 S: y, i" l
  34. TIM_OC2Init(TIM2, &TIM_OCInitStructure);' y2 g/ {; @: y. p' V- ^3 f
  35. % p4 S/ J1 a! _  ^4 z& u6 A
  36. TIM_Cmd(TIM2, ENABLE);
    ! Q; t% n7 B2 k# a$ j- H
  37. TIM_CtrlPWMOutputs(TIM2, ENABLE);
    5 {' J* B# a# {2 ^2 g8 ?- h
  38. }
复制代码
: D1 F: k- j" Q3 \- S. f5 r; S
9 u' f" \9 X0 `. [! R2 C- I
这样设置之后就可以用定时器2的输出触发了,至于触发的周期,设置TIM2的时间即可。这里不再赘述。
) r! W) Y: U& F2 d* a& f: y/ z' @7 \% V; M  f
3、第三种是外部引脚触发,对于规则通道,选择EXTI线11和TIM8_TRGO作为外部触发事件;而注入通道组则选择EXTI线15和TIM8_CC4作为外部触发事件。$ |' C, H! s' \6 p+ s6 L, D$ x7 D
8 `8 j8 b! Q, U1 ?" C
(5) 第五个参数是ADC_DataAlign,这里设置为ADC_DataAlign_Right右对齐方式。建议采用右对齐方式,因为这样处理数据会比较方便。当然如果要从高位开始传输数据,那么采用左对齐优势就明显了。
; O, Z. m0 w, E* i+ `& e, L9 X# h3 O# M
(6) 第六个参数是ADC_NbrOfChannel,顾名思义:通道的数量。要是到多个通道采集数据的话就得设置一下这个参数。此外在规则通道组的配置函数中也许将各个通道的顺序定义一下,如:5 z5 D8 v; D$ A3 R1 H
  1.       ADC_RegularChannelConfig(ADC1,ADC_Channel_13,1,ADC_SampleTime_13Cycles5);/ e% r; ^) W% v2 U8 f5 L
  2. . t5 G8 o3 J/ T* K8 B# h8 p
  3.       ADC_RegularChannelConfig(ADC1,ADC_Channel_14,2,ADC_SampleTime_13Cycles5);
复制代码

' S6 n' n9 C& x; b- {. D+ `' t, R; P' j7 y) T: f( A/ p
  多通道数据传输时有一点还要注意:若一个数组为ADC_ValueTab[4],且设置了两个通道:通道1和通道2,则转换结束后,ADC_ValueTab[0]和ADC_ValueTab[2]存储的是通道1的数据,而ADC_ValueTab[1]和ADC_ValueTab[3]存储的是通道2的数据。如果数组容量大则依次类推。& i  ?* O7 M7 `! i- t. z2 Q
) X( W0 C* |1 _: n; m* x  h2 \6 P
  补充一点:在使用DMA传输数据的时候,需要设置外设地址和存储器地址,外设地址当然就是ADC的地址了,而存储器的地址如果使用8位数据的话,存储器必须定义为8位缓冲区;如果使用16位数据格式的话,存储器则为16位缓冲器,不可定义为32位或更多,否则,数据将出错。
. K! Z! c% a& `/ g! c( Z; F! F8 h2 Z- s. a
问题的解决方法
4 A: B5 m% h0 |3 |5 [
  上面分析了adc结构体的参数,下面再来单独看看ADC_ExternalTrigConv这一项。
' J! M  ~/ S0 |" i  在stm32f2xx_adc.h文件中有这个成员的参数定义,发现里面并没有ADC_ExternalTrigConv_None这个常见的定义。
$ a7 X+ Z7 e* Z. K+ @5 B. s
; M# V# [" i0 J, E' J
  1. /** @defgroup ADC_extrenal_trigger_sources_for_regular_channels_conversion
    $ K" [5 U, N, Z$ N  _0 S5 A
  2.   * @{8 U& E( l* w+ u! z. z, _# s
  3.   */ ! V* x5 T& f' f& k
  4. #define ADC_ExternalTrigConv_T1_CC1                ((uint32_t)0x00000000)
    , ?) C  s" b7 Q! @
  5. #define ADC_ExternalTrigConv_T1_CC2                ((uint32_t)0x01000000)
    4 M  J4 P2 s" ?
  6. #define ADC_ExternalTrigConv_T1_CC3                ((uint32_t)0x02000000)8 u1 Z6 s  t; T% L) `
  7. #define ADC_ExternalTrigConv_T2_CC2                ((uint32_t)0x03000000)5 w5 P; B# D/ d% m6 M
  8. #define ADC_ExternalTrigConv_T2_CC3                ((uint32_t)0x04000000), K/ ^1 p$ R" I; n, S
  9. #define ADC_ExternalTrigConv_T2_CC4                ((uint32_t)0x05000000)2 d0 u& q6 W- A+ U
  10. #define ADC_ExternalTrigConv_T2_TRGO               ((uint32_t)0x06000000)/ n2 M, R+ ~6 z+ c! X& Z  u; m# s
  11. #define ADC_ExternalTrigConv_T3_CC1                ((uint32_t)0x07000000)0 l+ d4 m; S. A3 Y( z
  12. #define ADC_ExternalTrigConv_T3_TRGO               ((uint32_t)0x08000000)
      G# K) ~! x0 L1 i4 e
  13. #define ADC_ExternalTrigConv_T4_CC4                ((uint32_t)0x09000000)4 [2 E' k+ h' n. v6 S
  14. #define ADC_ExternalTrigConv_T5_CC1                ((uint32_t)0x0A000000)
    ) o: [, q# f6 F% e" l
  15. #define ADC_ExternalTrigConv_T5_CC2                ((uint32_t)0x0B000000)
    % W# F2 `: o# `
  16. #define ADC_ExternalTrigConv_T5_CC3                ((uint32_t)0x0C000000)$ {# p, q+ D4 {6 a" }
  17. #define ADC_ExternalTrigConv_T8_CC1                ((uint32_t)0x0D000000)
    + ^5 l. j# [  R! e- E  L& p  |
  18. #define ADC_ExternalTrigConv_T8_TRGO               ((uint32_t)0x0E000000)& A, J& C( w0 J0 V( B2 B
  19. #define ADC_ExternalTrigConv_Ext_IT11              ((uint32_t)0x0F000000)
复制代码

' }% g" V( d: i% {' h  再来看看stm32f10x_adc.h文件中的ADC_ExternalTrigConv的参数定义:
5 p, F# Z1 S5 H3 f+ {/ m9 Q
  1. /** @defgroup ADC_external_trigger_sources_for_regular_channels_conversion
    8 r" D  c' r( m& }8 O1 l6 H
  2.   * @{
    $ ~9 [0 Z: v  A& k/ `4 t
  3.   */" I7 z. G! x/ U" M, J& p- Z; N

  4. . q! w1 r5 V8 u) c' c
  5. #define ADC_ExternalTrigConv_T1_CC1                ((uint32_t)0x00000000) /*!< For ADC1 and ADC2 */
    5 U, `6 s# M1 n8 I5 X; v; a+ o3 B
  6. #define ADC_ExternalTrigConv_T1_CC2                ((uint32_t)0x00020000) /*!< For ADC1 and ADC2 */7 V& ]2 U' j$ S) g2 H
  7. #define ADC_ExternalTrigConv_T2_CC2                ((uint32_t)0x00060000) /*!< For ADC1 and ADC2 */
    6 h; |6 n* \+ k: b
  8. #define ADC_ExternalTrigConv_T3_TRGO               ((uint32_t)0x00080000) /*!< For ADC1 and ADC2 */
    " i/ z$ m7 c/ B7 s  C! m0 J. e8 B
  9. #define ADC_ExternalTrigConv_T4_CC4                ((uint32_t)0x000A0000) /*!< For ADC1 and ADC2 */
    4 E& F! f: N2 o! ^$ N- e
  10. #define ADC_ExternalTrigConv_Ext_IT11_TIM8_TRGO    ((uint32_t)0x000C0000) /*!< For ADC1 and ADC2 */1 ~' }, W% c+ @; {1 `
  11. , g) u, n5 q* U
  12. #define ADC_ExternalTrigConv_T1_CC3                ((uint32_t)0x00040000) /*!< For ADC1, ADC2 and ADC3 */
    ' t2 ]' u0 x! }/ T. e& u4 |# u
  13. #define ADC_ExternalTrigConv_None                  ((uint32_t)0x000E0000) /*!< For ADC1, ADC2 and ADC3 */   //f2xx系列并没有这个定义8 [* T1 w5 E0 I! ~( O
  14. 3 \+ o1 u& Z% O4 c% B
  15. #define ADC_ExternalTrigConv_T3_CC1                ((uint32_t)0x00000000) /*!< For ADC3 only */0 F) p# n3 Z  u' H0 G& Y
  16. #define ADC_ExternalTrigConv_T2_CC3                ((uint32_t)0x00020000) /*!< For ADC3 only */
    + s7 m! L7 s/ t; p  v" P' F
  17. #define ADC_ExternalTrigConv_T8_CC1                ((uint32_t)0x00060000) /*!< For ADC3 only */
    3 n) s; y! q& W1 X) P' t
  18. #define ADC_ExternalTrigConv_T8_TRGO               ((uint32_t)0x00080000) /*!< For ADC3 only */
    + }" |4 J9 l& v; ~3 b; c, b
  19. #define ADC_ExternalTrigConv_T5_CC1                ((uint32_t)0x000A0000) /*!< For ADC3 only */
    ( B& L/ T* c2 d2 a  U/ P
  20. #define ADC_ExternalTrigConv_T5_CC3                ((uint32_t)0x000C0000) /*!< For ADC3 only */
复制代码

, o. o, n) g( p9 N' n% R8 U+ P) B! E  对比发现stm32f2xx系列并没有ADC_ExternalTrigConv_None这个定义,很是奇怪,现在还不明白ST的工程师为什么做这个变动。
6 ^9 ]+ z8 c  a7 k* {9 j  那么问题怎么解决呢?
9 |+ T, u, z* t/ B# A: C, q  一种是进行adc结构体的初始化操作,在配置之前恢复默认值。即调用ADC_StructInit(&ADC_InitStructure);修改如下:
  1.     ADC_StructInit(&ADC_InitStructure);//新增加的
    0 D# `4 i  ~  V, I0 _* I  ^
  2.     ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;* }% v5 H; C6 Z6 C$ C3 D
  3.     ADC_InitStructure.ADC_ScanConvMode = ENABLE;5 Y1 u3 A$ ^* E
  4.     ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;5 [5 j9 R% w8 S- e+ B
  5.     ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;' I( Y1 B/ P4 ~2 N! }2 [, _# `
  6.     ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
    $ k7 O6 |* T3 C8 X& G
  7.     ADC_InitStructure.ADC_NbrOfConversion = 9;: H- S6 \7 V: {2 o
  8.     ADC_Init(ADC1, &ADC_InitStructure);
复制代码
  调用ADC_StructInit(&ADC_InitStructure)语句,ADC_ExternalTrigConv会恢复默认值0。如下:
9 Y; A% \1 }  U; X# @: O8 O; X
9 o: y& c9 S# B" w2 m
20180823201211262.png
: b4 t* n4 A, @8 ^, L8 z
- D5 q* }8 w5 u8 i3 |; h8 y
  另一种方法是直接配置该参数为0,如下:
5 H9 g& R! p4 D* r1 H
  1.     ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;) g$ N: `& V) G& t5 `6 j7 E: b4 I
  2.     ADC_InitStructure.ADC_ScanConvMode = ENABLE;1 r' m3 O4 z& Z9 I3 z
  3.     ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;( ?/ a, P! O1 C/ \; g+ I6 T! A
  4.     ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
    0 }7 _) G8 x# R
  5.     ADC_InitStructure.ADC_ExternalTrigConv= 0;//新增加的- ?) I. V& q1 C) i0 D  R* B, S
  6.     ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;1 V4 f6 c9 t  m9 z3 O5 m
  7.     ADC_InitStructure.ADC_NbrOfConversion = 9;
    , R0 V4 p- j( K
  8.     ADC_Init(ADC1, &ADC_InitStructure);
复制代码
7 \. [0 m/ P9 y% K
  这两种方法都可以解决adc采样对齐方式异常问题。* V- o: z) j7 k" ~2 g6 m9 }$ A5 B
  但是ADC_ExternalTrigConv= 0在stm32f2xx_adc.h中其实是对应ADC_ExternalTrigConv_T1_CC1的。0 o/ f! \/ P4 v0 x; c2 O  v

  D: U/ H* a( S* S1 S  F
20180823201832969.png
1 Q! m/ o4 [2 F+ o  G( E# t

7 B* x/ R. J6 Z; k( r  也就是说调用软件触发函数ADC_SoftwareStartConv函数里直接置位CR2的ADC_CR2_SWSTART位也可以触发定时器触发方式的adc通道。
# t3 o* E$ L( h6 _
2 W. I0 ~" S& u3 A. E2 k4 g4 Q0 B, l
1 s* q% i4 n8 N2 d1 C1 i: Z
收藏 评论0 发布时间:2021-12-2 16:03

举报

0个回答
关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版