基于HAL库,实现最简单ADC采集。: v8 T, y9 ^0 w4 D6 X) ^
第一步,使用CubeMX配置时钟。! r1 }, U: w$ P' `+ ]; `
5 d% z9 ~$ X7 Y2 D
7 u! {. p% Q+ ~: I3 x; G3 ~3 j
然后是adc的配置:
( ?/ y5 V& D+ c
7 a* v9 l0 U% u+ F& }
% A; N4 H. \% r7 T" ]: w
6 T1 J6 q d) N; i8 C$ U/ T将,稍微修改一下风格,并手写头文件和源文件。
' l* I4 q# i( h$ }
4 U- ^3 Z6 ^, w5 u* J0 {1 T6 kadc.h很简单,就不说了。, L/ S& D" s5 Y$ e: k5 }
) K _& z- a2 l0 S8 N2 {3 p
- #ifndef __ADC_H
# {8 B0 p- F/ h2 s7 c - #define __ADC_H
# `: V+ O5 C. ^ - #include "sys.h"4 V7 }" R3 G' I9 b
- p0 G/ Z5 [& E$ X F
- void MY_ADC_Init(void); //ADC通道初始化
6 L. H$ O# |/ e* @. { - u16 Get_Adc(void); //获得某个通道值 k2 A) E& ]5 I9 c2 S" c! ^* ?
- #endif
复制代码
4 x7 f. Y9 j N7 n' ~/ ]6 S: P其中,MY_ADC_Init和HAL_ADC_MspInit的内容完全是根据CubeMX生成的代码写的,就改了一个变量名字。Get_Adc则简单了,当我们需要获取adc的值的时候,先HAL_ADC_Start启动ADC,然后HAL_ADC_PollForConversion等待转换完成,最后HAL_ADC_GetValue返回结果。
, [: m0 ]7 x; S. ?# ]+ f
# p% H2 }2 y# r- q2 `9 H% v- #include "adc.h", Y; f2 x4 q4 [' h9 |1 f# r
- #include "delay.h"
! Z( D/ f. k% B" G# c
! P. o6 k0 @- m# C) I* d- # t; }( c8 [' @0 w
- ADC_HandleTypeDef ADC1_Handler; //ADC句柄
, P' V& w& v3 ?! Y - ADC_ChannelConfTypeDef ADC1_ChanConf; //ADC通道配置句柄3 i+ L2 } h, Z/ l; s) t( d
- ; Y( p- W& [& [# E" G
- 1 c. j) Z& T G" m6 ^
- //初始化ADC" c* c5 p) X! l0 I' i
- void MY_ADC_Init(void)
2 g1 j( O8 d8 J - {
" U% _. T. e4 H: d" P! w - ADC1_Handler.Instance = ADC1;" Y, c9 L$ }, `6 M
- ADC1_Handler.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4; //4分频,ADCCLK=PCLK2/4=108/4=27MHZ) g# j1 O# v; u: V! z3 K
- ADC1_Handler.Init.Resolution = ADC_RESOLUTION_12B; //12位模式3 R- v1 ^/ t8 P9 P" p, X
- ADC1_Handler.Init.ScanConvMode = DISABLE; //非扫描模式
+ R* A' z% k. A3 A* a9 i3 u - ADC1_Handler.Init.ContinuousConvMode = DISABLE; //关闭连续转换/ J# Q3 }' `0 j& x. V
- ADC1_Handler.Init.DiscontinuousConvMode = DISABLE; //禁止不连续采样模式- X" |+ O) n) `( T- k8 ^
- ADC1_Handler.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE; //使用软件触发; }2 Y' _9 T2 z9 u; o* D' R
- ADC1_Handler.Init.ExternalTrigConv = ADC_SOFTWARE_START; //软件触发* n# T5 q" s% Z
- ADC1_Handler.Init.DataAlign = ADC_DATAALIGN_RIGHT; //右对齐9 L7 W `, G' o! c1 M8 M$ R
- ADC1_Handler.Init.NbrOfConversion = 1; //1个转换在规则序列中 也就是只转换规则序列1
+ H1 \1 ~. m" B9 A( N# e - ADC1_Handler.Init.NbrOfDiscConversion = 0; //不连续采样通道数为0
* o3 r: Z, |! X - ADC1_Handler.Init.DMAContinuousRequests = DISABLE; //关闭DMA请求
5 l3 R3 z( H! V7 \# } - ADC1_Handler.Init.EOCSelection = DISABLE; //关闭EOC中断, q, a' b& u" `
- HAL_ADC_Init(&ADC1_Handler); //初始化
( j( K) u! v9 o; q9 q) c5 H - + o0 A6 V9 V3 U( J8 n
- ADC1_ChanConf.Channel = ADC_CHANNEL_5; //通道5 PA58 P; z5 b0 ]1 U6 G" b$ h6 s) V
- ADC1_ChanConf.Rank = 1; //1个序列0 o, ]( K( c+ ]3 I, z
- ADC1_ChanConf.SamplingTime = ADC_SAMPLETIME_480CYCLES; //采样时间$ j, J9 _6 S# ]* m9 @2 J& I# [. _2 h2 Q
- ADC1_ChanConf.Offset = 0;. v+ e3 A; E# j; K
- HAL_ADC_ConfigChannel(&ADC1_Handler, &ADC1_ChanConf); //通道配置
! S" d/ x! D. B/ Z" ~. P3 B& k
- i1 g# u* j% D$ ]. V- }
1 s0 x1 U: G* B9 x# X; N; P
/ n4 P* x6 F8 k$ H9 s5 b& E- //ADC底层驱动,引脚配置,时钟使能; b: i0 ~" z6 H8 f
- //此函数会被HAL_ADC_Init()调用
9 ]1 e U% l0 e* } - //hadc:ADC句柄
& L' u7 `8 ?# K( m6 ? - void HAL_ADC_MspInit(ADC_HandleTypeDef *hadc)
, R% v1 _* o! O( j9 [ - {
- f3 E/ ^! }4 @; H/ u0 [ ?3 a! S! V - GPIO_InitTypeDef GPIO_Initure;
" B$ v9 j- J8 z- Y# q - __HAL_RCC_ADC1_CLK_ENABLE(); //使能ADC1时钟
S8 H4 a! P4 `5 z - __HAL_RCC_GPIOA_CLK_ENABLE(); //开启GPIOA时钟
) x( P7 f! ]' t# e3 a0 @; h- \9 Y - " Y) }; {/ p6 D. Q
- GPIO_Initure.Pin = GPIO_PIN_5; //PA5
3 Q6 x' K; ~" y& Q - GPIO_Initure.Mode = GPIO_MODE_ANALOG; //模拟
+ ?( M% v R4 ~# a4 N - GPIO_Initure.Pull = GPIO_NOPULL; //不带上下拉
$ D$ z' u4 s8 b$ V. @ - HAL_GPIO_Init(GPIOA, &GPIO_Initure);
! G+ S9 p0 k2 H# _7 b$ n, ]7 m - }
) t7 ]6 P3 D4 i' ?/ `$ \
5 ~6 o3 Q" r! D0 ?- //获得ADC值# l. b+ k+ |( T' }$ O
- //ch: 通道值 0~16,取值范围为:ADC_CHANNEL_0~ADC_CHANNEL_16& W6 r5 T* B7 c3 \
- //返回值:转换结果
. Q6 [" U$ U2 q1 S - u16 Get_Adc()* z# u- z: `, Q3 I; R) [" Y A1 r
- {
' p! \) k0 q0 z+ k/ K# ^ - HAL_ADC_Start(&ADC1_Handler); //开启ADC. G" @. Z, e p
- HAL_ADC_PollForConversion(&ADC1_Handler, 10); //轮询转换
# ]6 z& m( A; E- F1 n+ m: s - return (u16)HAL_ADC_GetValue(&ADC1_Handler); //返回最近一次ADC1规则组的转换结果
) V; y6 L0 \2 m* v" S. j) w" s - }
复制代码
4 o1 j/ t9 d- M( n. W; }! a* }main.c中,主函数初始化之后,直接读取adc的值,并打印。1 y" V% h* _7 Q5 E
1 `+ `) Y# N: D' G- t# t- #include "sys.h"; s2 G7 L0 j6 z, L5 p
- #include "delay.h"
1 z. \/ N( m: U/ a7 [6 b - #include "usart.h"
# S2 p7 x" f. V, _- D& O - #include "adc.h"! ~ R Q u0 l' [8 m. r, Y; f
- ' m! i; G: a7 W) N- p
- int main(void)$ l) v+ K/ h' w- a) Y! q# k9 W
- {9 Y! m2 |7 L( R& x8 H
- u16 adcx;( q/ Q& v3 W% k1 `. X
- Cache_Enable(); //打开L1-Cache% P, E" K) U1 R3 t
- HAL_Init(); //初始化HAL库
1 Y" m" K$ E& S0 D% l - Stm32_Clock_Init(432, 8, 2, 9); //设置时钟,216Mhz
^3 v4 {5 r+ W$ }# C - delay_init(216); //延时初始化
6 A$ y. v7 X. J. J% D3 G3 b, Y - uart_init(115200); //串口初始化
+ o' Q- c( F! O& r% p4 T - MY_ADC_Init(); //初始化ADC1通道54 C- C. b4 Y0 e: b. U3 Y
-
E$ Y( z3 S) m0 K - while (1), {3 B7 ~% C+ \9 k2 w" c7 }8 E
- {5 k) I4 ~9 v" i4 P/ l3 A+ ?
- adcx = Get_Adc(); //获取通道5的转换值,20次取平均
. T N6 _. ]' _1 L2 B - printf("%d\r\n", adcx);7 l8 r+ H H. `7 H
- delay_ms(250);& w' I+ ]+ Z( d' m3 z' U) L+ C
- }
2 Y. }: X6 N2 V/ w/ I1 s4 k - }
复制代码
& t( d$ L. l/ T& c# H如果需要对多个通道进行轮询读取,可以稍微修改一下函数Get_Adc,在每次读取之前设置一下需要转换的通道:
4 T( x; D; E( p9 E% W* Y( j; j" v( K& N* W/ p+ t. w
- //获得ADC值
; u0 k' t" L. \; D! n; } - //ch: 通道值 0~16,取值范围为:ADC_CHANNEL_0~ADC_CHANNEL_16
# }+ J; |: y) b* }9 N( n - //返回值:转换结果4 o5 j [5 V* i! o3 y t( \
- u16 Get_Adc(u32 ch)
3 b/ [5 f3 K, } K% S - {
- r1 b1 q2 O _ - ADC_ChannelConfTypeDef ADC1_ChanConf;
! X, w: i# Q2 k' _
8 I! x, [1 |; B: |8 z; m9 p( b# r- ADC1_ChanConf.Channel=ch; //通道) @- n1 y( D$ G& i' n3 l
- ADC1_ChanConf.Rank=1; //1个序列4 ^' R `# s: r
- ADC1_ChanConf.SamplingTime=ADC_SAMPLETIME_480CYCLES; //采样时间
+ C7 E7 p" m1 i% g" j; P - ADC1_ChanConf.Offset=0;
& B0 j+ h. @) C( s; S- _ r - HAL_ADC_ConfigChannel(&ADC1_Handler,&ADC1_ChanConf); //通道配置
9 F0 b! |1 b) c3 X/ v -
) Q) Z6 x- j8 D( { - HAL_ADC_Start(&ADC1_Handler); //开启ADC+ {! N# Y' {' n+ c
- / X, v; t. D$ O0 U! a/ s: d
- HAL_ADC_PollForConversion(&ADC1_Handler,10); //轮询转换' k3 S# [1 Q$ ?1 I
. v/ p( B( z+ v7 ]; ^- return (u16)HAL_ADC_GetValue(&ADC1_Handler); //返回最近一次ADC1规则组的转换结果
' a) S0 w6 D( j' w - }) N, a/ {, O7 U7 R* S
复制代码 3 i* p: P2 o" A( q& M& g& ]7 _
# X, K2 m/ }! h+ F$ |% A7 W3 n! K5 l d
|