AD转换即模拟信号转换为数字信号,一般在单片机中模拟信号对应电压,通过ADC口将相应的电压转换为二进制的数字信号,从而推算出测得电压。下面我介绍下STM32中L0系列调用库函数来实现AD转换。: A3 t, X( N5 r! G- L3 b
5 X& y# {+ p! ^4 W 首先最基本的AD转换模式,即单次单通道检测,且不用到DMA。L0系列一共有19个AD口对应19个AD通道,其中16到18为检测内部模拟信号的通道。下面代码中用到是PA0即对应通道0,具体代码如下图:! n1 N+ v+ M0 V0 E6 Y2 x; f
' e7 L4 d" E# b7 v
- Adc_init()
, Q$ o" P3 A8 q1 j! O4 S - 9 M% { O- @6 B; P) r9 G
- {! f8 O2 p, R% {
- __HAL_RCC_ADC1_CLK_ENABLE();& R! L1 _, O; v5 M+ Q9 G2 Q0 h4 A
- AdcHandle.Instance = ADC1;
) f, r0 l2 y1 y- v& g4 n/ \- s
- e6 G3 ^8 c7 g1 p; G- AdcHandle.Init.OversamplingMode = DISABLE;4 I& p H* l `/ D
$ C K% M' J0 I7 i8 e. _6 \- w- AdcHandle.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV1;
0 Q* m; _$ d0 V4 `3 _5 X( | - AdcHandle.Init.LowPowerAutoPowerOff = DISABLE;
, w" f; c/ }# W/ W6 o$ T, E - AdcHandle.Init.LowPowerFrequencyMode = ENABLE;
' _( ~' N' N$ h& U$ U8 k - AdcHandle.Init.LowPowerAutoWait = DISABLE;+ j5 ?2 G7 E" k' t* {
- 6 s3 a! G$ ?' Y" C. e5 c7 t
- AdcHandle.Init.Resolution = ADC_RESOLUTION_12B;
. p( c+ G- S3 {1 f - AdcHandle.Init.SamplingTime = ADC_SAMPLETIME_7CYCLES_5;- W& _2 b# S( g. W% V0 _
- AdcHandle.Init.ScanConvMode = ADC_SCAN_DIRECTION_FORWARD;4 S4 A" l; Y1 H6 e: b
- AdcHandle.Init.DataAlign = ADC_DATAALIGN_RIGHT;
; \9 _9 r) S; l - AdcHandle.Init.ContinuousConvMode = ENABLE;
1 K) v# m6 G( P; A' B - AdcHandle.Init.DiscontinuousConvMode = DISABLE;! ?9 G8 T' U Z" ] Y, ^
- AdcHandle.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;' R8 G9 y# x% B6 ]( ^
- AdcHandle.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
! r2 h6 d" @9 k: S$ U t+ h - AdcHandle.Init.DMAContinuousRequests = DISABLE;9 H9 g( g% Y# F( j5 V; e& s3 P
- 3 x+ S5 G' X2 s2 {# D
- HAL_ADC_Init(&AdcHandle);9 e) S$ j8 c2 L" x5 ~
- HAL_ADCEx_Calibration_Start(&AdcHandle, ADC_SINGLE_ENDED);
6 U' q! ]8 i5 W1 `& x! y - , R* N" h% O' L9 \$ q
- }
% Z) v7 s& M" }, o$ q - 3 o; z U; ^$ b
- //配置ADC初始化4 S3 d, D' e8 K
- / k, u+ D! e4 [( q: g5 ]6 s
- void HAL_ADC_MspInit(ADC_HandleTypeDef *hadc)
. d0 R# k+ s# e ?$ P, l+ q - {2 b' k. E6 p$ y5 @! m5 a* M
- GPIO_InitTypeDef GPIO_InitStruct;/ i: d' P' F; O1 O' `) P: _
- # _3 z J7 X+ |! B. Z
- /*##-1- Enable peripherals and GPIO Clocks #################################*/ A; }3 W) Y$ F4 j
- /* Enable GPIO clock ****************************************/3 L4 @3 `! a" y
- __HAL_RCC_GPIOA_CLK_ENABLE();; I" v( ?+ `" j% a5 I% ~) C
- /* ADC1 Periph clock enable */% A- g+ f' r$ N3 D6 I
- __HAL_RCC_ADC1_CLK_ENABLE();
$ _4 i, x& W( w& [: N
0 z! v0 K3 B, [. u: ^: E8 g- /*##- 2- Configure peripheral GPIO #########################################*/
. w6 }5 g1 ]& a9 v) l - /* ADC3 Channel8 GPIO pin configuration */
1 h- s7 v* k# c* x& o2 P! X - GPIO_InitStruct.Pin = GPIO_PIN_0;
% Z& B3 p/ G: i3 K - GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
( t- K. |( p: C+ D% i' S' l }9 k - GPIO_InitStruct.Pull = GPIO_NOPULL;, F/ p, M' K" b( P/ ~1 x
- HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
* Y6 f% m; j$ z( b, N2 ^5 x - }
0 v3 @. V) D6 ?" [7 R' C- X
6 V: K. R2 ^# y- //初始化ADC引脚PA0,开启时钟3 r8 t0 R5 H& s
- 3 s8 J) p0 L. h# c
- void get_voltage(void)
0 o% o% B4 w, f9 V# u8 V K0 s9 P - {( x; c* O+ F" T1 [
- bsp_adc_init();
! I( L1 w# v2 N - HAL_ADCEx_EnableVREFINT();5 r. n. z% k" D t5 m+ j
- HAL_ADC_Stop(&AdcHandle);
0 E% ~9 W5 s7 [ - AdcHandle.Instance->CHSELR=0;0 t, A) a+ [! i5 b
- sConfig.Channel = ADC_CHANNEL_17; //通道17专门测内部电压值
( O) ?& D4 Z$ l2 G; |- u7 o - HAL_ADC_ConfigChannel(&AdcHandle, &sConfig);
% n- w1 H* c# { u% `" H - HAL_ADC_Start(&AdcHandle);
) z0 J( I& v* b% ` - HAL_ADC_PollForConversion(&AdcHandle, 10);
7 c3 s- e6 [3 I1 e - /* Check if the continous conversion of regular channel is finished */
: ^) @" A8 _ M1 } - if ((HAL_ADC_GetState(&AdcHandle) & HAL_ADC_STATE_REG_EOC) == HAL_ADC_STATE_REG_EOC)" g2 u* l) u5 `+ O3 V/ z
- {8 m* B% H2 `3 z; M& j
- /*##-6- Get the converted value of regular channel ########################*/$ q; }6 E# f8 L+ H$ P
- uwADCxConvertedValue = HAL_ADC_GetValue(&AdcHandle);2 }. M' T! W) [% V" l
- }0 H/ s" R7 y4 v4 V7 e% s
- 9 s3 d+ D* P- Z* H
- vdd_value=VREF_IN_VALUE*FULL_ADC_DIGTIL_VALUE/uwADCxConvertedValue; //内部电源电压/ R( _; Z# Z ?5 T: P' c- V
- HAL_ADCEx_DisableVREFINT();
8 C9 \3 A" V; k - HAL_ADC_Stop(&AdcHandle);0 u( Y6 a( @' v& b
- AdcHandle.Instance->CHSELR=0;% g/ l D0 s* m5 G# A
- sConfig.Channel = ADC_CHANNEL_0; //ADC0,去测外部PA0口接的电压
. u# U; m, w- j! o4 c& g/ S - HAL_ADC_ConfigChannel(&AdcHandle, &sConfig);) M& S6 m$ E- j9 M n
- HAL_ADC_Start(&AdcHandle);
) Q' A. f# U' H! k1 G) f* q - HAL_ADC_PollForConversion(&AdcHandle, 10);
0 @/ \% y8 o' t, S' x - /* Check if the continous conversion of regular channel is finished */6 c" t: Q3 ?3 U# q4 N( i
- if ((HAL_ADC_GetState(&AdcHandle) & HAL_ADC_STATE_REG_EOC) == HAL_ADC_STATE_REG_EOC)- E# H. z! E3 i E$ c2 F
- {& h+ g1 J m6 ]' m7 r& A Q
- /*##-6- Get the converted value of regular channel ########################*/
6 T( B: h- h0 n5 Q - uwADCxConvertedValue = HAL_ADC_GetValue(&AdcHandle);
' J6 |5 f+ g' M( m& H; ~ - }% i* T9 } d# I8 D4 a: S
- //直接获取的是二进制码,14位对应最大值4095,内部电压为vdd_value通过比例计算得到电压数值
, t+ T- v6 e8 \& R2 ?, f - temp_voltage=(float)uwADCxConvertedValue*vdd_value/4095;
- X4 i( w4 e: S+ w* W+ M A9 ^ - //得到浮点型电压值 是乘了1000倍的 ^1 v- m% b; Q+ F# E! e! h0 t4 U
- HAL_ADC_Stop(&AdcHandle);' j f: `* F. o3 e* f9 h
- //HAL_ADCEx_DisableVREFINT();) g4 x. l, X2 b1 E
- __HAL_RCC_ADC1_CLK_DISABLE();
: q9 X" I7 I, P - }$ J( }8 y: Z8 R+ ^: b, C* B" Q
- }
复制代码 ' [* @# b* o/ K& f, {
* H2 v3 c' z& E 以上ADC检测,相当于一次连续检测了两次,第一次为内部电压用的特地通道17,第二次检测的是外部电压对应硬件连接的PA0对应通道0
2 p/ N" i0 y: k$ K# A) t. j% [; o1 K2 u, ?. x
8 ~$ O. V* {' D |