AD转换即模拟信号转换为数字信号,一般在单片机中模拟信号对应电压,通过ADC口将相应的电压转换为二进制的数字信号,从而推算出测得电压。下面我介绍下STM32中L0系列调用库函数来实现AD转换。
6 t2 O- N- c: y+ K/ Q% y- O$ F. \1 d+ \0 v& \
首先最基本的AD转换模式,即单次单通道检测,且不用到DMA。L0系列一共有19个AD口对应19个AD通道,其中16到18为检测内部模拟信号的通道。下面代码中用到是PA0即对应通道0,具体代码如下图:% H0 D( v& |3 C8 m( s6 s
( j9 k& R( Y( ~9 _" n c% C( K
- Adc_init()
7 H) H2 B: \: {$ {/ x - * ^' v m0 k" i$ P+ K$ `
- {& q# {+ T( k# f0 W( o' l; N* c
- __HAL_RCC_ADC1_CLK_ENABLE();& ~* V$ D/ a E7 W* K2 @5 N
- AdcHandle.Instance = ADC1;% X; D/ F% h# Y
- . d, T+ Y. P0 e/ X8 l3 [- t8 y
- AdcHandle.Init.OversamplingMode = DISABLE;0 e: i" j4 C# {1 y$ c
/ e/ G' P' Y s3 r0 S8 E- AdcHandle.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV1;1 y( @& k# U2 ^/ C! o
- AdcHandle.Init.LowPowerAutoPowerOff = DISABLE;# ~7 L# `3 h" e% g" d- r5 L g
- AdcHandle.Init.LowPowerFrequencyMode = ENABLE;* C3 g) T2 L: N! i! r+ u
- AdcHandle.Init.LowPowerAutoWait = DISABLE;) y A1 [% y1 O8 G5 P5 H. M
- $ U& d C7 D8 V& o. K
- AdcHandle.Init.Resolution = ADC_RESOLUTION_12B;' \( S" h+ c2 O$ T
- AdcHandle.Init.SamplingTime = ADC_SAMPLETIME_7CYCLES_5;
6 A4 p* x$ ^' a/ C/ t' U- \ - AdcHandle.Init.ScanConvMode = ADC_SCAN_DIRECTION_FORWARD;
7 p! D5 P: C- n7 E7 I - AdcHandle.Init.DataAlign = ADC_DATAALIGN_RIGHT;
8 ~0 q, P( l; G' @ - AdcHandle.Init.ContinuousConvMode = ENABLE;) l3 J8 r" }; M- `) D& ]
- AdcHandle.Init.DiscontinuousConvMode = DISABLE;: J* y* u8 [( \
- AdcHandle.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;; J! Q' U. t% }
- AdcHandle.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
D1 ~/ G. k( r( x, d - AdcHandle.Init.DMAContinuousRequests = DISABLE;
# e& q2 L3 | m: i$ c; I
' d) g5 N1 Y1 ]6 N& J- HAL_ADC_Init(&AdcHandle);1 v6 }" ~) s' B) M
- HAL_ADCEx_Calibration_Start(&AdcHandle, ADC_SINGLE_ENDED);6 R1 @/ ?! t; `' m
7 a& v9 K" A3 z; T- }
$ D& t" K0 g- y) q5 z2 T. ?% } - 4 l. k' R4 n# s; S- H& k; u2 n, s7 O
- //配置ADC初始化
8 C S2 E7 B2 l E* C - # q5 S0 t9 m- \$ E7 P
- void HAL_ADC_MspInit(ADC_HandleTypeDef *hadc)
' B& D2 p; e( d: f) c/ y4 Y - {
% r" x* {. x- _ X# ^( J, z - GPIO_InitTypeDef GPIO_InitStruct;
- M3 g2 ^1 ~' ?8 F3 Z7 N3 m - 6 r% j0 h/ r2 g( r
- /*##-1- Enable peripherals and GPIO Clocks #################################*/# J! P9 j* j+ I' ]) ?9 N6 S
- /* Enable GPIO clock ****************************************/
4 Y/ k' ]' j p2 H) O4 U - __HAL_RCC_GPIOA_CLK_ENABLE();% {; F7 T( L# _6 _
- /* ADC1 Periph clock enable */
: D" ^4 m) f2 T3 k. {4 u# O9 h6 A - __HAL_RCC_ADC1_CLK_ENABLE();
' y% g9 _) [& }
^* b* t6 v: p& k4 ^+ X% D( W- /*##- 2- Configure peripheral GPIO #########################################*/
7 @2 z* ^7 S: u$ W1 D) @ - /* ADC3 Channel8 GPIO pin configuration */
a; H, W2 C2 e) ^& | - GPIO_InitStruct.Pin = GPIO_PIN_0;
; o. [ l, {0 C, `1 k, Y! \% n - GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; u# B, g. N. F" ?5 F% U- \- o
- GPIO_InitStruct.Pull = GPIO_NOPULL;
, r* n" K( C$ h! Z - HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);7 J9 k; _$ t" U2 I# B( c
- }
" z. r0 r8 X- M
8 z. P, ~. N7 u }- //初始化ADC引脚PA0,开启时钟
; t5 f5 v5 Z2 L0 b3 A: r. K2 x& K
& @4 D$ m& e. O( S8 |3 {- void get_voltage(void)
# j) {3 i) T& ?, J+ N. T - {
6 i9 c; h: p- x& q - bsp_adc_init();2 `' [5 h1 w4 D9 Z$ s3 F& z
- HAL_ADCEx_EnableVREFINT();
) e! E7 j, B6 j5 l0 e - HAL_ADC_Stop(&AdcHandle);8 ?# T) ?/ l4 I3 D! {5 c
- AdcHandle.Instance->CHSELR=0;$ ?5 n# ^4 O- s$ w. m' U8 \9 g
- sConfig.Channel = ADC_CHANNEL_17; //通道17专门测内部电压值
+ B; W. I9 l! Y- L - HAL_ADC_ConfigChannel(&AdcHandle, &sConfig);0 `! {5 F- ]6 n! Z' G
- HAL_ADC_Start(&AdcHandle);
9 ?0 W9 O4 q8 V2 J; N% f+ b. z - HAL_ADC_PollForConversion(&AdcHandle, 10); ' e+ H; h% m- f+ ^5 T& f
- /* Check if the continous conversion of regular channel is finished */% S" }7 C9 D0 N
- if ((HAL_ADC_GetState(&AdcHandle) & HAL_ADC_STATE_REG_EOC) == HAL_ADC_STATE_REG_EOC)1 c# N# Y4 b4 |: Z& F5 I7 y9 c
- {
/ b3 N4 w0 x# T) n R - /*##-6- Get the converted value of regular channel ########################*/
' H2 o5 Y2 R* @ N9 p" d& s - uwADCxConvertedValue = HAL_ADC_GetValue(&AdcHandle);
9 z$ l+ B, }: y4 I' Z4 U9 r - }
- c' z' I9 c" p$ c# B* C - - ^$ B. d4 Z) `7 p
- vdd_value=VREF_IN_VALUE*FULL_ADC_DIGTIL_VALUE/uwADCxConvertedValue; //内部电源电压9 W$ u+ K' |/ W
- HAL_ADCEx_DisableVREFINT();
9 _" }7 z( U: c8 y+ j1 V - HAL_ADC_Stop(&AdcHandle);$ `0 x/ t; b Z7 \" I7 ~
- AdcHandle.Instance->CHSELR=0;
* o! X5 ^1 s) N) l - sConfig.Channel = ADC_CHANNEL_0; //ADC0,去测外部PA0口接的电压6 e7 W B% h2 e
- HAL_ADC_ConfigChannel(&AdcHandle, &sConfig);2 k! N& U- a. I/ N1 q
- HAL_ADC_Start(&AdcHandle);
( `- g6 l* ~( x - HAL_ADC_PollForConversion(&AdcHandle, 10); ' O! L7 i2 E; c8 F$ r4 n6 T3 w
- /* Check if the continous conversion of regular channel is finished */
. F( s0 V. h6 T$ c2 O - if ((HAL_ADC_GetState(&AdcHandle) & HAL_ADC_STATE_REG_EOC) == HAL_ADC_STATE_REG_EOC)1 J+ L) o% T3 i x: V, V
- {- k; r: b; u4 s/ G- q) S5 E% x+ }. a' K
- /*##-6- Get the converted value of regular channel ########################*/
: z# g# u$ T: w! F - uwADCxConvertedValue = HAL_ADC_GetValue(&AdcHandle);
. M' P3 {+ l8 P2 `/ V9 h. r( B1 X3 ` - }
7 n) i& d3 y2 m+ w1 C( S. |' c; q - //直接获取的是二进制码,14位对应最大值4095,内部电压为vdd_value通过比例计算得到电压数值' u* W# Y/ S+ S% x6 q8 l
- temp_voltage=(float)uwADCxConvertedValue*vdd_value/4095;, i$ [5 f4 M2 x8 O$ B+ V
- //得到浮点型电压值 是乘了1000倍的 8 Y$ J3 p$ }/ {% J
- HAL_ADC_Stop(&AdcHandle);
, F& Z$ K8 p" y- _2 |! y9 a0 I - //HAL_ADCEx_DisableVREFINT();1 j) L; Y# }% n5 C! F6 R
- __HAL_RCC_ADC1_CLK_DISABLE();
9 j; |/ b( n8 Z& q# {& K# S - }
, n5 u6 O2 L! ?% U - }
复制代码 5 x/ }' M; K) \' E6 n I4 r' I
3 }: r6 r; L. d% ]. W( g: m8 {
以上ADC检测,相当于一次连续检测了两次,第一次为内部电压用的特地通道17,第二次检测的是外部电压对应硬件连接的PA0对应通道03 {7 Q/ c- N. Y( w4 R
Y1 K3 E4 C( C0 q9 v
: T- a; E. U" }. h' H+ r; U J' T
|