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

STM32L071RB ADC 多通道模式

[复制链接]
hellolinux-2302 发布时间:2018-10-20 20:56
项目上要用到STM32L071 ,很简单的采集4个通道的ADC值。网上找了一下什么IT模式,DMA模式.....太多了,太麻烦。我们的应用很简单,就是每隔1秒采集一下ADC IN0,ADC IN1, 内部参考电压, 内部温度传感器4个通道。4 z4 p6 w! |$ u8 W- x+ ^7 \* w
首先是ADC初始化,用到了Vrefint,和内部温度传感器。% D- P0 R1 m' Z

; N" K% i/ Z4 p, p  ^  z
  1. /* ADC init function */
    ) t+ M9 x, d" f/ O4 m$ {
  2. void MX_ADC_Init(void)
    ) K; b" t% i" o% @2 z1 Z! a; f
  3. {
    - F3 T  e4 ^9 y* ^. A

  4. ' J. d1 l1 z0 x3 \7 j/ l
  5.   ADC_ChannelConfTypeDef sConfig;
    3 `( T7 d. W0 M7 ^7 o$ ~3 F

  6.   G; r1 M- E4 |+ X2 M0 \, t
  7.     /**Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion)
    7 ]; W' a+ w% S1 R
  8.     */
    6 a* A3 F' J8 `5 g* A% V) ^
  9.   hadc.Instance = ADC1;/ _- R/ z) {, f0 S! `6 J
  10.   hadc.Init.OversamplingMode = DISABLE;
    ' w6 @2 j* Y% j- T$ e
  11.   hadc.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV2;* X1 s) O0 N  e& Y5 C& E7 a
  12.   hadc.Init.Resolution = ADC_RESOLUTION_12B;2 ?" A: q7 `# n. H1 ?2 @9 Q
  13.   hadc.Init.SamplingTime = ADC_SAMPLETIME_160CYCLES_5;* ~, z9 S9 m$ t/ r, y/ J1 ~
  14.   hadc.Init.ScanConvMode = ADC_SCAN_DIRECTION_FORWARD;
    " p' B0 E# l% ]* W# o& c# @
  15.   hadc.Init.DataAlign = ADC_DATAALIGN_RIGHT;7 t9 h" \+ S& |
  16.   hadc.Init.ContinuousConvMode = DISABLE;
    3 e+ M# c1 \# D( r
  17.   hadc.Init.DiscontinuousConvMode = ENABLE;
    8 x; B9 `) W3 r/ }0 `6 E  f
  18.   hadc.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;1 w: K. C5 t+ q& H0 z0 i
  19.   hadc.Init.ExternalTrigConv = ADC_SOFTWARE_START;
    5 M7 o- d5 I# m
  20.   hadc.Init.DMAContinuousRequests = DISABLE;6 n5 `1 L) t- @0 w( z( {
  21.   hadc.Init.EOCSelection = ADC_EOC_SINGLE_CONV;' e% p6 Z$ _2 T  }  ~
  22.   hadc.Init.Overrun = ADC_OVR_DATA_PRESERVED;
    7 a  [) y; i; w8 W
  23.   hadc.Init.LowPowerAutoWait = DISABLE;  p- c# @. h3 w- W! J% N5 f
  24.   hadc.Init.LowPowerFrequencyMode = DISABLE;
    8 `0 ]" c5 |5 k# Q$ i! o
  25.   hadc.Init.LowPowerAutoPowerOff = DISABLE;
    % v+ ]) m3 |' |# ~0 F% a
  26.   if (HAL_ADC_Init(&hadc) != HAL_OK)
    5 ?- I2 {1 A( Y( z
  27.   {& F5 l0 }5 A7 Q" y, {; ~+ x3 M/ X, ]
  28.     _Error_Handler(__FILE__, __LINE__);2 \) A) P6 }) Q4 a9 V1 ?
  29.   }
    2 L/ n* d6 }% P7 v$ d
  30.   /* 校正ADC */& o' H; Q, Y" L  g+ u
  31.   if(HAL_ADCEx_Calibration_Start(&hadc, ADC_SINGLE_ENDED) != HAL_OK), `  G( h- G1 e( r' j
  32.   {" f$ n' f# I, B# _
  33.     _Error_Handler(__FILE__, __LINE__);
    % E8 e* p/ _5 H( Z: q' R. ]* T* E
  34.   }% M4 k8 x$ ~) v$ A
  35.   , n, E- n1 h% r" m' M+ @: M
  36.   /**Configure for the selected ADC regular channel 0 to be converted.*/5 v- S  y" D/ A" l. u2 ~: U
  37.   sConfig.Channel = ADC_CHANNEL_0;9 P8 `& f  y9 \* V' @
  38.   sConfig.Rank = ADC_RANK_CHANNEL_NUMBER;
    ! F0 v$ e. c7 y: z
  39.   if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
    $ \  {+ n2 }/ u0 v6 c
  40.   {
    2 h  L; G, V3 i8 [! U& j" S) k- T
  41.     _Error_Handler(__FILE__, __LINE__);8 e, n( D$ i& N$ V8 q
  42.   }- W+ Y& ^2 G  o
  43.   /**Configure for the selected ADC regular channel 1 to be converted.*/7 v$ }0 n' q$ c4 W+ e% x# P. J
  44.   sConfig.Channel = ADC_CHANNEL_1;9 d) b5 M3 |" L$ g
  45.   if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
    + i4 B. f5 @+ M3 U8 v) P
  46.   {
    4 T& a# G; ^% c3 d8 W1 I
  47.     _Error_Handler(__FILE__, __LINE__);
    ; H' _+ Z0 {. Y, t0 v
  48.   }
    ! ?+ M5 y$ E) ~3 D8 J3 K9 T3 h
  49.   
    % M7 S& W+ B( @- R# D
  50.   /**Configure for the selected ADC regular channel 17 to be converted.*/
    6 W* Z: s" J" N9 W4 w
  51.   sConfig.Channel = ADC_CHANNEL_VREFINT;: I5 w, _; x- u6 u" E; M( [) \5 v
  52.   if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
    1 S  b" [$ L8 q+ T% v
  53.   {
    : M/ ^% E" H7 b9 v
  54.     _Error_Handler(__FILE__, __LINE__);
    ; P) Q/ O5 S% T% |/ o7 o, C
  55.   }
    4 ?! ?  W/ z* M7 P+ c8 k: H- [5 G
  56.   # G" q3 p/ o# G  z1 Y
  57.   /**Configure for the selected ADC regular channel 18 to be converted.*/
    $ y0 g* A* M* b9 ^: T5 d
  58.   sConfig.Channel = ADC_CHANNEL_TEMPSENSOR;
    6 s! {; ~% {; H: \8 a# I
  59.   if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)" v1 {. e4 n7 E2 m4 q
  60.   {2 {# V# X$ {) }2 W. \
  61.     _Error_Handler(__FILE__, __LINE__);
    - P" [% U, Q5 P3 c7 Z
  62.   }2 n3 A* O% [7 x) e. q4 _
  63.   
    0 E4 T. d! \2 A; I6 s$ X" s. X. a
  64.   HAL_ADCEx_EnableVREFINT();6 o4 @% K, O, e! \' O: p" a+ L
  65.   HAL_ADCEx_EnableVREFINTTempSensor();
    3 y% j) K# }- \9 [2 K
  66. }
复制代码

7 k. a4 S8 `7 i( B  a+ y  n3 P6 i- b# j; v6 |8 z
- m" Q  M6 q( e$ v8 f$ w

1 H3 J" Z2 _  [ADC采样函数5 m4 y* A) U: N' D7 s* y) D
  1. /* Private functions ---------------------------------------------------------*/  N4 ~' Z/ N  g8 ]/ X
  2. #define RES1  10000   //分压电阻R1,10K
    . e* k. e0 y% ~& A
  3. #define RES2  10000   //分压电阻R2,10K
    : I: i( M' s/ f4 m. y) R, Y: J3 O
  4. #define PRATIO  (RES1+RES2)/(RES2)% v' |) D, K. J7 |/ ^' p6 G

  5. , {4 a+ `2 `8 A+ M. a
  6. #define ADC_12BIT     4095.0
    - z/ m& U. W. l0 d
  7. #define ADC_REF       3.3
    4 k  j* }- c1 v$ Y
  8. / f5 X! P5 ?' Y! z% Y5 x
  9. #define VOL_RADIO     ADC_REF/ADC_12BIT                                                //无电阻分压模式系数
    3 g$ T: g2 p2 S2 l( S
  10. #define BAT_RADIO     (ADC_REF*PRATIO)/ADC_12BIT  //电阻分压模式系数
    9 y6 k: _/ E; {% V2 n6 {# E) U
  11. , \7 \' l: V" P0 s
  12. //温度校正! ]+ M0 Q- H; v. i
  13. #define TEMP130_CAL_ADDR ((uint16_t*) ((uint32_t) 0x1FF8007E))
    2 w5 f+ R$ o6 e& q
  14. #define TEMP30_CAL_ADDR ((uint16_t*) ((uint32_t) 0x1FF8007A))% Q9 F6 ?; `7 p& b6 e" p* ?, H
  15. #define VDD_CALIB ((uint16_t) (300))
    ) }9 n' x0 a$ s
  16. #define VDD_APPLI ((uint16_t) (330))
    ( d+ J# g3 `+ {+ Y' C
  17. /*******************************************************************************/ M% [/ a1 K# p& F6 Q8 [( K9 t& p5 @
  18. * Function Name  : ComputeTemperature$ F( b, v* i9 v% O: C
  19. * Description    : Compute STM32 Temperature
    2 H# \7 ~2 X. |. l
  20. * Input          : None/ _0 M% m* F- \7 b
  21. * Output         : None( q  N- V8 Z9 a6 g3 S! x. ?, z
  22. * Return         : None
      _* J$ }% w# Q+ d
  23. *******************************************************************************/6 @( d1 t" r9 Q/ v/ d0 |7 Q5 b
  24. int32_t ComputeTemperature(uint32_t measure)
    6 e" @  z- [" ~8 \$ Y  U8 E
  25. {
    , d) A/ F; P+ ~9 ], S
  26.   int32_t temperature;
    7 E) _" \+ i/ I3 r, ~
  27.   temperature = ((measure * VDD_APPLI / VDD_CALIB)- (int32_t) *TEMP30_CAL_ADDR );4 L7 V( q4 K5 i) @. ?" ~
  28.   temperature = temperature * (int32_t)(130 - 30);
    ( a" j" v! W: J% I" o+ {
  29.   temperature = temperature / (int32_t)(*TEMP130_CAL_ADDR - *TEMP30_CAL_ADDR);
    ( Z* F5 q( S! E: Y" \, T
  30.   temperature = temperature + 30;
    " E0 L( L9 J0 n: }& Y! H4 Q3 ?4 n  e
  31.   return(temperature);
    5 A+ z" s% H* s& j1 }
  32. }
    + O6 V/ ]% Z6 d, L5 ?
  33. /*******************************************************************************
    , s9 V# D6 p- o8 y
  34. * Function Name  : Get_Adc
    8 O6 [! k4 e6 m! ~
  35. * Description    : get voltage
    : X) f2 v% S$ l2 r
  36. * Input          : None
    $ m! r& k3 o9 y& B
  37. * Output         : None: m- E* i+ A. r" k
  38. * Return         : None) y7 ?; F3 d# u2 i7 K
  39. *******************************************************************************/
    & r+ V! f7 F% T: I3 D
  40. void Get_Adc(void): h  G' `2 D$ U) V
  41. {: G+ T% `* @, a- j) \) P9 F
  42.   u32 adc_value;2 T' Z! d2 b( s; V% l
  43.   adc_value = 0;
    * y. E3 S, M8 B

  44. 2 U" P5 |, V4 f
  45.   /*Start the conversion process*/  
    " P" ^9 S# Y7 L) O- M" H
  46.   if (HAL_ADC_Start(&hadc) != HAL_OK)# C, g6 z$ T+ @7 I
  47.   {4 Z. ]5 k* p$ {
  48.     /* Start Conversation Error */
    / d) U" K/ t9 b' c7 b
  49.     Error_Handler();
    5 b6 Q+ O5 L+ w) y
  50.   }6 n5 _7 b$ u. s* \7 O9 n# s% J
  51.   HAL_ADC_PollForConversion(&hadc, 50);   
    : a8 `0 T$ n# w9 e) H" k/ b
  52.   /* Check if the continous conversion of regular channel is finished */8 k) a. ]- `# l( R/ F! ~
  53.   if ((HAL_ADC_GetState(&hadc) & HAL_ADC_STATE_REG_EOC) == HAL_ADC_STATE_REG_EOC)8 i  v2 X0 k" Y6 u9 h2 d5 ^+ O
  54.   {9 z/ s! b: B- F+ c; X$ ~' Q( ~
  55.     /*Get the converted value of regular channel */
    % t* N3 A& Y" T. [% `
  56.     adc_value = HAL_ADC_GetValue(&hadc);1 `1 T- \( H0 J1 {  p+ g
  57.   }
    ; ]3 l$ e6 f3 ]; d9 E
  58.   printf("DEBUG: ADC CHANNEL 0  = %fV\r\n", BAT_RADIO*adc_value);                //ADC 通道0 用10K,10K电阻分压  z- Y4 x0 h# _( z9 U" L

  59. ) W, m1 j4 V' i
  60.   2 A, n0 p0 U$ B) J7 N
  61.   /*Start the conversion process*/  
    & _" L$ D) T9 V/ |6 j/ U6 h" `) H+ r
  62.   if (HAL_ADC_Start(&hadc) != HAL_OK)
    / H+ Z: d; _, _& U9 Z" N6 U/ R9 a
  63.   {  F  P: j) d; M. J
  64.     /* Start Conversation Error */
    & M( B- o% _  F* h: R
  65.     Error_Handler();
    ( U6 b. g% E( h% p& o1 L
  66.   }
    : ~/ s1 n4 S/ J3 f* I
  67.   HAL_ADC_PollForConversion(&hadc, 50);    9 \5 x5 Z, C5 W' C% {2 e
  68.   /* Check if the continous conversion of regular channel is finished */
    % Z' I% }) g: M  V( ]( R, m
  69.   if ((HAL_ADC_GetState(&hadc) & HAL_ADC_STATE_REG_EOC) == HAL_ADC_STATE_REG_EOC)
      w4 Q" R" k$ {! o
  70.   {
    ) v) L2 {/ H8 h( t+ F1 p8 L1 z) H2 W
  71.     /*Get the converted value of regular channel *// b( C. Y+ t9 m6 S3 _( D. o: b0 e
  72.     adc_value = HAL_ADC_GetValue(&hadc);
    ; E4 Z! {7 P! t1 F
  73.   }
    , ?! q& R1 q( z7 a9 T2 j4 R
  74.   printf("DEBUG: ADC CHANNEL 1  = %fV\r\n", VOL_RADIO*adc_value);                //ADC 通道1 没用电阻分压
    ' [) l5 G) Q* r3 k8 i
  75. ( B: f5 j$ ?2 ]# ?9 e; s4 Q2 `
  76.   
    ' Y: E, w$ G0 s4 p: i
  77.   /*Start the conversion process*/  - `, x& M! d5 W( `  w* \
  78.   if (HAL_ADC_Start(&hadc) != HAL_OK), n+ d/ d: S, h  K3 H+ Z
  79.   {
    + S0 {$ N  N) Y) g9 {" ], o
  80.     /* Start Conversation Error */
    6 \0 q; P) E4 m3 `- ^" J+ q
  81.     Error_Handler();
    5 r+ a( H1 C; H
  82.   }
    - q  o) C- A9 T6 V/ G) d1 l8 o
  83.   HAL_ADC_PollForConversion(&hadc, 50);    # a5 k+ q4 W$ i* F( H, u
  84.   /* Check if the continous conversion of regular channel is finished */
    9 S  a* A( ~$ W, o; ?; t" M/ y3 W
  85.   if ((HAL_ADC_GetState(&hadc) & HAL_ADC_STATE_REG_EOC) == HAL_ADC_STATE_REG_EOC)4 h9 U# ^# d$ c9 Y  t
  86.   {. u% K' U1 n+ x+ T4 U0 a! A" p! K
  87.     /*Get the converted value of regular channel */
    3 h; f) j( I# ~; m9 {
  88.     adc_value = HAL_ADC_GetValue(&hadc);# K) U( X1 l/ I) R5 N* w% s2 g2 }
  89.   }
    2 ^* q3 o2 |% I5 i
  90.   printf("DEBUG: ADC CHANNEL 17 = %fV\r\n", VOL_RADIO*adc_value);        //内部Vref = 1.2V" X6 ^% j7 {( Q
  91. # [4 }! y0 w) i# d
  92.   
    $ l1 N# F; l+ s1 |& U$ n( W4 m: R
  93.   /*Start the conversion process*/  6 g+ c, x; {. u2 f+ X. k8 D
  94.   if (HAL_ADC_Start(&hadc) != HAL_OK)' X  r; s+ c* D1 E2 u
  95.   {
    4 S8 q/ Q+ M! ~/ n9 m
  96.     /* Start Conversation Error */8 w. k7 d! M6 j. b! D. l% t+ e' s
  97.     Error_Handler();
      ~  m3 c6 p4 T$ `9 |  [! u
  98.   }1 k3 U$ t& o9 b" B
  99.   HAL_ADC_PollForConversion(&hadc, 50);   
    ; ?  _; }# i* \8 i* s- G
  100.   /* Check if the continous conversion of regular channel is finished */
    ) r5 b+ Q# w8 P! k2 p
  101.   if ((HAL_ADC_GetState(&hadc) & HAL_ADC_STATE_REG_EOC) == HAL_ADC_STATE_REG_EOC)' F. ]0 I* e8 b$ T. l# P+ b+ D
  102.   {
    ; }) k, u- P0 C, }) w
  103.     /*Get the converted value of regular channel */6 J' U! O+ ?* N6 \* j2 ~
  104.     adc_value = HAL_ADC_GetValue(&hadc);
    + |# I/ i3 R! I9 s4 P3 D
  105.   }' [/ q6 T% |5 c  _, _
  106.   printf("DEBUG: ADC CHANNEL 18 = %d℃\r\n", ComputeTemperature(adc_value));        //内部温度传感器) l8 p  d: ]6 T0 ?( u
  107.   
    + M/ _" o, G* q. |; h9 G8 A7 g3 K
  108.   HAL_ADC_Stop(&hadc);
    3 h( T' E! n6 ~  S" }
  109. & L2 L9 Q; e+ q+ S8 ?& |' m
  110. }
复制代码

% f' o3 A& n4 L# }" p9 b: n2 B$ J# G1 _# z, D! b9 x
收藏 评论5 发布时间:2018-10-20 20:56

举报

5个回答
fanyao-367090 回答时间:2018-10-25 08:56:04
楼主这是吐槽么
hejun1203 回答时间:2018-10-27 15:48:43
shinyzhuo 回答时间:2019-1-4 16:54:20
楼主可以啊,刚好我这就要用ADC来采集电压,先收藏了
hellolinux-2302 回答时间:2019-1-4 17:13:41
fanyao-367090 发表于 2018-10-25 08:56
$ ~1 }9 T& h* x) c0 y7 a楼主这是吐槽么

; ], u0 W/ d3 g5 p, w' y( C; gST 给的很多历程太复杂,其实大家的应用都很简单。
shinyzhuo 回答时间:2019-1-14 16:57:20
“Error[Pe020]: identifier "u32" is undefined ”3 A& [4 C% t0 E& R( W* p
楼主这个怎么报错呀
关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新和工艺
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版