AD转换即模拟信号转换为数字信号,一般在单片机中模拟信号对应电压,通过ADC口将相应的电压转换为二进制的数字信号,从而推算出测得电压。下面我介绍下STM32中L0系列调用库函数来实现AD转换。+ M$ s7 h; g( E, P* G- z# K
$ d' m2 e2 k# }1 X. I
首先最基本的AD转换模式,即单次单通道检测,且不用到DMA。L0系列一共有19个AD口对应19个AD通道,其中16到18为检测内部模拟信号的通道。下面代码中用到是PA0即对应通道0,具体代码如下图:: C# C x, x. {" j2 d' c2 f. e
# p+ M% z+ y' V - Adc_init()
8 U2 Z' G1 m R+ x# u6 n - 3 g" z3 S) ?/ r" H5 C5 a& e+ F
- {7 o9 R% z+ w3 x' F6 N# h
- __HAL_RCC_ADC1_CLK_ENABLE();
8 O2 B) ?0 l. J3 `/ B2 E& a( J - AdcHandle.Instance = ADC1;
* T' ?* U' K1 y - - b e$ W3 s$ @* p# B
- AdcHandle.Init.OversamplingMode = DISABLE;1 { _% e) Z& u( v- f6 P7 M4 M
" H7 J) N% I( G7 {: [; M2 Q. Z9 K- AdcHandle.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV1;8 J6 S7 o# N# d: f
- AdcHandle.Init.LowPowerAutoPowerOff = DISABLE;
. p; {$ M I( n1 } E+ ` o) d - AdcHandle.Init.LowPowerFrequencyMode = ENABLE;7 N2 @* e7 U6 H5 d! N0 O
- AdcHandle.Init.LowPowerAutoWait = DISABLE;, ^% x! S/ m' N$ E- Z
- Y( V2 v4 F; ~( @8 a1 x* A5 i! S
- AdcHandle.Init.Resolution = ADC_RESOLUTION_12B;2 S7 E: ]+ W# x' V& a
- AdcHandle.Init.SamplingTime = ADC_SAMPLETIME_7CYCLES_5;; S1 | [ D" f( I. O
- AdcHandle.Init.ScanConvMode = ADC_SCAN_DIRECTION_FORWARD;, D3 }5 c* G" V) \0 N) Q: i1 O4 W1 s9 D
- AdcHandle.Init.DataAlign = ADC_DATAALIGN_RIGHT;
: O" R0 \' H0 F3 V/ O - AdcHandle.Init.ContinuousConvMode = ENABLE;
' w" a A$ l/ B$ F* K5 o. [ - AdcHandle.Init.DiscontinuousConvMode = DISABLE;
$ i. F6 }4 w. s3 O - AdcHandle.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
1 a4 T) O# R Y% f) q# r5 P! H4 B# S - AdcHandle.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
/ v) @$ Y+ {" h4 `# |+ t - AdcHandle.Init.DMAContinuousRequests = DISABLE;* t% v E5 L& p8 a) R
- . P6 @! s1 f* Z, p
- HAL_ADC_Init(&AdcHandle);& f4 c& n; J8 h; Z) ~
- HAL_ADCEx_Calibration_Start(&AdcHandle, ADC_SINGLE_ENDED);
9 b( V7 h! X: v, X4 L
& P' S" Y5 o- t- u+ k4 S" J! l- }
. w/ I0 ^% e' P- I: O - 8 [% ^* Y) e$ p8 G2 S7 z) s
- //配置ADC初始化. C8 a8 B7 @- m2 ]# V
. S/ g% R, |8 s0 i2 h; Z9 W+ c; L. {- T- void HAL_ADC_MspInit(ADC_HandleTypeDef *hadc)
; q; x* @( e- Z. z - {6 t9 `" o; t. {
- GPIO_InitTypeDef GPIO_InitStruct;
4 Z* `( C' U" I
+ o" n- W: L2 R- L- x- /*##-1- Enable peripherals and GPIO Clocks #################################*/
$ [, R/ z1 N/ w$ }' R8 J1 G - /* Enable GPIO clock ****************************************/6 M9 R# U- W8 r
- __HAL_RCC_GPIOA_CLK_ENABLE();
+ P" q8 [5 O( ]6 H1 p' g - /* ADC1 Periph clock enable */! ~! n0 b! d- H8 G$ S/ X# v
- __HAL_RCC_ADC1_CLK_ENABLE();
9 j( p8 v2 v8 Y+ `" v( i% W, R - 7 u4 f# C7 D6 R2 s3 E" g& q
- /*##- 2- Configure peripheral GPIO #########################################*/
" h" _! M# s/ q6 A - /* ADC3 Channel8 GPIO pin configuration */
# {; z. O7 ]7 x2 ~ - GPIO_InitStruct.Pin = GPIO_PIN_0;) T5 P$ ?! f( D1 K9 ]6 B1 a# x6 [
- GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;* Q% p& c0 d7 ^/ p: s: L
- GPIO_InitStruct.Pull = GPIO_NOPULL;" a: p& O9 d0 P+ G3 I S% |4 C
- HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);1 R$ c. v' @* l* R
- }
" C* ]2 L, A! g - ; }. u& q, l. q# s+ Y/ P
- //初始化ADC引脚PA0,开启时钟
0 G# Z( ^- y6 h# i - % M- o/ }: M* t
- void get_voltage(void)
( r4 F4 z+ n. I @5 h$ q* { - {8 V0 U" O1 d f5 z7 c# M; [
- bsp_adc_init();% a2 u! T0 F! i( ?0 B
- HAL_ADCEx_EnableVREFINT();
; F, Z2 ]8 b( W( @+ l0 | - HAL_ADC_Stop(&AdcHandle);
) h- e; \. \. g( I7 N - AdcHandle.Instance->CHSELR=0;
( h# {3 Y& }7 C' }5 T0 b- D - sConfig.Channel = ADC_CHANNEL_17; //通道17专门测内部电压值
9 h: u w9 {. h h& p, p - HAL_ADC_ConfigChannel(&AdcHandle, &sConfig);: d% ?* G6 i4 k
- HAL_ADC_Start(&AdcHandle);
8 P) h( H, v/ k' i, T5 v# l) o - HAL_ADC_PollForConversion(&AdcHandle, 10); / _3 n5 E: x) ?8 J
- /* Check if the continous conversion of regular channel is finished */
7 _( B2 T2 P m) \/ _- ] - if ((HAL_ADC_GetState(&AdcHandle) & HAL_ADC_STATE_REG_EOC) == HAL_ADC_STATE_REG_EOC). R! U% Q2 c2 ]& {7 t: e/ F
- {
; ^/ I. [: s/ @1 s. p% J; S - /*##-6- Get the converted value of regular channel ########################*/
- h' b& q: m+ v8 R' S% n - uwADCxConvertedValue = HAL_ADC_GetValue(&AdcHandle);
% v' O8 i6 M( \- }' W - }
/ s& `2 j; F2 q3 e
9 ?* a" N d( |8 o+ d' c- vdd_value=VREF_IN_VALUE*FULL_ADC_DIGTIL_VALUE/uwADCxConvertedValue; //内部电源电压
$ C$ z8 A* N; J/ A6 o - HAL_ADCEx_DisableVREFINT();& J1 W1 c6 Q% m3 z, K1 E& z
- HAL_ADC_Stop(&AdcHandle);' W: t* L) O4 H5 {
- AdcHandle.Instance->CHSELR=0;; R# m9 w6 b% k" d
- sConfig.Channel = ADC_CHANNEL_0; //ADC0,去测外部PA0口接的电压; L4 x1 N9 r4 X4 h$ d" t
- HAL_ADC_ConfigChannel(&AdcHandle, &sConfig);
. ^" n$ ^9 @8 I# y - HAL_ADC_Start(&AdcHandle);
% D5 T/ X8 h: O7 F g: @9 t - HAL_ADC_PollForConversion(&AdcHandle, 10);
4 _. N. s9 G9 S, Y3 X - /* Check if the continous conversion of regular channel is finished */
: U0 L; R# z, w - if ((HAL_ADC_GetState(&AdcHandle) & HAL_ADC_STATE_REG_EOC) == HAL_ADC_STATE_REG_EOC)
: c- F }3 r! j! i$ w1 U - {
8 F2 l3 _1 [$ l- `$ G3 g( m7 `) n: N - /*##-6- Get the converted value of regular channel ########################*/
. Z N9 B6 E/ R2 f - uwADCxConvertedValue = HAL_ADC_GetValue(&AdcHandle);
' V7 h3 F2 v. _% [) F - } I0 h2 N) v7 ~- S
- //直接获取的是二进制码,14位对应最大值4095,内部电压为vdd_value通过比例计算得到电压数值6 p0 ^; K7 N2 D) ?# C( h
- temp_voltage=(float)uwADCxConvertedValue*vdd_value/4095;
" E' g9 A7 a5 i0 s X# l$ S - //得到浮点型电压值 是乘了1000倍的
" `4 z W. y" l6 o# D7 Z! \! Z2 H - HAL_ADC_Stop(&AdcHandle);! [5 @4 L8 p2 D& I8 X% [; P
- //HAL_ADCEx_DisableVREFINT();5 }0 n `" m1 A( l w3 J( N! A5 V
- __HAL_RCC_ADC1_CLK_DISABLE();
& ?* @ q# i) g5 L/ Y+ B6 |& J$ X - }
: p% r, s( K* R# r! S; H - }
复制代码 6 A# n+ k; ]5 ]5 E( d
: |! I* z X8 Q$ c 以上ADC检测,相当于一次连续检测了两次,第一次为内部电压用的特地通道17,第二次检测的是外部电压对应硬件连接的PA0对应通道0
6 b# V4 x& |: @( w. v
4 ^ j3 b5 J' M: S$ F
+ |7 h7 Q- S2 x' o! \- j; N0 C |