基于HAL库,实现最简单ADC采集。
2 ]1 i1 m6 L/ R" V第一步,使用CubeMX配置时钟。
9 h! x8 z$ g% ?( Z6 P! P8 h; \, ? D3 p
- H3 ~/ t$ n5 A; n然后是adc的配置:
% @" g: L, s. i+ k6 V; m# v
C( Y: h. p$ `! {3 M' s& X, R4 L1 H
( a: R; p* {, z4 v7 k# h; `# i
将,稍微修改一下风格,并手写头文件和源文件。
# l) t/ F1 p" z. e( n9 v0 ^) K- R! @8 x; e: ?
adc.h很简单,就不说了。+ G6 J1 y9 } l( K4 f; s4 r F8 l3 m
7 {0 |2 c7 }- G, {1 N- h- #ifndef __ADC_H; e K9 n$ Y9 N
- #define __ADC_H$ }- v! O5 X: w6 q
- #include "sys.h"9 D' c. H2 M: G+ m
# x. k$ |9 P4 E; m7 w- o& e- void MY_ADC_Init(void); //ADC通道初始化
+ X$ E. ^' C0 s1 j' a$ O - u16 Get_Adc(void); //获得某个通道值
8 X# @5 z+ }( Q6 A) \, j - #endif
复制代码
0 @& p- B$ f9 R其中,MY_ADC_Init和HAL_ADC_MspInit的内容完全是根据CubeMX生成的代码写的,就改了一个变量名字。Get_Adc则简单了,当我们需要获取adc的值的时候,先HAL_ADC_Start启动ADC,然后HAL_ADC_PollForConversion等待转换完成,最后HAL_ADC_GetValue返回结果。& y. z- U5 }1 |/ h: |5 O) M
) _- y7 x, t/ d
- #include "adc.h"
: d8 G5 ~% C* a0 }2 { - #include "delay.h"1 L! h3 ]8 l* E- V2 D z
- 4 W% a& O0 B7 k$ V
& l7 |: b. ~% D- ADC_HandleTypeDef ADC1_Handler; //ADC句柄# H: j0 J+ V, K* i
- ADC_ChannelConfTypeDef ADC1_ChanConf; //ADC通道配置句柄
8 x' h7 d( v, ?' {; G( M+ z6 F+ q
9 F( r% x# Y& }' ~- n, T
( h4 I" Z/ ]! F- //初始化ADC( [6 Z* W4 _: d7 o
- void MY_ADC_Init(void)2 |3 C! N$ Z, q3 B: E
- {
7 F) j& O+ E% A( j$ I, L: A - ADC1_Handler.Instance = ADC1;5 D) s: `/ I/ m4 F! B# d5 x4 W% {
- ADC1_Handler.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4; //4分频,ADCCLK=PCLK2/4=108/4=27MHZ
8 c( V( q9 e& B& H - ADC1_Handler.Init.Resolution = ADC_RESOLUTION_12B; //12位模式9 C2 M: v- e- ~: A! A$ ]
- ADC1_Handler.Init.ScanConvMode = DISABLE; //非扫描模式
+ N# s8 b& O3 ]: W* B - ADC1_Handler.Init.ContinuousConvMode = DISABLE; //关闭连续转换5 X+ q ?* u; \4 k' V* L e4 S/ w# ~
- ADC1_Handler.Init.DiscontinuousConvMode = DISABLE; //禁止不连续采样模式8 Y# L- X) S& g2 Q4 u; {
- ADC1_Handler.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE; //使用软件触发
; Q7 B+ x, X A0 D) n, i9 _2 ~9 b, d - ADC1_Handler.Init.ExternalTrigConv = ADC_SOFTWARE_START; //软件触发
8 d, W6 P. g* G" T - ADC1_Handler.Init.DataAlign = ADC_DATAALIGN_RIGHT; //右对齐
1 ] F7 m" N X t - ADC1_Handler.Init.NbrOfConversion = 1; //1个转换在规则序列中 也就是只转换规则序列1
/ A, k) V+ C# \ - ADC1_Handler.Init.NbrOfDiscConversion = 0; //不连续采样通道数为0 W) k. v* v1 t* ^
- ADC1_Handler.Init.DMAContinuousRequests = DISABLE; //关闭DMA请求
9 Q$ [/ y f. {- b0 S - ADC1_Handler.Init.EOCSelection = DISABLE; //关闭EOC中断, h& m0 s9 v/ j$ t6 ]+ o
- HAL_ADC_Init(&ADC1_Handler); //初始化8 F8 Y6 T6 P% P; J6 G
$ }" W0 N5 M/ q- ADC1_ChanConf.Channel = ADC_CHANNEL_5; //通道5 PA5( s( ~. [/ L5 C4 B4 U/ J
- ADC1_ChanConf.Rank = 1; //1个序列
: E9 R7 `$ ^+ T, a: W - ADC1_ChanConf.SamplingTime = ADC_SAMPLETIME_480CYCLES; //采样时间/ e$ D. n# g) ]& H9 }1 z# o
- ADC1_ChanConf.Offset = 0;4 K3 i1 p. G* u
- HAL_ADC_ConfigChannel(&ADC1_Handler, &ADC1_ChanConf); //通道配置7 y% s3 ^5 z8 T. N
6 Y" n5 \" G2 c; |& t/ X- }( }$ z- V& X" J" k+ p$ C9 r; H A- V
- : T/ m; s% G' x8 l* E
- //ADC底层驱动,引脚配置,时钟使能
" j" X+ R" w" H" i. k - //此函数会被HAL_ADC_Init()调用
7 A7 ]2 i7 F3 |+ G; ?7 o+ M- E - //hadc:ADC句柄, ?, Q% m' O( {/ T3 ]1 u
- void HAL_ADC_MspInit(ADC_HandleTypeDef *hadc)+ g: z! D. q( H) u) [. O
- {
) D: D& d- `- m( f - GPIO_InitTypeDef GPIO_Initure;, _) d. T1 D4 k# o% x, q5 y
- __HAL_RCC_ADC1_CLK_ENABLE(); //使能ADC1时钟) l- a& G% }, u5 `9 O2 ]" ^! C
- __HAL_RCC_GPIOA_CLK_ENABLE(); //开启GPIOA时钟3 y# T2 K- ~0 C4 V
- : |: R( a- |5 m! ~& v
- GPIO_Initure.Pin = GPIO_PIN_5; //PA5: @# e; m9 V+ u7 o `) _& P; K" a2 [
- GPIO_Initure.Mode = GPIO_MODE_ANALOG; //模拟0 g; v3 M8 f) a
- GPIO_Initure.Pull = GPIO_NOPULL; //不带上下拉5 _: m$ X2 T+ L7 u; S8 d' m! E0 H
- HAL_GPIO_Init(GPIOA, &GPIO_Initure);1 z+ p8 N* N( b2 L5 Z# L" t! Y
- }) } P0 v) z/ ^7 V
- 9 ~4 z9 m7 Z0 `4 V( Q+ I* Y8 A
- //获得ADC值
9 X% l3 N7 D5 f - //ch: 通道值 0~16,取值范围为:ADC_CHANNEL_0~ADC_CHANNEL_16
/ }2 F: _: l1 y. [+ J/ v8 u - //返回值:转换结果; p+ k% n. \1 W2 F5 Y5 j6 f
- u16 Get_Adc()
- a; C3 F; ^0 L3 a3 S I. F0 _6 a3 x - {2 ]7 b3 p) a- u4 A3 F/ N
- HAL_ADC_Start(&ADC1_Handler); //开启ADC
: f+ |1 }( h6 g, A; X0 r - HAL_ADC_PollForConversion(&ADC1_Handler, 10); //轮询转换
! U3 C; ~# L% U5 g - return (u16)HAL_ADC_GetValue(&ADC1_Handler); //返回最近一次ADC1规则组的转换结果
, q$ ]7 U. }* w6 W+ Q( ] - }
复制代码
8 N1 X( V1 C3 w% B6 @8 smain.c中,主函数初始化之后,直接读取adc的值,并打印。8 a3 n! {5 }# g! f
. K3 v% J+ L( q1 s) m- #include "sys.h"
; c, z) P8 z0 W) `" L3 e' j0 d - #include "delay.h"
% ?% X! S' R. x# ` - #include "usart.h"
/ J3 k1 {8 x! e$ [0 O$ H: i% d) A - #include "adc.h"
L: K. ]1 E9 M2 N) T
6 H3 X+ w" A. e* _/ H* z- int main(void)% e; `0 ^7 e4 K3 n0 I1 b" ]
- {7 S; O' ~5 E- u
- u16 adcx;. w" i9 K9 a( W4 c+ B3 \
- Cache_Enable(); //打开L1-Cache% Y/ }! P; O9 O1 Q( q, n, d; \+ {
- HAL_Init(); //初始化HAL库6 |5 n; w* q! Y, i* [
- Stm32_Clock_Init(432, 8, 2, 9); //设置时钟,216Mhz
, G2 w f9 K5 r" C - delay_init(216); //延时初始化
! G: {$ [$ n1 b. d - uart_init(115200); //串口初始化
* j( V$ q1 U/ S; s2 _& }6 b - MY_ADC_Init(); //初始化ADC1通道5
: z* ?* v# o4 u) g1 t -
) x" T9 {% e' [; c" I9 f% | - while (1)
/ w# x% H0 V9 N$ v4 f - {
1 j& |" a# A5 o- g7 q6 }' X( Y; z9 l - adcx = Get_Adc(); //获取通道5的转换值,20次取平均; r; V+ p+ b M
- printf("%d\r\n", adcx);
! Z, p3 U: D1 W5 P - delay_ms(250);
" e5 }- n9 r& y" X, { - }% s8 \4 [+ q) w- @, i3 f
- }
复制代码 s; _2 x3 K0 q7 S
如果需要对多个通道进行轮询读取,可以稍微修改一下函数Get_Adc,在每次读取之前设置一下需要转换的通道:8 w; y( u5 e( c. M' C: d) j
# d$ ]+ m, {& z9 O
- //获得ADC值$ i; `" o+ [2 S6 V! }
- //ch: 通道值 0~16,取值范围为:ADC_CHANNEL_0~ADC_CHANNEL_16
/ U/ ] E& U M - //返回值:转换结果
- }3 N! H- z; r& x# `& R4 f - u16 Get_Adc(u32 ch)
- |' ^9 k" S4 i* U - { ~7 e: K" y, w2 q! L6 ? p
- ADC_ChannelConfTypeDef ADC1_ChanConf;+ X4 O3 |4 p4 ^/ s# C, Z
8 B9 |% i( V/ v3 u" l" E- ADC1_ChanConf.Channel=ch; //通道
2 I8 z' V) G1 k1 ^- x6 ] - ADC1_ChanConf.Rank=1; //1个序列
9 m) j) @' q1 M9 B/ Y9 C - ADC1_ChanConf.SamplingTime=ADC_SAMPLETIME_480CYCLES; //采样时间
! x8 n3 r, p: h - ADC1_ChanConf.Offset=0;
p, L' ], c# m& I! f! {, ^9 k - HAL_ADC_ConfigChannel(&ADC1_Handler,&ADC1_ChanConf); //通道配置
( x2 K( M& }" i! ?5 I; E) C -
! M Y8 x2 m I - HAL_ADC_Start(&ADC1_Handler); //开启ADC
; v# N8 q- K, n' o4 e4 z -
6 n. v4 Y2 G2 j9 _7 B - HAL_ADC_PollForConversion(&ADC1_Handler,10); //轮询转换8 [+ g" l w# c, M
: N; Y, v6 H8 K- return (u16)HAL_ADC_GetValue(&ADC1_Handler); //返回最近一次ADC1规则组的转换结果
8 T6 N! @* [% T2 C - }9 j. j a6 j& y9 J5 t$ ]
复制代码
* ?, x) j) o4 [
" |1 u( b$ ]; c' c# {( t+ b2 C; v. y6 b9 u6 e
|