基于HAL库,实现最简单ADC采集。# u# a; I/ Y. c2 z. D% w
第一步,使用CubeMX配置时钟。
: K! C1 e/ r2 u a2 z0 M4 W6 y8 |/ n- C( f: N2 C6 K- k6 }9 k7 J
' e" ^ C U% R7 U
; x9 C" m- i' S- S7 G1 w; ^ f! |
然后是adc的配置:. [8 c( Q3 F8 k4 ?, e
0 v# r/ g$ u, I
5 K6 D3 P, M% x1 P& ?- m( g& s) j
* E/ H! ~; e7 N5 H: ~, V* v
将,稍微修改一下风格,并手写头文件和源文件。: [, W3 b( ?6 J
# z6 F: `4 D/ q+ _
adc.h很简单,就不说了。1 f2 m1 i2 @3 K u- R' Y. P' E
- #ifndef __ADC_H
5 D6 p; U( j3 ?; E - #define __ADC_H" f5 K% M, L- m' a5 Y7 A+ }) Z( V
- #include "sys.h" S J, b" z6 ~6 C" u
- " M! J# r7 M# k
- void MY_ADC_Init(void); //ADC通道初始化
- m5 L' ^) w$ Z9 r& _- W, t& O" _' G - u16 Get_Adc(void); //获得某个通道值
: L) ~. ^% Q5 Z8 ^3 p - #endif
. G' {6 P! x2 F$ A9 a
复制代码 " b+ C3 C( e1 \( ?7 G
其中,MY_ADC_Init和HAL_ADC_MspInit的内容完全是根据CubeMX生成的代码写的,就改了一个变量名字。Get_Adc则简单了,当我们需要获取adc的值的时候,先HAL_ADC_Start启动ADC,然后HAL_ADC_PollForConversion等待转换完成,最后HAL_ADC_GetValue返回结果。
8 a$ t( k9 g- Q/ t- #include "adc.h"
* V" X# |' A' o1 a - #include "delay.h"
5 @3 {1 c7 a: R0 S) k# h
: _* M6 l0 L/ Q0 G
& L9 o5 Z6 ^. `( ]- ADC_HandleTypeDef ADC1_Handler; //ADC句柄
! X& N) w5 m2 G# p - ADC_ChannelConfTypeDef ADC1_ChanConf; //ADC通道配置句柄) i/ O9 ^* s% T2 X" l+ l% c% L
! f5 g- H) Q# o3 i! f! P4 c
: Z5 \- X% {2 h2 y- //初始化ADC
1 J3 z6 @3 ]% s. x; w& F - void MY_ADC_Init(void)/ f; W2 x, {; t k1 d; U8 \
- {
3 q! E/ D; N X! ]- U' o6 h1 { - ADC1_Handler.Instance = ADC1;, W' J* V' t; B6 ?/ d2 K# S2 y
- ADC1_Handler.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4; //4分频,ADCCLK=PCLK2/4=108/4=27MHZ2 y9 m9 T- }( s/ w. R/ P
- ADC1_Handler.Init.Resolution = ADC_RESOLUTION_12B; //12位模式
; k% `$ N$ X H# I - ADC1_Handler.Init.ScanConvMode = DISABLE; //非扫描模式- A Y: a! B9 V6 Z# R
- ADC1_Handler.Init.ContinuousConvMode = DISABLE; //关闭连续转换; g/ W0 k5 Y6 R5 }& q4 L
- ADC1_Handler.Init.DiscontinuousConvMode = DISABLE; //禁止不连续采样模式
- n. h/ d4 O! s/ G0 U& u - ADC1_Handler.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE; //使用软件触发
( X2 G4 R0 S! }4 l" i5 _& Z - ADC1_Handler.Init.ExternalTrigConv = ADC_SOFTWARE_START; //软件触发
1 E1 n; F3 f; B) F; Q6 y - ADC1_Handler.Init.DataAlign = ADC_DATAALIGN_RIGHT; //右对齐& x: |( N' s8 n1 I
- ADC1_Handler.Init.NbrOfConversion = 1; //1个转换在规则序列中 也就是只转换规则序列19 B' z5 a: a) F" O X
- ADC1_Handler.Init.NbrOfDiscConversion = 0; //不连续采样通道数为00 \1 G' `, y6 L5 ~9 ?/ _/ C2 P
- ADC1_Handler.Init.DMAContinuousRequests = DISABLE; //关闭DMA请求: F% F3 Z& S0 Z% g2 J* ?; U: O
- ADC1_Handler.Init.EOCSelection = DISABLE; //关闭EOC中断
4 ^8 L# K; s! w0 ^! G" Q - HAL_ADC_Init(&ADC1_Handler); //初始化( f0 i9 ^0 x1 W6 H" f9 Q2 S
. a6 b, m4 D# m+ n; u- ADC1_ChanConf.Channel = ADC_CHANNEL_5; //通道5 PA5! B6 w. [' P/ }. U7 k( t
- ADC1_ChanConf.Rank = 1; //1个序列0 ]$ E8 b2 y+ X9 [4 h. {. V* U
- ADC1_ChanConf.SamplingTime = ADC_SAMPLETIME_480CYCLES; //采样时间
& }3 Z5 F! s8 _& X1 o" p - ADC1_ChanConf.Offset = 0;
% T5 l1 B8 p7 q) W9 ~( C$ V" t2 P - HAL_ADC_ConfigChannel(&ADC1_Handler, &ADC1_ChanConf); //通道配置
# S1 W7 H6 ^$ r2 H7 R
! f5 m |% R: M- }5 e" v5 u( C: c5 I) A
- 0 l* _6 {! }9 G7 E
- //ADC底层驱动,引脚配置,时钟使能
/ Z1 V3 K- Z% R1 o; D3 H- _ - //此函数会被HAL_ADC_Init()调用/ C1 i4 U1 k8 H2 G4 R! \) q7 {
- //hadc:ADC句柄$ W$ D3 _1 U5 t/ \6 X1 B
- void HAL_ADC_MspInit(ADC_HandleTypeDef *hadc)
4 c O1 E7 W4 [' A6 k' ? - {! e- ]8 j5 L) @$ f
- GPIO_InitTypeDef GPIO_Initure;; v/ A* k2 [& N, {
- __HAL_RCC_ADC1_CLK_ENABLE(); //使能ADC1时钟9 {+ ]. h2 F. `1 R' Q
- __HAL_RCC_GPIOA_CLK_ENABLE(); //开启GPIOA时钟- V4 r6 e7 |, p5 a4 J$ x- ?
7 @( S. b2 N4 Q0 [ O' E! o- GPIO_Initure.Pin = GPIO_PIN_5; //PA5: P: H$ N0 h& V( `% X {3 n* I1 w# [
- GPIO_Initure.Mode = GPIO_MODE_ANALOG; //模拟2 D. t8 v5 V( j4 w7 g9 e
- GPIO_Initure.Pull = GPIO_NOPULL; //不带上下拉
. @. m+ N! z1 u# g; ^& W2 m - HAL_GPIO_Init(GPIOA, &GPIO_Initure);
. t/ ^+ B% b: I1 x3 g - }% m* V: ]/ R& T+ T3 l
- . ?2 L q ~# b8 l3 H, B9 x5 j( _
- //获得ADC值* x$ H; c9 w ~( n6 V
- //ch: 通道值 0~16,取值范围为:ADC_CHANNEL_0~ADC_CHANNEL_16+ }) _7 Z5 l S5 s
- //返回值:转换结果
s; |+ `: ^$ l( M - u16 Get_Adc()6 g }( v$ ^9 v, K6 _3 x
- {
4 E5 E8 ^" y# m% z. F - HAL_ADC_Start(&ADC1_Handler); //开启ADC
% B: [+ y; G& {* G - HAL_ADC_PollForConversion(&ADC1_Handler, 10); //轮询转换1 j- W6 E$ K; S
- return (u16)HAL_ADC_GetValue(&ADC1_Handler); //返回最近一次ADC1规则组的转换结果. C5 r l, }4 c" h, R
- }
) Y5 |, e1 ~! C" |7 x7 }8 S
复制代码 # d( B: d2 W8 G5 w/ E
main.c中,主函数初始化之后,直接读取adc的值,并打印。6 n' X# X$ X9 N6 b
- #include "sys.h"; [! v3 Z& a O% Z5 L
- #include "delay.h"
l R- c, {: J% T) q5 m - #include "usart.h"& `# i; U; R" D/ Q) p
- #include "adc.h"- z8 b8 f- C: y1 M3 X n3 K
- " Z |# m: t, ]+ C% f: \6 R
- int main(void)
7 O3 ^3 [: ]+ ^2 ~6 h! {1 l - {: Q4 f% \9 S5 w, `2 G
- u16 adcx;
/ ?# `$ W- R) D& e. J3 J7 t2 T - Cache_Enable(); //打开L1-Cache
: b/ u [3 P' s' [ - HAL_Init(); //初始化HAL库
3 n, O- T- S2 c+ t/ G/ R: T - Stm32_Clock_Init(432, 8, 2, 9); //设置时钟,216Mhz
( Y+ \0 O- W) A9 z9 K - delay_init(216); //延时初始化0 T3 G$ }' K8 J9 F( }
- uart_init(115200); //串口初始化! ~. p" K0 t2 S4 a/ J$ v
- MY_ADC_Init(); //初始化ADC1通道5
6 v& D9 L' o5 }# H( x, Y% k - # u# F7 _" c* m d
- while (1)9 v5 z8 b7 }1 e' z; r
- {0 b% {8 O: C; F f+ o* ]
- adcx = Get_Adc(); //获取通道5的转换值,20次取平均
+ H8 l6 E/ Y% }& l* Z _7 ^, L. t - printf("%d\r\n", adcx);: u) ?) y" U. @4 X! O
- delay_ms(250);
|; B: a: D1 T a, } - }
. y5 G( e+ `% D: d) Q - }: H& \$ R1 u7 V, L4 ]+ `
复制代码 " c: K: t; J& Y- Y w
如果需要对多个通道进行轮询读取,可以稍微修改一下函数Get_Adc,在每次读取之前设置一下需要转换的通道:; C8 `& _* ^! }: ]4 H6 N" n7 M
- //获得ADC值. v5 c. y H/ s$ @) B8 \
- //ch: 通道值 0~16,取值范围为:ADC_CHANNEL_0~ADC_CHANNEL_16
6 q2 J4 F6 C; W - //返回值:转换结果4 ?0 Z2 N" i8 }0 d( u
- u16 Get_Adc(u32 ch) 5 i- l- S7 D- ]2 K
- {
1 z" V, b/ T; P- ]: V, ?+ } - ADC_ChannelConfTypeDef ADC1_ChanConf;
1 s, D+ d1 J. X! Z) f @$ f - % A; X9 k3 w/ L
- ADC1_ChanConf.Channel=ch; //通道7 c; ]3 k/ r8 Y c; ?4 D
- ADC1_ChanConf.Rank=1; //1个序列. z' W9 b' O) S' M, o5 }
- ADC1_ChanConf.SamplingTime=ADC_SAMPLETIME_480CYCLES; //采样时间1 V. a8 _+ y- C' Y- }2 ~' m% n
- ADC1_ChanConf.Offset=0; / w5 ]0 h+ F4 m
- HAL_ADC_ConfigChannel(&ADC1_Handler,&ADC1_ChanConf); //通道配置4 l- ]. d8 E3 g0 Y
- # m' ], z9 {! m5 z
- HAL_ADC_Start(&ADC1_Handler); //开启ADC
2 g0 D2 B5 M) a8 a* X9 e -
& l8 M8 `6 V; ^+ H - HAL_ADC_PollForConversion(&ADC1_Handler,10); //轮询转换! u Y G: _7 \( n
-
& [2 ^' ^; w) v8 j2 M. g) g4 ^ - return (u16)HAL_ADC_GetValue(&ADC1_Handler); //返回最近一次ADC1规则组的转换结果
7 S; R2 ]' x) J/ F7 a$ p; @! } - }
复制代码 ————————————————
$ V& Z" r* }: ~+ R" Q版权声明:小盼你最萌哒- L! |9 r$ J$ J* z0 W$ @3 u
如有侵权请联系删除
( B/ E5 y3 p8 A+ U
! t' F" T0 F3 _& T/ J! x3 Y
3 `, N/ C% w ^; j6 \; G# | |