基于HAL库,实现最简单ADC采集。
4 s' \% D* N3 E* }6 V) k: Y第一步,使用CubeMX配置时钟。+ A8 r* D! C1 T) t
. M- }" Q" L4 E' ~6 `1 \3 T* E
9 o4 X& P& U1 Q& S
然后是adc的配置:
* }. U" U9 f7 ]: ^9 f6 w0 I8 \3 X$ [5 y$ J7 \* A5 K
# E8 i/ b) S" q2 e
' Q. n* e& j: F1 ?! g0 b: h将,稍微修改一下风格,并手写头文件和源文件。2 n2 r+ O7 o( @- u
" c+ u2 E, ]5 K. ^adc.h很简单,就不说了。5 ~. Z1 p0 d& L; E# r- l6 S
. k+ T& U2 {/ b' I) k% S- #ifndef __ADC_H
" n$ Z1 C0 @, W( E: Z0 w! ?, u6 Z - #define __ADC_H
( `: U& d5 \/ ?6 C# K( x - #include "sys.h"
! \9 V0 I p9 C. ]5 _% v - $ k; [9 Q& V- M
- void MY_ADC_Init(void); //ADC通道初始化- V4 a+ ~& u1 X2 E6 w8 z
- u16 Get_Adc(void); //获得某个通道值 $ O$ A; g0 _2 `) O' g4 Y) v8 I
- #endif
复制代码
3 i" u1 N, Q* w8 P8 d其中,MY_ADC_Init和HAL_ADC_MspInit的内容完全是根据CubeMX生成的代码写的,就改了一个变量名字。Get_Adc则简单了,当我们需要获取adc的值的时候,先HAL_ADC_Start启动ADC,然后HAL_ADC_PollForConversion等待转换完成,最后HAL_ADC_GetValue返回结果。! H% t' c' T3 X
! K) `1 }' n/ }; v- a- #include "adc.h" m! ]% q5 I3 Z1 c# N
- #include "delay.h"
0 j. K1 u# R1 J
) e& @! ]; L4 W! ^- ) h) N: z( M& c) A9 f
- ADC_HandleTypeDef ADC1_Handler; //ADC句柄2 e H8 G2 u7 c. p2 e
- ADC_ChannelConfTypeDef ADC1_ChanConf; //ADC通道配置句柄
: _6 }, F+ r# B, F9 n8 ~0 \
" m# r W; Z9 Q. [. L( W
% j* [6 ~' Y, @6 w( e3 [, F+ [- //初始化ADC
" Q$ Z) [# }8 [9 M' o4 W - void MY_ADC_Init(void)
7 P1 D: E" Z* J/ s - {
& h1 @' j6 k7 ^: J! L' G - ADC1_Handler.Instance = ADC1;4 z; P* f& Q4 g" s3 `0 s* S0 [8 F, M
- ADC1_Handler.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4; //4分频,ADCCLK=PCLK2/4=108/4=27MHZ' w" p, U- [# B$ C
- ADC1_Handler.Init.Resolution = ADC_RESOLUTION_12B; //12位模式
' ^6 a9 Z# L. V* E# j - ADC1_Handler.Init.ScanConvMode = DISABLE; //非扫描模式# T9 r/ n7 T/ W+ ^# ^9 k
- ADC1_Handler.Init.ContinuousConvMode = DISABLE; //关闭连续转换
3 f8 D+ w9 _- l! Z0 R - ADC1_Handler.Init.DiscontinuousConvMode = DISABLE; //禁止不连续采样模式
/ H+ h( X o$ O" _ - ADC1_Handler.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE; //使用软件触发
6 @3 h; n2 G, b3 t; G$ J& D' G - ADC1_Handler.Init.ExternalTrigConv = ADC_SOFTWARE_START; //软件触发2 ]6 s, r0 I/ Z* z8 I" H" z
- ADC1_Handler.Init.DataAlign = ADC_DATAALIGN_RIGHT; //右对齐
: Z; T8 i) r, u5 E, j j - ADC1_Handler.Init.NbrOfConversion = 1; //1个转换在规则序列中 也就是只转换规则序列1* h3 x% O) ^' ^: s# H9 _1 s9 K
- ADC1_Handler.Init.NbrOfDiscConversion = 0; //不连续采样通道数为04 L4 i+ @5 Q' W
- ADC1_Handler.Init.DMAContinuousRequests = DISABLE; //关闭DMA请求
% a1 _. B. f, b* B) B3 J4 D l - ADC1_Handler.Init.EOCSelection = DISABLE; //关闭EOC中断$ u" |. e& c) R9 C, p2 O, m k0 v
- HAL_ADC_Init(&ADC1_Handler); //初始化
7 L8 }& ^& F& c' @+ n - # A7 @ S' r L$ k* w0 B
- ADC1_ChanConf.Channel = ADC_CHANNEL_5; //通道5 PA5
; {! b5 K% u# h; t# _* Q8 a - ADC1_ChanConf.Rank = 1; //1个序列% j- \ [- k9 w; } d2 T' W" K, b
- ADC1_ChanConf.SamplingTime = ADC_SAMPLETIME_480CYCLES; //采样时间
D/ k' y' D- u3 ?4 y' B8 I3 B. _3 p - ADC1_ChanConf.Offset = 0;) Q" }1 V8 g$ w" F; D
- HAL_ADC_ConfigChannel(&ADC1_Handler, &ADC1_ChanConf); //通道配置
$ s2 |$ y$ A( u
) A* _- u0 d/ E! I- X& N u! Y- }
3 _0 a& H0 ?2 [; X$ B- i0 M4 t - 0 Y8 t1 Y, T- ]9 w2 e7 E% |
- //ADC底层驱动,引脚配置,时钟使能
* F. g- [2 {0 v8 l - //此函数会被HAL_ADC_Init()调用
9 ^, s% q! U+ ^( Z/ X7 G - //hadc:ADC句柄; W' L8 Y; |( b- E+ w3 N
- void HAL_ADC_MspInit(ADC_HandleTypeDef *hadc)
8 h3 [: @* l7 f2 O - {/ |& q) `0 r" Z' t
- GPIO_InitTypeDef GPIO_Initure;' W& c. Q" ~/ u( q
- __HAL_RCC_ADC1_CLK_ENABLE(); //使能ADC1时钟
" S5 J# M8 i6 [% w8 N% I - __HAL_RCC_GPIOA_CLK_ENABLE(); //开启GPIOA时钟0 o; x( Y1 y+ C5 |0 ~; ~8 E+ F
- 2 s5 `" G; f! W* J6 n
- GPIO_Initure.Pin = GPIO_PIN_5; //PA5' e" R8 v: B9 W7 _+ H4 c
- GPIO_Initure.Mode = GPIO_MODE_ANALOG; //模拟/ `" C) h P2 w+ `) I6 e+ F
- GPIO_Initure.Pull = GPIO_NOPULL; //不带上下拉" Q- Y& Z# l. d; k- b) K4 h" @
- HAL_GPIO_Init(GPIOA, &GPIO_Initure);
1 A" J7 [8 E5 e- e' [ - }
! T8 p& U* p0 o5 `
+ ~' }8 |& b3 F _& m* D! i0 a" }- //获得ADC值- [$ `5 x; @5 D2 j. s' t& K
- //ch: 通道值 0~16,取值范围为:ADC_CHANNEL_0~ADC_CHANNEL_16: k+ K4 ^0 C7 t' M4 U0 q3 B
- //返回值:转换结果: T+ }/ K; ]8 W! W& u
- u16 Get_Adc()% g( p+ \7 `: a6 u
- {
: Q v6 X X; M+ k- ? - HAL_ADC_Start(&ADC1_Handler); //开启ADC
1 k* y1 c( W1 O! P- Z3 x - HAL_ADC_PollForConversion(&ADC1_Handler, 10); //轮询转换5 j. `! x! w* n0 _$ p5 y, X6 p
- return (u16)HAL_ADC_GetValue(&ADC1_Handler); //返回最近一次ADC1规则组的转换结果
2 _7 }* z( P( a( S+ P - }
复制代码
. h' c' M: ?$ A+ k; {& p2 Y9 t& F4 x0 m' Dmain.c中,主函数初始化之后,直接读取adc的值,并打印。6 ^* G* J) u; T( j# n: n! G" |$ W6 ^
& t2 B& e$ d- Q* P e. r( S2 I/ r- #include "sys.h"8 p( [7 C/ ? s; O; u
- #include "delay.h"
+ B1 r5 ]" w2 p - #include "usart.h"
4 L* T4 ?" a X, N - #include "adc.h"( e! y( m/ G& e, a* j
' N$ t0 z* P8 x, x5 i- int main(void)" L3 _' O3 X1 R% ]- L
- {
6 @" r, d# ^, U% @ - u16 adcx;
9 P" H# m6 R( ^ A - Cache_Enable(); //打开L1-Cache9 ?1 ~) v+ D& a$ B4 B+ O: F
- HAL_Init(); //初始化HAL库
6 h8 V1 F/ M/ O3 t2 w8 m - Stm32_Clock_Init(432, 8, 2, 9); //设置时钟,216Mhz$ P; }& m4 b- m/ u7 j9 @( q8 ~
- delay_init(216); //延时初始化' t* a' d& Q) U, h! Q4 m* e
- uart_init(115200); //串口初始化3 k( E; o: R+ ~' q/ U
- MY_ADC_Init(); //初始化ADC1通道5
5 r& p8 e% ^9 L& @' D' U -
- P! r' f1 Z0 M - while (1)
/ d. A; w" T. \% z% f* S. W - {
: H: i9 D+ C- n3 ]2 I - adcx = Get_Adc(); //获取通道5的转换值,20次取平均7 L3 y/ K: I' X1 v# y) U
- printf("%d\r\n", adcx);2 q& h, V0 U. ?. q! h( h7 p R# ^- ]
- delay_ms(250);
0 h9 a A$ V( [2 b1 P3 [1 H N9 H - }
! N% `1 [2 B1 W, {. U$ t - }
复制代码
7 L1 a2 s" Y O# I; p& b. O" l" i如果需要对多个通道进行轮询读取,可以稍微修改一下函数Get_Adc,在每次读取之前设置一下需要转换的通道:& E6 W( ~2 W% B
$ ~0 q* L3 @6 d: g) P' _$ { P
- //获得ADC值8 ]" ?) G* R# o" x, ?5 }
- //ch: 通道值 0~16,取值范围为:ADC_CHANNEL_0~ADC_CHANNEL_16' l9 h0 x, y: s8 r
- //返回值:转换结果; B, |9 O6 ~) P( C, l2 G: u$ \
- u16 Get_Adc(u32 ch) 1 }: D2 x0 k0 M5 H ~1 X
- {
+ v( Z( O |' j - ADC_ChannelConfTypeDef ADC1_ChanConf;) K3 O' N& M: A, D
: l( K3 F- _/ }" B# {- a- ADC1_ChanConf.Channel=ch; //通道' H$ h* _8 e- b. O& U4 e
- ADC1_ChanConf.Rank=1; //1个序列
$ O) D( |8 m; Y2 N - ADC1_ChanConf.SamplingTime=ADC_SAMPLETIME_480CYCLES; //采样时间
- k$ y4 K2 F& S! F9 [2 O7 J - ADC1_ChanConf.Offset=0; ! s3 e2 @1 z$ x+ o3 C4 Q+ {$ Z
- HAL_ADC_ConfigChannel(&ADC1_Handler,&ADC1_ChanConf); //通道配置' o8 g8 N+ s1 R4 d- H6 s
- . R3 T% r* @8 j* |7 ]7 R/ c. u
- HAL_ADC_Start(&ADC1_Handler); //开启ADC
* f+ s& W1 D2 ~. x3 D - - l0 ~; m+ U$ K" ^# n, _
- HAL_ADC_PollForConversion(&ADC1_Handler,10); //轮询转换
# ?; _! R c' c5 q& k - # j8 a3 _8 A2 F4 A4 S; p9 S
- return (u16)HAL_ADC_GetValue(&ADC1_Handler); //返回最近一次ADC1规则组的转换结果
9 _; R6 Q9 |. `; D - }
- J/ c4 v% o( |# I$ H' x
复制代码
2 o! N. F) O. x6 _& K. X, l0 x; N
0 [5 B) X: q4 G- x. r5 Q |