STM32L0开发系列——01 ADC采集& Z* @+ p# {- s4 ]' G7 s
前言
% |, q: R! X( z# } B使用芯片:STM32L051C8T6! X% |* {0 R5 ?/ O. r/ S
软件平台:KEIL V5、STM32CubeL0$ x. C$ n9 \4 {5 f" K) B
库函数:HAL9 r0 T; o- W9 p$ h2 k; ~& X
- ] @/ P( W7 z' }+ ^一、原理图$ u5 P7 R8 i1 `* a! |8 Y( ?
本文介绍在STM32上使用ADC1的第1通道,对电池电量进行采集。
% J J8 r# N% A# \2 {" O% ?) E& h: |, |0 g/ ?4 L8 [ E5 |- g5 d1 N, t
+ s9 c/ _+ ]$ V; R% {9 j9 R
) X( k5 ~7 v* Y l2 k
二、ADC通道与引脚对应关系
8 w: o1 T7 [( J- E) r6 X9 j' I+ X% T+ B; U7 `
" ~! t5 ?+ U \3 k
" c1 Z+ r) E$ U0 Q( h1 w# I& f, ~( J, x3 D0 O1 ^, r/ O, i. v3 E9 |
三、ADC相关
) g; f+ f5 Y$ q7 M# M6 e4 Y ^8 E( f: t1、 ADC 可由 APB 时钟或 HSI16 时钟提供。
3 ]% c+ G& k: h+ u, t' [2、 ADC 转换时间: 12 位分辨率对应的转换时间为 0.87 µs (1.14 MHz), 10 位分辨率
$ [, o" U: o; F3 D# c: C对应的转换时间为 0.81 µs,若降低分辨率,可进一步缩短转换时间。
- n8 \6 u/ J# t9 h
. ~5 \( f6 U$ Q/ J8 w四、实验步骤4 H( [3 K) Q7 S( t! n/ b- Z
1、系统时钟配置# E* L+ u7 V% [7 Z# G* v' L8 S' j
/ d3 {! a ?2 l4 i, i, O4 ?, O l
- //****************************************************************************** " a7 h8 U9 u6 z% V8 S. p
- //name: SystemClock_Config + u' o5 X2 _! V
- //introduce: 系统时钟配置
0 Z; g8 c: k- K6 w' J2 Z0 J4 h. r0 g - //parameter: none
* P. L8 @2 g; u- s - //return: none
X( i+ X v8 P3 ~
: f# P9 M" r3 [* G- //changetime: 2019.05.21
# r: W, S& A" X d: ^" | - //******************************************************************************
^. w. H+ w& f. Q - void SystemClock_Config(void)
9 l5 R( n0 s/ [6 d2 y - {' O% B M; L" ?6 Z* r' ~& P0 H
- % j! v% }, j2 L. e' `
- RCC_ClkInitTypeDef RCC_ClkInitStruct;
+ v j( ]+ b2 T( L! H* [# {9 X( j - RCC_PeriphCLKInitTypeDef PeriphClkInit;
- V% l/ Z% Q: T( N6 Q3 d - RCC_OscInitTypeDef RCC_OscInitStruct;: o& V; {6 ]9 T7 w6 c1 l
% I6 g' I$ u$ {9 F8 C3 a- __PWR_CLK_ENABLE();/ h" f3 D7 S ~0 F6 X: n
9 w, J, ?1 B0 F; p; H- __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);' q8 k+ i3 ] U; _
9 V6 p x$ I* f# G- RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI|RCC_OSCILLATORTYPE_HSE;
?2 D5 u4 R8 e - * p) v9 b1 t" @- H1 E B6 z6 Z4 ?8 A0 y# J
- RCC_OscInitStruct.HSEState = RCC_HSE_ON;
" F0 c7 ] j/ o2 r( M, S4 j5 x - RCC_OscInitStruct.HSIState = RCC_HSI_ON; //ADC的时钟源
% h. j; p* L+ g - RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
) s4 m5 m$ \" d - RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;3 h; u! z% k% Q. t6 {9 z$ U
- RCC_OscInitStruct.PLL.PLLMUL = RCC_PLLMUL_8;! L( L6 ?) B8 q, M
- RCC_OscInitStruct.PLL.PLLDIV = RCC_PLLDIV_2;0 [4 e- g9 F% h( _* a& _% ?
- HAL_RCC_OscConfig(&RCC_OscInitStruct);
: @( {# R! ^3 c" T9 S, d
' D) q& F* N% d- RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK' X! l" S. p, u
- |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;* m- Y" S7 T) F, ^' n1 X. u
- RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;5 x1 @( ~2 ?8 y- [. b" _/ V
- RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
8 [% g% w/ x2 K% ?6 w - RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
' ~( D( ?( j! j4 g5 I$ u - RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;& `; E( S) H8 A
- HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1);. { e, H8 j" ?4 d4 O, a1 ^4 ?
. @3 H# P5 ?/ @% y- PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART1; Q1 v9 ]3 k3 E( B, K
- PeriphClkInit.Usart1ClockSelection = RCC_USART1CLKSOURCE_PCLK2;3 K. g. J: q& J& \0 ]5 x4 i
- HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit);
1 y6 U% t# L2 O
! p# C1 t o4 n- __SYSCFG_CLK_ENABLE();
$ O. e* S) F. F4 {7 O
! t, Y+ D7 w& ^ S) k4 Z0 S" y0 B2 ~1 Q% W- }
复制代码 ( A+ ?; @5 s% ?& y, {: j- O0 Y
注意:一开始程序中没有配置HSI时钟,采集不到电压
# Z# L2 c& T3 j# Y7 y2 B( Z m4 w6 _# ~* @+ N
2、ADC文件
5 _4 e, f0 d E+ }& U4 |& M# J
; B: F* j! i1 [/ m% W- #include "main.h"
: P- Z Z& l3 K) x& n9 T
$ {; u% V9 N: Q9 J: c" s: g! Z- ADC_HandleTypeDef hadc;' f V6 @/ c0 b! y9 U. a
- GPIO_InitTypeDef GPIO_InitStruct;
2 Z) z$ k5 M; E# u* l - ADC_ChannelConfTypeDef sConfig;$ V+ [- d3 Y: E5 v) h ?5 `
- . c$ [, J' P& n! W7 _1 t% @
- 6 L* r4 c: t/ J8 n+ p5 i. X
- //******************************************************************************
/ O2 u0 B" \8 w- W) Q4 h - //name: ADC_Init
, _3 Y) {# P& M& P0 Q8 I - //introduce: ADC初始化
; F- \$ ? A* k/ ~6 a, T. d# Z - //parameter: none % B1 I7 x: x0 ]3 _) _1 T
- //return: none ) u% F3 k7 Q- A7 [
- 3 B; I* Y; x. B( R
- //changetime: 2019.05.21 : ~5 T* W8 I2 Z
- //******************************************************************************
" e% G2 l& j9 v7 _' ` - void ADC_Init(void)4 g" U. h( S4 ~
- {# W- S' J3 g' x% `; o9 F' Y
- uint32_t Calibration=0;: o6 D8 Q9 l, ]+ g
- 0 D8 Y& ^$ F/ e# k6 ?' h5 w$ \+ z% K
- __HAL_RCC_ADC1_CLK_ENABLE();* P: Y3 Y' o+ o4 B! D
- __HAL_RCC_GPIOB_CLK_ENABLE();
; u; T& E# `' j" g - 9 @: n1 P* x/ `8 T) O. b
- GPIO_InitStruct.Pin = GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3;9 K- V* s" t8 a" C
- GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
( f3 R4 V6 ~* z2 e: n - GPIO_InitStruct.Pull = GPIO_NOPULL;
/ B) q6 C k1 u! j - HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);! ?1 d3 Y. x q# C
-
- Y; k2 E! _. c- G - hadc.Instance = ADC1;
+ z/ l' n" N) u4 y% J - hadc.Init.OversamplingMode = DISABLE;" g/ m' V% V* K$ D) p
- hadc.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV2;
* v5 i7 [' [& h4 U - hadc.Init.Resolution = ADC_RESOLUTION_12B;
$ s6 L( Y0 p Y, R; u# }9 l+ i - hadc.Init.SamplingTime = ADC_SAMPLETIME_79CYCLES_5;
% t! @: X! h, ~ h - hadc.Init.ScanConvMode = ADC_SCAN_DIRECTION_FORWARD;' G& Z1 m+ ?+ ?; K% c4 F% G2 m
- hadc.Init.DataAlign = ADC_DATAALIGN_RIGHT;
6 C( ~/ R1 W4 w+ k% K4 c4 W* n/ M - hadc.Init.ContinuousConvMode = DISABLE;* p# u" e7 X7 K2 a/ o0 {- C* f
- hadc.Init.DiscontinuousConvMode = DISABLE;
( \" u& g8 T( v# | g - hadc.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
+ j: @$ E! c+ J' H - hadc.Init.ExternalTrigConv = ADC_SOFTWARE_START;
2 B$ v2 z2 |" n, b( j - hadc.Init.DMAContinuousRequests = DISABLE;
3 E; B/ j, V0 Q1 Z - hadc.Init.EOCSelection = ADC_EOC_SEQ_CONV;
: @/ m: _3 A# O# y# N0 W6 V1 M/ c - hadc.Init.Overrun = ADC_OVR_DATA_PRESERVED;) g: W& b8 `0 [
- hadc.Init.LowPowerAutoWait = DISABLE;
2 Z: G6 _# i5 y - hadc.Init.LowPowerFrequencyMode = DISABLE;
% N% X( B; ~/ E! D& d - hadc.Init.LowPowerAutoPowerOff = DISABLE;) n) L/ P" b4 ]2 O
- HAL_ADC_Init(&hadc) ;
# T! k! M2 F' ^5 ` l$ ]% Z5 b - 0 { V' ]& l q$ t
- //启动ADC校验功能# z0 f* j* u3 \. {4 p+ Y; N7 V
- HAL_ADCEx_Calibration_Start(&hadc,ADC_SINGLE_ENDED);
; a4 U) s4 Q* k/ ] e - //获取校验值
( |' d. X3 c* l5 o6 e - Calibration = HAL_ADC_GetValue(&hadc);
# I) p3 ^$ B, e9 D' U- b - ) v* M) V9 M9 O* ^+ ~ v! A
- // 清除之前通道
: j ?' m+ o+ E: ]; u3 w4 w+ W( u. @ - sConfig.Channel = ADC_CHANNEL_1|ADC_CHANNEL_2|ADC_CHANNEL_3;, j6 S3 n7 D0 O: J& P' A
- sConfig.Rank = ADC_RANK_NONE; // 清除通道属性
# S9 e, L# s) c% c4 Y - HAL_ADC_ConfigChannel(&hadc, &sConfig);: \( I, g! y" ~# K+ w) C5 Z
- 0 O/ l7 [- x: }2 }# L( e
- }7 Q4 H5 {/ G# v7 U! i+ i5 @
- 9 b) s1 f2 D1 |7 w
- //******************************************************************************
* p7 [5 G7 f: j - //name: GET_ADC
6 @. u" w( I" ?# [" b$ P/ F r2 K - //introduce: 单通道采集ADC的值
/ S4 X! \7 Q5 F ?1 x8 ~$ K+ T - //parameter: CH:ADC采集通道
0 [( F0 H& C Z" V - //return: ADC采集值 : [) T' Z6 q4 v F% Z1 _! {
- ! v) K9 b W% e! j4 I& f" t
- //changetime: 2019.05.21
1 H+ b- {* K% { u/ M - //******************************************************************************
4 C! F1 C# P& u; W - uint32_t GET_ADC(uint32_t CH)
# \5 e( H" U/ q; b4 m! s/ u( J - {& ?3 z" a+ Y# L, L0 a
- uint32_t adc_conv_var;
9 O: a# ^- f* l+ O - sConfig.Channel = CH;! ~8 S A4 q: n t8 u @' T
- sConfig.Rank = ADC_RANK_CHANNEL_NUMBER; // 设置通道2 D5 L: F& g: X/ }: m3 e& }
- HAL_ADC_ConfigChannel(&hadc, &sConfig);
+ d6 E& n7 S5 B3 J - * L' [* z1 u& P, p1 K' w
- // 启动转换
0 i) f! p1 d) w2 C) V0 S4 \* b# Q! h - HAL_ADC_Start(&hadc);0 Y8 p8 U/ r8 B3 t+ H
-
1 u, e! A0 A8 s9 P7 m( a& p - // 等待转换结束$ G9 b% e5 ^8 `4 V, B u8 }
- HAL_ADC_PollForConversion(&hadc,20);// 超时20ms* j8 E, @# Y% R B$ L
- 2 a$ K; p J* I! y. r M! d
- // 读取结果
. ~2 F' Y" M- T- s4 @* V - adc_conv_var = HAL_ADC_GetValue(&hadc);
+ W7 m7 O0 N: e, c3 C$ e9 [+ ] -
, |6 m+ ~* P. `6 R& N* y - // 清除通道) r1 i/ B5 H& N' w0 f5 y
- sConfig.Rank = ADC_RANK_NONE; // 清除通道
& `- \; h; X- k/ Y, D6 G. | - HAL_ADC_ConfigChannel(&hadc, &sConfig);
+ R4 g6 t( {% e) V - 5 P# i. v V4 g; D! F. h+ F
- return adc_conv_var;) b: j# W% ~% D5 ]1 s* f
- }
4 B* w. d8 N2 p+ B/ ]4 \
# B! q# y7 H+ i E! Q- //******************************************************************************
0 |( n% [2 U* o( n0 O3 z - //name: Get_Adc_Average
8 ~/ v9 C1 T/ ]' I' R - //introduce: 多次采集求平均值
& x0 `! z+ t- @5 @ - //parameter: CH:ADC采集通道
9 E3 v9 b/ z$ X. [ - //return: ADC采集值
; q/ d) ^& O6 W, h0 H r9 Q - 9 Z5 q* U* p0 D: {
- //changetime: 2019.05.21 & i! U$ S8 Z1 F% }: _+ q
- //******************************************************************************9 |9 E' \' y5 V6 ]: ?% e. s' f
# d4 G2 b: Q7 e. d0 p l* R- void Get_Adc_Average(uint32_t *ch,uint32_t *adcx,uint8_t times)
8 a6 T- N$ Y" y - {
4 q2 |9 J2 x0 r. c4 E/ q1 N6 x - uint32_t temp_val[9]={0};
+ A. F: O3 c" I7 Z2 | - uint8_t t,i;6 f9 ^. A5 |/ h' T5 J9 `
- for(t=0;t<times;t++)
. i- a- S' u' J - {+ y/ d! Y& N: s: R, E
- for(i=0;i<9;i++)
5 Q: J+ K- V p4 R4 @' s4 |9 Q- O) N - {
" f0 R l6 c6 u# ^+ o - temp_val<i style="font-style: italic;">+=GET_ADC(ch);3 E6 K3 g( B( t; w R. H& w
- </i> HAL_Delay(5);) t9 y0 q2 j: }) `( K
- }
& m* `! v! i0 l - & M; S9 _. W( |, m4 ?/ |
- }$ H0 x) p q2 [$ d
-
2 c9 K: Y3 k, |% e# D. Z- o1 r - for(i=0;i<9;i++)5 w0 V$ s8 `9 L$ Q3 f* O, m! N" [# Q
- {& k R; X4 j5 |) ^* O: P: d
- adcx = temp_val/times;
4 O( C) M! N* t& J6 X V6 w, } - }
6 `: B. N A( v% E( |* _ - {2 |! U" q$ M. d
- } , X* j$ N, X" D+ q* j i
复制代码
4 q! O. J1 g1 ~/ q% Z5 _8 @! H3、main中测试/ P) u9 w5 Y" L8 _
- while(1)
, I: _% p! j3 z. s+ D0 d! b - {
/ g) |4 I( r* d$ I% V* m1 ] - BATTER_VALUE = GET_ADC(ADC_CHANNEL_1);
6 k' s0 {: B0 y$ O+ W G) o - temp=(float)BATTER_VALUE*(3.3/4096)*2; 5 {6 R5 o2 ^% k* p( e+ I$ \7 T1 O
- printf("temp=%0.2f\r\n",temp);6 G+ F/ h: x, k9 D6 g3 \. l
- , {4 ^4 E* I/ I2 J" O7 ~( Y
- HAL_Delay(100);
, Y+ O4 w1 f- X, t2 R# S - }
复制代码 9 x$ v/ {7 a1 D% |9 m, u/ G) v
N( `% k8 |" m$ Q, @
四、实验结果
* q0 o& R2 z0 X) I+ R% ]5 d7 e: z% \/ i& w
由于ADC的精度是12bit(4096)、参考电压为3.3V,因此实际读出的电量值为BATTER_VALUE3.3/40962.
% ?; n' G4 u9 x) l" w( P0 K试验成功
$ L( [& F3 n' P! c0 O
) H; v& A. P; L; O& h W, i E
7 R8 E$ X+ \4 Z: `9 }# }- d
: ~/ }5 @1 ^, n' ]# X) J |