基于HAL库,实现最简单ADC采集。
* c* X% H6 B: ]第一步,使用CubeMX配置时钟。! [1 n; L2 g+ `1 v2 q! \# b" s
" V2 ? W& j* X8 o4 H* S
* c6 N* m; o9 ^( D6 j# x- R! x! A, G
; B6 C8 e* B) f q9 X/ \2 E0 y然后是adc的配置:6 E8 C d& I" J3 X2 j
% X! H3 w3 _ j- w" e
4 R1 h) h8 n' I, j
' d2 l) L! y% n( ~0 Q: J! w R
将,稍微修改一下风格,并手写头文件和源文件。
( e% h9 h$ y- c- J* @% `
% F# Q7 X3 W9 w8 R+ Xadc.h很简单,就不说了。
& [% [8 c) `8 e- #ifndef __ADC_H% {* C$ ?% A3 @8 L
- #define __ADC_H
/ H& f& Z" ?( i/ x/ Q - #include "sys.h"+ g+ r8 @, O# ?% B$ q2 I5 l" Y: s1 \
- . o% Z& D; d# A6 V0 L
- void MY_ADC_Init(void); //ADC通道初始化
& r: E' m9 q7 z3 h8 V- d - u16 Get_Adc(void); //获得某个通道值 F2 K8 m9 L4 ]; ^
- #endif
3 D5 A; ~' A" ~' H7 H# v
复制代码 4 }) A) ^/ K }! u6 s
其中,MY_ADC_Init和HAL_ADC_MspInit的内容完全是根据CubeMX生成的代码写的,就改了一个变量名字。Get_Adc则简单了,当我们需要获取adc的值的时候,先HAL_ADC_Start启动ADC,然后HAL_ADC_PollForConversion等待转换完成,最后HAL_ADC_GetValue返回结果。! O+ Z+ f; f0 y# y E, t, r
- #include "adc.h"; ]# r+ |. [( S( l9 r4 V
- #include "delay.h" K9 Z7 Z$ T C6 a) X
- / R0 j2 J9 D$ E" _. B& u( F
+ `. K) Z$ l V, [5 }" b* @5 H3 V- ADC_HandleTypeDef ADC1_Handler; //ADC句柄3 u, T V4 Q: L8 N6 V
- ADC_ChannelConfTypeDef ADC1_ChanConf; //ADC通道配置句柄; K0 v0 m P+ F; w' n0 I' T
- + `1 X5 z( b; ^8 Q
+ C m/ Z1 q" L+ ^: H- //初始化ADC
+ n. @" N( h+ X# d3 l" y - void MY_ADC_Init(void)$ E4 f) D) P6 ^" b" j% S
- {4 j1 ]: I1 `9 @) i7 P U- `0 R
- ADC1_Handler.Instance = ADC1;' C) X4 M; Q' B( I
- ADC1_Handler.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4; //4分频,ADCCLK=PCLK2/4=108/4=27MHZ
$ q- M4 n5 L3 C - ADC1_Handler.Init.Resolution = ADC_RESOLUTION_12B; //12位模式
* F% E! m; g% q6 g! r - ADC1_Handler.Init.ScanConvMode = DISABLE; //非扫描模式
* l& h& C- C% P7 ~% ~, a, @5 X' o - ADC1_Handler.Init.ContinuousConvMode = DISABLE; //关闭连续转换+ W# f6 n; `+ m; Z/ L' k% t
- ADC1_Handler.Init.DiscontinuousConvMode = DISABLE; //禁止不连续采样模式
9 ~$ l1 s# y8 x! Y* c& f7 g ? - ADC1_Handler.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE; //使用软件触发
$ G# R# Z L8 K7 E - ADC1_Handler.Init.ExternalTrigConv = ADC_SOFTWARE_START; //软件触发1 m: R% N8 R( o; J2 W- O
- ADC1_Handler.Init.DataAlign = ADC_DATAALIGN_RIGHT; //右对齐, K' ?+ s& i& o8 r1 y
- ADC1_Handler.Init.NbrOfConversion = 1; //1个转换在规则序列中 也就是只转换规则序列1. _+ e7 C6 T/ a Y
- ADC1_Handler.Init.NbrOfDiscConversion = 0; //不连续采样通道数为0, |) Y$ z6 L* K" w% x
- ADC1_Handler.Init.DMAContinuousRequests = DISABLE; //关闭DMA请求
* l0 ^0 k. J* `$ h9 v7 b - ADC1_Handler.Init.EOCSelection = DISABLE; //关闭EOC中断# `& U1 T5 s1 l8 R' a
- HAL_ADC_Init(&ADC1_Handler); //初始化3 e/ R$ D& @8 a- L5 \" \
4 t% b& G0 O' ~& J$ [- ADC1_ChanConf.Channel = ADC_CHANNEL_5; //通道5 PA5/ h/ V7 U7 J% x& l6 w. c5 ]
- ADC1_ChanConf.Rank = 1; //1个序列
. | {$ z+ o) M& c# @3 J; B/ }9 p0 Z, H - ADC1_ChanConf.SamplingTime = ADC_SAMPLETIME_480CYCLES; //采样时间9 j+ n' G! w4 w% ]
- ADC1_ChanConf.Offset = 0;/ o V8 h. X* b5 T
- HAL_ADC_ConfigChannel(&ADC1_Handler, &ADC1_ChanConf); //通道配置& W. v, r8 y- b! ~% n: b; ]% c
- ; ?9 ~& P5 h5 ~+ @7 ^% g
- }
; m) K, \9 G+ b4 B E; y/ z4 o7 y
* ?. m8 P% j: [7 |- //ADC底层驱动,引脚配置,时钟使能2 t$ K$ C3 }) j; S- w: _ g
- //此函数会被HAL_ADC_Init()调用
0 ?$ K0 C5 O0 v S - //hadc:ADC句柄5 {) `/ {- Q2 F* e5 h- y, C
- void HAL_ADC_MspInit(ADC_HandleTypeDef *hadc)
3 Y) m' P7 u$ p+ [6 d - {5 O" o& k% z1 n; @
- GPIO_InitTypeDef GPIO_Initure;
6 G6 O+ F. b7 Y9 c, X( ] - __HAL_RCC_ADC1_CLK_ENABLE(); //使能ADC1时钟
, a9 K5 v7 x& k8 ~0 ` - __HAL_RCC_GPIOA_CLK_ENABLE(); //开启GPIOA时钟 w! x2 K1 F3 W1 z1 v, i6 V0 p* i
- C( c5 X! R- B( q
- GPIO_Initure.Pin = GPIO_PIN_5; //PA5
: w: |& O4 x6 g5 c( } - GPIO_Initure.Mode = GPIO_MODE_ANALOG; //模拟
' N$ g9 @+ ?9 c: c1 ~5 ^) R - GPIO_Initure.Pull = GPIO_NOPULL; //不带上下拉
4 ~" O2 u" y% s9 p/ v; c% a1 j - HAL_GPIO_Init(GPIOA, &GPIO_Initure);/ q3 z7 ^2 D/ E& n
- }
- P; f% w2 P! z8 e, d) D - , B9 X2 R, k, J P: Q
- //获得ADC值* L6 Y# W. a' z9 I) A2 @5 Z
- //ch: 通道值 0~16,取值范围为:ADC_CHANNEL_0~ADC_CHANNEL_16
) O8 A: q- s9 r l. T m - //返回值:转换结果
( i3 [8 _. a$ x3 ?/ S - u16 Get_Adc(), v( L( J/ n2 r, p: o
- {$ d' x( |* L7 z6 V) P ~+ ?
- HAL_ADC_Start(&ADC1_Handler); //开启ADC( K+ _) H9 O3 f. e$ v0 T
- HAL_ADC_PollForConversion(&ADC1_Handler, 10); //轮询转换5 ~$ q6 i% G' ]
- return (u16)HAL_ADC_GetValue(&ADC1_Handler); //返回最近一次ADC1规则组的转换结果 W( d. W4 f5 O8 r
- }
/ @4 i3 ]+ O2 A: s3 j. ~! `; g
复制代码
& T, Z4 i4 M. Z2 z0 emain.c中,主函数初始化之后,直接读取adc的值,并打印。
$ p; \- t1 X0 ^ w/ m+ r( D+ q- #include "sys.h" s& y6 R0 J1 }0 H
- #include "delay.h"* a9 a3 _' J! M( P$ @% b1 \2 r+ ]
- #include "usart.h"
' x) `; H/ j5 A7 a, { - #include "adc.h"
+ [6 s1 F I# S0 a3 t+ _+ K" ` - 0 }* N: J' d6 g
- int main(void)
; k5 Y# S! ~0 T: F. \ - {
+ S) P, M7 q4 N- i( _ - u16 adcx;* {+ N, {# a7 | w
- Cache_Enable(); //打开L1-Cache& i+ ~8 c) O4 u; d% L
- HAL_Init(); //初始化HAL库! z7 z& m! O( d: m
- Stm32_Clock_Init(432, 8, 2, 9); //设置时钟,216Mhz% [, s7 c" j6 m3 l, m% g, f' |
- delay_init(216); //延时初始化5 E- Q: f# V& ^$ ?
- uart_init(115200); //串口初始化
, F8 K! Q# m2 v; Q/ _ - MY_ADC_Init(); //初始化ADC1通道51 @. ?' r8 ^2 m5 H7 E. i
-
" P. X& k$ @0 J1 h& ?! a - while (1); @8 E+ ?! E2 }5 L2 a" A
- {- ~6 ^$ } E) }. I
- adcx = Get_Adc(); //获取通道5的转换值,20次取平均3 n9 u8 }) ? h R1 I
- printf("%d\r\n", adcx);; X. z. a. ^9 u5 r9 @/ o. g
- delay_ms(250); K5 W& D7 w- A# }( i) e& O
- }
2 S k; E) g/ f# q) d: Q, x - }
3 E8 N4 C1 @5 ?8 G7 e5 E" v
复制代码
1 c' Q& g' [, \1 O- l- N4 Z7 W如果需要对多个通道进行轮询读取,可以稍微修改一下函数Get_Adc,在每次读取之前设置一下需要转换的通道: h& T r* n. D! ^* M) Q
- //获得ADC值/ ` i: j' B+ H2 m
- //ch: 通道值 0~16,取值范围为:ADC_CHANNEL_0~ADC_CHANNEL_163 c1 |% Y# C' d
- //返回值:转换结果
) j9 y% D+ l7 ]+ t$ c - u16 Get_Adc(u32 ch)
2 M) u4 [) J( H! c - {. c; a2 _1 |) c6 k
- ADC_ChannelConfTypeDef ADC1_ChanConf;5 q% J5 {! m* ?+ [
-
8 X0 o$ @" `4 R4 u! j - ADC1_ChanConf.Channel=ch; //通道) g) e! X/ ~& y7 z% ~
- ADC1_ChanConf.Rank=1; //1个序列
" u; _% E( D( {5 u5 Z p- ^ - ADC1_ChanConf.SamplingTime=ADC_SAMPLETIME_480CYCLES; //采样时间
6 P0 s, Z2 E7 [# ?% m; g# Q - ADC1_ChanConf.Offset=0;
) c$ b9 ~$ ]+ C$ J/ c - HAL_ADC_ConfigChannel(&ADC1_Handler,&ADC1_ChanConf); //通道配置/ I; c a0 K1 I: ^+ A2 I. z) G
- 9 h4 N3 q) W" p. {/ [: w( k: U$ u
- HAL_ADC_Start(&ADC1_Handler); //开启ADC$ f1 N& D; `" `8 A8 ^( L% a5 Z0 k, l1 C, |. W
- ! Q+ z) v0 O0 h3 v& c
- HAL_ADC_PollForConversion(&ADC1_Handler,10); //轮询转换
! R0 b, X0 ^% i* A - 4 n- z% z% @0 |6 T7 `0 z
- return (u16)HAL_ADC_GetValue(&ADC1_Handler); //返回最近一次ADC1规则组的转换结果
* \5 o+ P! _2 C) x9 r$ E5 G - }
复制代码 ————————————————
l- x4 a. `6 d) D( o, j版权声明:小盼你最萌哒- H% l3 d$ f* }8 e/ o6 C
如有侵权请联系删除7 s+ S5 Q/ v) o W+ E% f! H
0 ]# H X( d' e: y' l" A- T4 z5 k2 j' P# |( B
|