基于HAL库,实现最简单ADC采集。
: a- X* ~4 w1 o' M) X2 H# t8 }第一步,使用CubeMX配置时钟。. ]* B8 c$ j5 w: a8 c+ n- Y
! ?, [/ U& W' I- l$ @/ r( a( N
* z; a7 E2 D2 s" T
/ b7 O! I. W- Q& R! o! F3 Q. _然后是adc的配置:
6 t1 \& Z( f, L( l( U( m4 ^2 u
8 c/ s" a ]8 c3 I1 ~
( p0 d+ N/ h G' Q; U* _6 s* |6 m+ {9 r/ N# r4 k
将,稍微修改一下风格,并手写头文件和源文件。
6 {7 j1 d9 F/ t7 T3 f" y- M) {9 S/ u2 C8 Y8 C# n- F( _; ^
adc.h很简单,就不说了。
$ ? r# o! B( A3 {% `. k% N- #ifndef __ADC_H
4 ~5 t) q9 j, a8 @" B - #define __ADC_H" u" m" R" ~8 V& \% A, @3 U4 @
- #include "sys.h" Z4 o& G" k, _' j* ]3 W9 R- W" f( a
- & ?2 S9 a% Y/ ]; g8 _- p
- void MY_ADC_Init(void); //ADC通道初始化
# O g X" J. b# h% A" r5 u+ ? - u16 Get_Adc(void); //获得某个通道值
0 }$ A7 v) n, ?; I1 B. O1 } - #endif # l- l' ~0 ~1 [
复制代码
) E1 r. V6 Q- M, }) s Z其中,MY_ADC_Init和HAL_ADC_MspInit的内容完全是根据CubeMX生成的代码写的,就改了一个变量名字。Get_Adc则简单了,当我们需要获取adc的值的时候,先HAL_ADC_Start启动ADC,然后HAL_ADC_PollForConversion等待转换完成,最后HAL_ADC_GetValue返回结果。7 T# w) ?3 E) N
- #include "adc.h"
8 [5 j p2 h" S5 y - #include "delay.h"
3 Y( p. n* ^: u9 C
1 L+ e9 {' L+ @! t% [; I. W
t- O v$ c9 _# I7 @/ P& w* K- ADC_HandleTypeDef ADC1_Handler; //ADC句柄
: L. @9 {% r" Y" y! Y - ADC_ChannelConfTypeDef ADC1_ChanConf; //ADC通道配置句柄" _4 ?& h9 n; E0 J# A$ d
, Q$ L( D+ V C2 d1 L
6 ]% r. X& X# V/ ]- //初始化ADC
) H% f7 {. r2 P1 U - void MY_ADC_Init(void)
! L4 q4 O: J5 Y+ b5 T - {
6 \! N" Q& `9 p" h& Y - ADC1_Handler.Instance = ADC1;% l+ L9 L5 X8 o& w
- ADC1_Handler.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4; //4分频,ADCCLK=PCLK2/4=108/4=27MHZ
g {7 M" e( ~* ^1 g: t - ADC1_Handler.Init.Resolution = ADC_RESOLUTION_12B; //12位模式
6 T% S V6 Y% Z) C, i: k% y+ P - ADC1_Handler.Init.ScanConvMode = DISABLE; //非扫描模式6 ~8 g7 m A. F3 s
- ADC1_Handler.Init.ContinuousConvMode = DISABLE; //关闭连续转换
6 j+ t, L3 f8 O5 R; R, t! ]) D - ADC1_Handler.Init.DiscontinuousConvMode = DISABLE; //禁止不连续采样模式
3 D7 d" F/ P) M - ADC1_Handler.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE; //使用软件触发) M4 X$ b+ o- a! h# Y( Z' c
- ADC1_Handler.Init.ExternalTrigConv = ADC_SOFTWARE_START; //软件触发5 c, r8 [# S3 J) C* k! P T
- ADC1_Handler.Init.DataAlign = ADC_DATAALIGN_RIGHT; //右对齐
4 u( o5 d; A9 L- S; d+ V$ q- Z8 B: J - ADC1_Handler.Init.NbrOfConversion = 1; //1个转换在规则序列中 也就是只转换规则序列1
4 K" r3 N8 r) u& c - ADC1_Handler.Init.NbrOfDiscConversion = 0; //不连续采样通道数为0% E4 j$ Z: ?4 h+ p
- ADC1_Handler.Init.DMAContinuousRequests = DISABLE; //关闭DMA请求# u& f7 i1 z. ~9 O! q
- ADC1_Handler.Init.EOCSelection = DISABLE; //关闭EOC中断
& w0 S# p- G$ \ - HAL_ADC_Init(&ADC1_Handler); //初始化! X" t/ R% S, ]. H
- : m- J+ P" t( f5 ^( ~
- ADC1_ChanConf.Channel = ADC_CHANNEL_5; //通道5 PA5% P8 w; A# E& d1 M9 h
- ADC1_ChanConf.Rank = 1; //1个序列" V% [6 @( w9 ]) D9 v6 l+ F$ p
- ADC1_ChanConf.SamplingTime = ADC_SAMPLETIME_480CYCLES; //采样时间
1 P5 Q+ V* q l9 o, D. `: N9 c9 J6 p( D - ADC1_ChanConf.Offset = 0;
7 @# U7 z2 S( L( P b1 W4 ~2 @ - HAL_ADC_ConfigChannel(&ADC1_Handler, &ADC1_ChanConf); //通道配置
3 H1 ~3 J- u, O+ i* x7 T$ J, G# R
/ x. o% d# r' Y Z+ S- G) Z- }5 h/ w* w+ `' ?: t
- 5 c! k+ P2 k& j+ t: j0 H3 ?
- //ADC底层驱动,引脚配置,时钟使能; Z5 o% A( L/ Z$ ]) }& r- S
- //此函数会被HAL_ADC_Init()调用
" O J+ \6 U( l4 N - //hadc:ADC句柄; K; t1 E. ] o( f6 l) M. o2 U* f9 Q
- void HAL_ADC_MspInit(ADC_HandleTypeDef *hadc)% d) r. Z4 i0 d; Y
- {
3 Y; j) v: f4 j$ T8 T - GPIO_InitTypeDef GPIO_Initure;9 Q! ?7 F( I Q6 H: F
- __HAL_RCC_ADC1_CLK_ENABLE(); //使能ADC1时钟
' C9 G# w/ t) y% |7 }8 o - __HAL_RCC_GPIOA_CLK_ENABLE(); //开启GPIOA时钟
7 u4 a" v- @7 ]8 @9 K# e9 Z! b4 N6 @
0 `$ z& i' W3 A8 o$ L. n9 E [$ _- GPIO_Initure.Pin = GPIO_PIN_5; //PA5
) q) g) K, N+ A" n+ e - GPIO_Initure.Mode = GPIO_MODE_ANALOG; //模拟
* M6 R9 {+ q7 r - GPIO_Initure.Pull = GPIO_NOPULL; //不带上下拉, I0 ~/ u3 x% s
- HAL_GPIO_Init(GPIOA, &GPIO_Initure);
* g. ^. B; f/ l9 k% s - }
, U( T$ k( M( A" N8 E* H - * \/ E' O7 a* U
- //获得ADC值% f+ w4 m0 U k; T
- //ch: 通道值 0~16,取值范围为:ADC_CHANNEL_0~ADC_CHANNEL_16' R" g# R. ^) _/ ^( @. y
- //返回值:转换结果0 x; Y2 ?0 f" j8 a3 X2 @
- u16 Get_Adc()# S1 b. b m; L, N
- {
( v4 z$ R) c8 L. ]: S2 H - HAL_ADC_Start(&ADC1_Handler); //开启ADC/ f* E' V) x# [6 `. B
- HAL_ADC_PollForConversion(&ADC1_Handler, 10); //轮询转换9 ^% t, h) w8 Q6 U D
- return (u16)HAL_ADC_GetValue(&ADC1_Handler); //返回最近一次ADC1规则组的转换结果
. f2 p% l4 |2 ]9 _ - }
( F1 K# Z+ }6 {
复制代码 . m9 T" N6 {0 A5 N2 k
main.c中,主函数初始化之后,直接读取adc的值,并打印。
7 T9 v- y# C- i) Y* }( S! q- V( x- #include "sys.h" Y, k; A3 Z: x' z2 H' A k
- #include "delay.h"# a- k8 T) z, R' f3 ~1 p4 Q5 E
- #include "usart.h"8 U& Z9 z- M! E$ Q
- #include "adc.h"
4 T$ P% S9 w" V* X* U) x: F1 E
" x* l$ \: S, K4 j b; W: p- m- int main(void)6 ~) ~. r ^* l5 l3 L& Q2 `
- {, @. d# D( B/ P& `- Y. ~/ b0 v
- u16 adcx;8 c- U$ k) T% L1 I4 i( a: F- f
- Cache_Enable(); //打开L1-Cache6 E$ N7 ]) L' Z5 F& |4 X: ?2 U/ q
- HAL_Init(); //初始化HAL库4 v* ^# H" _9 Y$ M( M- e
- Stm32_Clock_Init(432, 8, 2, 9); //设置时钟,216Mhz
% e7 [0 ~& I4 R9 d# V - delay_init(216); //延时初始化# N: ?2 a9 R2 |' d
- uart_init(115200); //串口初始化' u6 A5 J3 s) ^/ `
- MY_ADC_Init(); //初始化ADC1通道5; R$ T7 b6 u0 E/ S2 L! r
- 3 f7 e" H2 u$ Q' Z. @% f5 W
- while (1)
; E+ K- E. o, q0 o - {" S/ m0 S, v! ^6 B- y \, H, w
- adcx = Get_Adc(); //获取通道5的转换值,20次取平均
( r' l3 S# [0 ^. C - printf("%d\r\n", adcx);. G! j2 ` _4 a& ?& }0 j4 y( r) C
- delay_ms(250);
; D. v) z$ D; I2 c, ^1 V; E; m& }6 T/ R - }5 k$ G& y8 v% q* A9 y
- }2 @/ z- }! s2 z
复制代码 5 K0 Q: N/ K9 i( Z: R
如果需要对多个通道进行轮询读取,可以稍微修改一下函数Get_Adc,在每次读取之前设置一下需要转换的通道:" j5 H& ~$ l5 }+ n( v# O
- //获得ADC值- F% Q8 Q$ E1 r1 _2 X% \! j% i
- //ch: 通道值 0~16,取值范围为:ADC_CHANNEL_0~ADC_CHANNEL_160 {! {2 p# w# F3 K0 t* a0 D/ P8 c' m
- //返回值:转换结果$ i" ^" o8 A4 K3 {9 k9 V; f
- u16 Get_Adc(u32 ch)
6 V1 O! S! C9 ^ - {& w1 y3 P2 Q5 J S0 Q
- ADC_ChannelConfTypeDef ADC1_ChanConf;
6 y* ?) J8 k' I% Q3 Z. Q -
) a6 e' \9 b+ V1 s8 P9 ~ - ADC1_ChanConf.Channel=ch; //通道! D0 x& C: U0 n) q2 X! i
- ADC1_ChanConf.Rank=1; //1个序列
- V& o( x3 W$ |6 t) N - ADC1_ChanConf.SamplingTime=ADC_SAMPLETIME_480CYCLES; //采样时间
+ c$ u, w3 u4 X7 Q8 b0 n9 [( C F3 a1 X - ADC1_ChanConf.Offset=0;
/ U1 g5 s z% h5 n. c: q' M - HAL_ADC_ConfigChannel(&ADC1_Handler,&ADC1_ChanConf); //通道配置
7 O& L! r+ `: I' U0 Q* Y0 H -
6 n# {$ G! S, u - HAL_ADC_Start(&ADC1_Handler); //开启ADC
0 K6 h& \- h% C6 V7 J -
: f+ \/ O" a$ ?1 a# E - HAL_ADC_PollForConversion(&ADC1_Handler,10); //轮询转换& E1 i0 H. z4 o) H3 k! F2 v% ]
- 2 H8 W; O0 O2 R; ]' j
- return (u16)HAL_ADC_GetValue(&ADC1_Handler); //返回最近一次ADC1规则组的转换结果5 F* y" V: c& ~2 B+ G
- }
复制代码 ————————————————
+ E3 F1 ^( u) j0 b' g版权声明:小盼你最萌哒4 W* u! w: p M: O' ?
如有侵权请联系删除
" u0 F4 O, x/ ^) w6 Y3 A4 v8 ?7 s( K$ R0 G `2 l: r7 U
) m3 e- H* w; h- g# P
|