基于HAL库,实现最简单ADC采集。9 A, l) N6 N& ^' ? b2 @: Y
第一步,使用CubeMX配置时钟。
7 u+ n; {6 a E* h7 n- v, t' Z' r0 e3 S& E2 W
! O3 I/ m/ x! P1 c
8 q; I9 E/ E, m4 u3 @. V然后是adc的配置:5 U B: w3 u7 v: ^
4 v* f. a& D4 R
& t9 a$ H# C$ {3 l% X1 W- \# s# f% m2 f7 I0 y6 [+ r- w
将,稍微修改一下风格,并手写头文件和源文件。
# n/ Z3 Y6 G% u! D1 h6 ]6 j0 K
! ^" _1 @( N7 H$ c# c' Vadc.h很简单,就不说了。
) t' V; t; Y z" f- #ifndef __ADC_H9 ~2 b9 V r* w4 m& G6 T
- #define __ADC_H$ P5 E$ U: Z; r, A5 b" K
- #include "sys.h"& @5 O7 w, B, E/ {+ I/ q( e* b
- , D4 n1 X' q& J* e$ r, N p
- void MY_ADC_Init(void); //ADC通道初始化1 W1 E, i( |! w3 `" ^# f
- u16 Get_Adc(void); //获得某个通道值
( i4 w; K0 L5 l, ]- U0 G1 [ - #endif 9 K* D2 b1 v8 \5 V5 d
复制代码 $ w$ P- `) ^4 o$ n+ R: E
其中,MY_ADC_Init和HAL_ADC_MspInit的内容完全是根据CubeMX生成的代码写的,就改了一个变量名字。Get_Adc则简单了,当我们需要获取adc的值的时候,先HAL_ADC_Start启动ADC,然后HAL_ADC_PollForConversion等待转换完成,最后HAL_ADC_GetValue返回结果。
6 l+ l* @5 }+ C; x6 _1 f4 g4 y( r- #include "adc.h". N8 l, ^$ O+ D' y- u- C+ E
- #include "delay.h"
- X2 ]" {/ S* |! q
, n* A+ X7 l0 Z7 R3 J
) s0 p7 G* i) x i1 t& Z& ]- ADC_HandleTypeDef ADC1_Handler; //ADC句柄
* c7 O9 d1 A& l - ADC_ChannelConfTypeDef ADC1_ChanConf; //ADC通道配置句柄8 R9 U' R9 n& y. K
6 q/ i3 v9 N0 x: \
; K5 D M" C) T, J- A G- //初始化ADC
( j% b/ |( M) n, k _: B4 s - void MY_ADC_Init(void)4 t8 G- ]& h* {9 ]
- {
5 S1 B. R3 v4 q: \$ U$ [ - ADC1_Handler.Instance = ADC1;
$ r0 i3 G% y6 b9 Z. y5 \1 _ - ADC1_Handler.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4; //4分频,ADCCLK=PCLK2/4=108/4=27MHZ- g! h9 @1 O5 C h! v
- ADC1_Handler.Init.Resolution = ADC_RESOLUTION_12B; //12位模式5 s0 [% b) t; o
- ADC1_Handler.Init.ScanConvMode = DISABLE; //非扫描模式
& C' |+ F. t# V - ADC1_Handler.Init.ContinuousConvMode = DISABLE; //关闭连续转换! [( d$ l- N- e5 O: m
- ADC1_Handler.Init.DiscontinuousConvMode = DISABLE; //禁止不连续采样模式
# K9 R0 @! h% F/ T - ADC1_Handler.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE; //使用软件触发3 V- k3 m. \2 g! \5 Z3 j0 M1 {
- ADC1_Handler.Init.ExternalTrigConv = ADC_SOFTWARE_START; //软件触发4 Y# S2 B* b1 @6 W G) o( H
- ADC1_Handler.Init.DataAlign = ADC_DATAALIGN_RIGHT; //右对齐
) ^/ [9 l' l3 _! s - ADC1_Handler.Init.NbrOfConversion = 1; //1个转换在规则序列中 也就是只转换规则序列1
( r1 O" j, Z7 G6 k+ e P - ADC1_Handler.Init.NbrOfDiscConversion = 0; //不连续采样通道数为0- c4 R; k/ m$ {# o
- ADC1_Handler.Init.DMAContinuousRequests = DISABLE; //关闭DMA请求
: O2 ` X8 h# V0 w5 a - ADC1_Handler.Init.EOCSelection = DISABLE; //关闭EOC中断4 i5 ^' B6 L( H; d h2 P, R
- HAL_ADC_Init(&ADC1_Handler); //初始化& k1 C& u* f( a. u" P& ~; O
- 6 V. q* D& b" Z! b! I- c0 O% I/ M
- ADC1_ChanConf.Channel = ADC_CHANNEL_5; //通道5 PA5
) ]. g# w- G( p! ^. \+ j8 L - ADC1_ChanConf.Rank = 1; //1个序列- Z% J5 ^, X6 H' b
- ADC1_ChanConf.SamplingTime = ADC_SAMPLETIME_480CYCLES; //采样时间/ O2 C6 ?' C+ r: X
- ADC1_ChanConf.Offset = 0;
2 u" @4 }3 M6 s! w - HAL_ADC_ConfigChannel(&ADC1_Handler, &ADC1_ChanConf); //通道配置0 N6 |. S. g1 G- _, S
# I. m `$ N+ Q( |- }
# x' |, [" L) ~/ I% Q( J! t2 Y - & r6 Z& R; J1 A+ U7 d
- //ADC底层驱动,引脚配置,时钟使能: d" {/ {# W. r- o3 M
- //此函数会被HAL_ADC_Init()调用' v. _; c, t) u, l
- //hadc:ADC句柄
4 x' k& } _ I - void HAL_ADC_MspInit(ADC_HandleTypeDef *hadc)1 t: C% U8 N/ q3 r8 l4 q4 ]
- {
4 n" x! Z e& d5 O) S1 |- ? - GPIO_InitTypeDef GPIO_Initure;9 L4 y3 w. B% p& x1 ?
- __HAL_RCC_ADC1_CLK_ENABLE(); //使能ADC1时钟) g0 j# m; x3 R# I
- __HAL_RCC_GPIOA_CLK_ENABLE(); //开启GPIOA时钟- r7 [% k! ~3 O) ~' p3 t, i; k
* ~( H, K+ h8 F( I- X a- GPIO_Initure.Pin = GPIO_PIN_5; //PA5! G! { D* ]& v7 @! v! y' t
- GPIO_Initure.Mode = GPIO_MODE_ANALOG; //模拟
& c& L) E; |: ?8 \; } - GPIO_Initure.Pull = GPIO_NOPULL; //不带上下拉! k1 S' v; `/ J" v* D, F
- HAL_GPIO_Init(GPIOA, &GPIO_Initure);
; \7 |+ q! j6 r4 [, u - }0 P* ~& B6 z; {6 i. ~- I9 u
- & C5 Y5 h& I) H' e4 I
- //获得ADC值
5 M+ L l! q" O5 f ]4 y - //ch: 通道值 0~16,取值范围为:ADC_CHANNEL_0~ADC_CHANNEL_16: j/ Q! X F% @" z" @$ O
- //返回值:转换结果4 x4 z, G' K. S+ B
- u16 Get_Adc()" z, u; A# J. f# [
- {$ m' N$ z4 g. ?3 p
- HAL_ADC_Start(&ADC1_Handler); //开启ADC% D6 Q. \( N4 D# G7 V* E, C5 C8 t
- HAL_ADC_PollForConversion(&ADC1_Handler, 10); //轮询转换
9 A- d6 j5 V" A6 |0 {' T - return (u16)HAL_ADC_GetValue(&ADC1_Handler); //返回最近一次ADC1规则组的转换结果
/ c) p6 r4 D# m- p) p - }
5 X: t0 O/ |4 J& L
复制代码
2 k# t: u! J+ l4 p* Smain.c中,主函数初始化之后,直接读取adc的值,并打印。1 X, b# U! r: \5 J; ^/ q) h
- #include "sys.h"; u9 S% g X- r+ y
- #include "delay.h"
1 h4 Y* ]& S" G/ D - #include "usart.h"
% ~( ?" H2 o6 }& Y - #include "adc.h"
( q1 U2 g; [& W5 x" ]- H6 m - , z- ~- {+ e: H- r7 j. x: T( L8 ]& u# G
- int main(void)
5 {0 i! P& O$ M7 s( F - {) |0 I# ~+ P* Y6 a2 m4 t; q/ E0 [4 q
- u16 adcx;# j9 R& i2 |2 y$ s( i6 ~3 E9 \% V8 m
- Cache_Enable(); //打开L1-Cache. w8 F; [* y1 U
- HAL_Init(); //初始化HAL库9 c$ i3 l" ]3 l
- Stm32_Clock_Init(432, 8, 2, 9); //设置时钟,216Mhz c% Z& T9 a x; z$ u$ X
- delay_init(216); //延时初始化4 x! a2 D# `; y$ I8 A% [+ m0 y
- uart_init(115200); //串口初始化$ {8 Z) `" |) f: f) O
- MY_ADC_Init(); //初始化ADC1通道5
+ W% Z- b) X7 {) ? - ) v8 b1 G2 t, w, v5 q/ k2 j/ p
- while (1)
1 K1 i! i3 K/ A, k" E7 p - {
+ o& U* r: }" S2 a; K' A9 k3 v - adcx = Get_Adc(); //获取通道5的转换值,20次取平均1 @% m6 Q3 e2 T+ k
- printf("%d\r\n", adcx);' K7 z u2 r% ^1 W: C8 |
- delay_ms(250);
( C/ H7 h8 s: T: F! [ - }
5 s3 ]1 N6 m" w$ p - }
2 H& P! \# p% p
复制代码 6 f/ d+ c5 t. n$ g" W% B- T
如果需要对多个通道进行轮询读取,可以稍微修改一下函数Get_Adc,在每次读取之前设置一下需要转换的通道:
/ [5 l. J* X% ~7 e9 _" w- //获得ADC值/ p. a7 D! E: |. H3 j9 d% L
- //ch: 通道值 0~16,取值范围为:ADC_CHANNEL_0~ADC_CHANNEL_16
4 Q* l+ ^/ u6 ]# Y* E - //返回值:转换结果: Q% G& C" R1 F- Z1 @
- u16 Get_Adc(u32 ch)
( q2 J& v+ G3 V4 E" E* B - {
. H+ p/ a6 z' o4 V. V" J& {% L$ T: \& `5 X - ADC_ChannelConfTypeDef ADC1_ChanConf;
$ i; ~4 y& M5 N& B5 W5 H, Z -
6 R* l% R/ l4 D' w - ADC1_ChanConf.Channel=ch; //通道$ x8 J% m, Y0 X( P" J
- ADC1_ChanConf.Rank=1; //1个序列8 n) c! S$ I- @4 u" z
- ADC1_ChanConf.SamplingTime=ADC_SAMPLETIME_480CYCLES; //采样时间4 ^* C* C3 s% l0 C$ _; s$ I6 n/ c
- ADC1_ChanConf.Offset=0; 8 O6 }' i6 O! l C6 h9 @
- HAL_ADC_ConfigChannel(&ADC1_Handler,&ADC1_ChanConf); //通道配置; N4 q2 L, x6 o# B- f3 ^) h
-
5 l9 Y% C& I* e/ P1 {( q - HAL_ADC_Start(&ADC1_Handler); //开启ADC
; l# Y% u1 ?+ a& v1 u7 ]* w - 2 M: v+ N. r; y
- HAL_ADC_PollForConversion(&ADC1_Handler,10); //轮询转换" T7 D4 g4 F& f1 [! O' N: j
- : x$ h* S1 V; y& Z$ V
- return (u16)HAL_ADC_GetValue(&ADC1_Handler); //返回最近一次ADC1规则组的转换结果) w/ x/ K6 j8 X$ \! R2 c
- }
复制代码 ————————————————, r6 E+ Z' H# m- Q- P. ]% [! G: y
版权声明:小盼你最萌哒
0 _# ~3 d# t- g0 c4 V如有侵权请联系删除7 F% _: ]8 t7 ^" h
s3 m1 A% G& @, E: _& R/ O/ y1 y& R F9 h- v2 [/ j
|