基于HAL库,实现最简单ADC采集。
) j% u2 ^& y# y; p6 Q5 \5 [第一步,使用CubeMX配置时钟。$ {* z# h. E6 t: [0 |2 m2 j
1 w( E! ~. Z" j6 D f
; P. S& [# Y. @8 B4 E0 W
2 t# k1 O: }. T$ E然后是adc的配置:0 d- Y8 ~% h" |
4 T# ]' h: x" \7 h+ d- p9 N
% Q: X2 q( N5 }- T( H- S0 k0 }! o Z: G6 X. @7 F, X, _
将,稍微修改一下风格,并手写头文件和源文件。
$ }! p4 X, j5 S: u, g5 O5 G' ]1 ?9 @" O! n. `
adc.h很简单,就不说了。( n; L- f( t1 T$ c
- #ifndef __ADC_H
8 R) V3 T/ G# z5 F9 X K - #define __ADC_H
- B# {3 V4 G0 c& }6 u/ i7 L - #include "sys.h"
M3 N0 }: y j( n5 @
& X; P8 y$ X+ @) M" v- U- void MY_ADC_Init(void); //ADC通道初始化& I$ t4 e" t/ s( c: H5 p
- u16 Get_Adc(void); //获得某个通道值 % P9 S9 |, i& p; t
- #endif
- S& q5 _+ N3 p& M0 a
复制代码
, b- b7 |/ W) K* I7 \! D其中,MY_ADC_Init和HAL_ADC_MspInit的内容完全是根据CubeMX生成的代码写的,就改了一个变量名字。Get_Adc则简单了,当我们需要获取adc的值的时候,先HAL_ADC_Start启动ADC,然后HAL_ADC_PollForConversion等待转换完成,最后HAL_ADC_GetValue返回结果。
! b9 `: Z2 S; I- #include "adc.h"
) a) z! Z. `* C/ N6 F% ? - #include "delay.h"3 |/ m5 E, x+ R5 b$ Y2 b
9 |! |& h8 G a6 N9 I
. \/ h ^0 N6 ~- X- ADC_HandleTypeDef ADC1_Handler; //ADC句柄
0 f: N8 l* Z* U) ?$ r: c t - ADC_ChannelConfTypeDef ADC1_ChanConf; //ADC通道配置句柄
) K( Z3 |* C/ g4 l. p9 ]+ M& v
% t3 {$ q6 K" N6 Y) w$ r
# d: b0 w7 n+ s# N3 B( @- //初始化ADC
6 t7 o( T4 v' u5 C5 P; [ - void MY_ADC_Init(void)
: A p. J1 W0 H/ J3 q9 L - {3 T' h$ y% ]5 D+ H2 K& F5 \
- ADC1_Handler.Instance = ADC1;
5 { s+ W5 i& @% _0 S - ADC1_Handler.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4; //4分频,ADCCLK=PCLK2/4=108/4=27MHZ
! J+ X3 i+ W' R7 G* C$ o - ADC1_Handler.Init.Resolution = ADC_RESOLUTION_12B; //12位模式
4 k/ D( q$ R( o5 W1 ^ - ADC1_Handler.Init.ScanConvMode = DISABLE; //非扫描模式
% f3 x8 p6 e% l* W' ?* I/ C! X, O! | - ADC1_Handler.Init.ContinuousConvMode = DISABLE; //关闭连续转换6 S& d+ Q7 P7 h: n- `
- ADC1_Handler.Init.DiscontinuousConvMode = DISABLE; //禁止不连续采样模式
/ u0 i3 _7 [$ |6 D - ADC1_Handler.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE; //使用软件触发, k, s3 \9 J# i" ~
- ADC1_Handler.Init.ExternalTrigConv = ADC_SOFTWARE_START; //软件触发
7 L# {/ m* _3 ^! n0 z7 K - ADC1_Handler.Init.DataAlign = ADC_DATAALIGN_RIGHT; //右对齐% ^8 [3 A* Z# j$ i( E7 x
- ADC1_Handler.Init.NbrOfConversion = 1; //1个转换在规则序列中 也就是只转换规则序列1/ D# z6 }4 [1 K4 y( T: A
- ADC1_Handler.Init.NbrOfDiscConversion = 0; //不连续采样通道数为0
4 {' U0 L; \. n9 W) I. H$ b - ADC1_Handler.Init.DMAContinuousRequests = DISABLE; //关闭DMA请求
; r) t% ]0 ?" S' D# E8 x - ADC1_Handler.Init.EOCSelection = DISABLE; //关闭EOC中断
) C* M/ H; p7 I4 I1 n - HAL_ADC_Init(&ADC1_Handler); //初始化* K: q* v$ `, j7 h, ?( M Z* \
- 8 g) G2 F3 {' ]9 v
- ADC1_ChanConf.Channel = ADC_CHANNEL_5; //通道5 PA57 U& q8 `2 q/ S7 ~; R' M
- ADC1_ChanConf.Rank = 1; //1个序列! L& B( b- ^8 Z8 R3 R" M' L# l% J6 B
- ADC1_ChanConf.SamplingTime = ADC_SAMPLETIME_480CYCLES; //采样时间7 V. _# M8 B; ]% x! b7 E7 t; a
- ADC1_ChanConf.Offset = 0;
6 E4 K' i( b4 W0 a ~ - HAL_ADC_ConfigChannel(&ADC1_Handler, &ADC1_ChanConf); //通道配置0 G H" y& y i6 f5 {- b
- # b3 N, ]4 t' [2 T. Y. ^
- }
1 F, D0 v+ ^" @- O# Z( @2 M- }
% o2 v+ d9 p# r1 g6 p- //ADC底层驱动,引脚配置,时钟使能
3 W% A0 @: M- [. V" o% f' I9 X - //此函数会被HAL_ADC_Init()调用* X9 \4 ~" }" S. x$ F8 z
- //hadc:ADC句柄
P, }7 H/ }& s8 I - void HAL_ADC_MspInit(ADC_HandleTypeDef *hadc)
. q: K! e4 G- I7 `/ G& F$ o5 j - {) q2 z$ q6 N6 \0 C6 d' E; Y
- GPIO_InitTypeDef GPIO_Initure;
$ y. @2 h; q. {$ x7 s) k( i& G - __HAL_RCC_ADC1_CLK_ENABLE(); //使能ADC1时钟
8 m o0 W/ H+ q1 M- h - __HAL_RCC_GPIOA_CLK_ENABLE(); //开启GPIOA时钟; I! n6 F; L, E5 E; T
& V' a# X* X' R1 {- GPIO_Initure.Pin = GPIO_PIN_5; //PA5
6 c1 u z) J& U5 S" _) u8 S - GPIO_Initure.Mode = GPIO_MODE_ANALOG; //模拟: M# ?" ]$ Q7 y
- GPIO_Initure.Pull = GPIO_NOPULL; //不带上下拉4 O# `' d' w8 m; K
- HAL_GPIO_Init(GPIOA, &GPIO_Initure);
3 t1 k+ V; R. f4 D1 o9 q6 v/ m - }
- g- y- a D* j - . y) _! G' y8 L) @
- //获得ADC值" m1 R" U( Q& W4 c3 s$ V
- //ch: 通道值 0~16,取值范围为:ADC_CHANNEL_0~ADC_CHANNEL_16
v8 R2 t c2 D1 E1 I/ G - //返回值:转换结果
# U9 O4 @* I( S - u16 Get_Adc()3 w% ?$ E. ^! q9 K
- {, B% s2 r- \$ e. S# V% _
- HAL_ADC_Start(&ADC1_Handler); //开启ADC
7 h; x. E* c; i8 `0 V - HAL_ADC_PollForConversion(&ADC1_Handler, 10); //轮询转换0 t9 W- P# a+ P' l/ [( J" E0 |
- return (u16)HAL_ADC_GetValue(&ADC1_Handler); //返回最近一次ADC1规则组的转换结果& z" d. f5 F7 a# Q. S
- }
' d% e& o2 p4 W# i. E1 P
复制代码
" q/ ~) U6 X2 Z: smain.c中,主函数初始化之后,直接读取adc的值,并打印。. Y* j; Y: { f3 r# ~
- #include "sys.h"& H3 L& G2 L! U, z! {( G
- #include "delay.h"9 I. [7 C2 n# ~; u+ i D. L
- #include "usart.h"' ^; B" g1 K" f% g# l
- #include "adc.h"" P" \9 q- I% R% ?
- , h5 G0 F- g& g
- int main(void)8 } B% T% Y: t7 U3 F
- {. n2 D+ G. c8 O, k$ {" {# E W
- u16 adcx;
" X% S5 \- A( I$ f - Cache_Enable(); //打开L1-Cache! P+ r% z# ]& {' G1 H h
- HAL_Init(); //初始化HAL库- R& J% Y, L; X6 P0 F
- Stm32_Clock_Init(432, 8, 2, 9); //设置时钟,216Mhz s; D; ^$ S4 y
- delay_init(216); //延时初始化0 P2 N, z: V, D0 n% m% r' K
- uart_init(115200); //串口初始化
% e0 C# ?' R8 Y: ]& Q! e - MY_ADC_Init(); //初始化ADC1通道5
- {4 S* P* }& z8 D- ~6 v - n3 k) z- ?; Q, x( I
- while (1)- C5 ^$ k% b* a' T% ^3 U
- {; v, Q6 p, L P! Z6 }$ f
- adcx = Get_Adc(); //获取通道5的转换值,20次取平均
* ?* |; q D8 ]1 a# b2 } - printf("%d\r\n", adcx);& O" R U* ^7 _% c! B- b6 X
- delay_ms(250);$ @5 |& ?) O" m
- }# g) J$ p5 |' C
- }: W0 @& n4 w# q& l3 D& a
复制代码 ! w2 b/ z3 U6 _4 q: E- K
如果需要对多个通道进行轮询读取,可以稍微修改一下函数Get_Adc,在每次读取之前设置一下需要转换的通道:: p' d. R3 |; a$ ^6 v
- //获得ADC值0 U; V, i7 ^- J3 X( t' q: Z2 t
- //ch: 通道值 0~16,取值范围为:ADC_CHANNEL_0~ADC_CHANNEL_16
. E' h2 h2 J6 ?* v* J - //返回值:转换结果8 W; X1 Z" W/ u3 @* n0 E
- u16 Get_Adc(u32 ch) 1 D' {3 S, \2 G& ~; w- U
- {6 ?8 c2 Y1 f p
- ADC_ChannelConfTypeDef ADC1_ChanConf;( i2 n# }: n' d: O) j, i
-
b7 Q! S8 P! x q* |$ ` - ADC1_ChanConf.Channel=ch; //通道+ \3 B- D1 ~: K8 z
- ADC1_ChanConf.Rank=1; //1个序列$ V9 C, T! v0 w d4 ?
- ADC1_ChanConf.SamplingTime=ADC_SAMPLETIME_480CYCLES; //采样时间
$ d. b! G, Z# Y - ADC1_ChanConf.Offset=0; . ^% n6 S3 h5 r# `$ D" |
- HAL_ADC_ConfigChannel(&ADC1_Handler,&ADC1_ChanConf); //通道配置
7 H- |; ?6 ^$ S8 m) L - + h! r8 y: Q* g! N
- HAL_ADC_Start(&ADC1_Handler); //开启ADC
a, Q. \* t2 _0 y- U& c+ E - + ~8 e( e3 a3 u* ]
- HAL_ADC_PollForConversion(&ADC1_Handler,10); //轮询转换
- \. H% O; X) f' @) W+ {6 k" A - 6 O. m z* T8 L& z2 N3 n5 s
- return (u16)HAL_ADC_GetValue(&ADC1_Handler); //返回最近一次ADC1规则组的转换结果" w& H+ R+ n i& \3 E; j4 v9 }
- }
复制代码 ————————————————
0 B- X1 ?; N* |5 ? H4 U版权声明:小盼你最萌哒
! t" w$ [- i, F' w8 V* w如有侵权请联系删除+ M3 P* g' o2 t
7 q7 T0 y+ S0 x+ J
; L" }. V* [, m0 t |