基于HAL库,实现最简单ADC采集。5 q L X ]/ N, W2 Q; Z* N; e
第一步,使用CubeMX配置时钟。
3 s( r- |6 w1 H, A# N. R) s( o# a3 q) L ]; c! X; o, K
# l* _" D7 L# r1 v7 B2 J% \( Z然后是adc的配置:, i" l6 K# n8 q, ?! m5 E8 o
/ Q! R/ x1 g1 L" K0 H) _3 Q7 f6 b8 k: z0 N, u; n2 b8 F& _
5 i6 U5 B7 e) |7 f! E% V! N
将,稍微修改一下风格,并手写头文件和源文件。4 g2 \) f) M3 b0 [6 _$ E( g# _6 m0 P
; p5 T, }3 q% g8 v) X" P
adc.h很简单,就不说了。- g3 i" Q9 E0 B( {
9 m/ V9 ~ i# _* w- x% T2 {' T( F- #ifndef __ADC_H
) W4 A# D& P" E( d" X; o) n, o" ` - #define __ADC_H9 P) L( ?5 }8 N" d& ?
- #include "sys.h"; Z: `/ }; g8 w/ L( Q* K" t0 j+ J1 W
* T; Y8 \4 q# z- M- void MY_ADC_Init(void); //ADC通道初始化2 }& c1 q! W1 q- t
- u16 Get_Adc(void); //获得某个通道值 ' _ _0 Y Y( p& K4 W
- #endif
复制代码 8 j" W7 b9 ?" z/ m# |
其中,MY_ADC_Init和HAL_ADC_MspInit的内容完全是根据CubeMX生成的代码写的,就改了一个变量名字。Get_Adc则简单了,当我们需要获取adc的值的时候,先HAL_ADC_Start启动ADC,然后HAL_ADC_PollForConversion等待转换完成,最后HAL_ADC_GetValue返回结果。$ t) y, |; V, p0 A1 V/ s7 c
- S' M/ y$ G& g: Z& ^
- #include "adc.h"
0 Z' z; q; G5 _! S6 p3 s - #include "delay.h"+ @0 h/ R, v6 f/ S z2 ]; |9 I0 I& s
4 K7 @9 o; F8 k- 6 J8 e& U- U( {# i! J: U' N
- ADC_HandleTypeDef ADC1_Handler; //ADC句柄
. U, O- [' P( B, j- {, ~! F - ADC_ChannelConfTypeDef ADC1_ChanConf; //ADC通道配置句柄* s9 r! O2 m' Y
- 1 K% T0 ^5 M* X( t
- " L3 v9 q5 A6 ?6 _0 M3 f+ L5 k. O' T% O
- //初始化ADC/ o: R6 n( e( F( x+ k
- void MY_ADC_Init(void). {5 C2 _. S8 f( z+ l% u e
- {& O$ c5 {6 q, @; m
- ADC1_Handler.Instance = ADC1;1 @/ }% W" v( h9 h& b0 ]& b$ m
- ADC1_Handler.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4; //4分频,ADCCLK=PCLK2/4=108/4=27MHZ
% G: t- `* n- s6 o, `& |/ Y8 d2 r - ADC1_Handler.Init.Resolution = ADC_RESOLUTION_12B; //12位模式7 w: _) W7 s0 v! a
- ADC1_Handler.Init.ScanConvMode = DISABLE; //非扫描模式
( C& \- y* {2 z - ADC1_Handler.Init.ContinuousConvMode = DISABLE; //关闭连续转换
* K5 |* H7 E- g' w& D - ADC1_Handler.Init.DiscontinuousConvMode = DISABLE; //禁止不连续采样模式
9 k0 S; |+ S1 ^2 ~& h! d0 x3 s0 n, j - ADC1_Handler.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE; //使用软件触发- }6 d4 u) N- _% F3 W7 A
- ADC1_Handler.Init.ExternalTrigConv = ADC_SOFTWARE_START; //软件触发& L& W' _% e+ E: s1 X4 z
- ADC1_Handler.Init.DataAlign = ADC_DATAALIGN_RIGHT; //右对齐
5 V! k% L3 ^* X. w - ADC1_Handler.Init.NbrOfConversion = 1; //1个转换在规则序列中 也就是只转换规则序列10 x- H% Y1 b }. s
- ADC1_Handler.Init.NbrOfDiscConversion = 0; //不连续采样通道数为0
% m) Y h i3 [ - ADC1_Handler.Init.DMAContinuousRequests = DISABLE; //关闭DMA请求
% H! e1 q: P) f" X - ADC1_Handler.Init.EOCSelection = DISABLE; //关闭EOC中断/ j! O5 n8 }$ u K+ ] q2 j
- HAL_ADC_Init(&ADC1_Handler); //初始化/ l! X; j6 v8 k* ]: v
- ' ?: e' \9 J; D
- ADC1_ChanConf.Channel = ADC_CHANNEL_5; //通道5 PA5
3 u; u& g" T. `& w2 a - ADC1_ChanConf.Rank = 1; //1个序列
& }# m s- T! R n/ n' G - ADC1_ChanConf.SamplingTime = ADC_SAMPLETIME_480CYCLES; //采样时间1 R+ H& L% `( E+ y% b' B. ?. j
- ADC1_ChanConf.Offset = 0;
M; d% N" c( S6 ?8 w - HAL_ADC_ConfigChannel(&ADC1_Handler, &ADC1_ChanConf); //通道配置
N- k9 Q$ O2 A: X& A+ d/ f: p; S - * R6 m$ V6 j/ S
- } s) ^: D, ?; v4 k' h: }; |7 o2 _
- ! ?7 X, j7 F! k' B, e) X
- //ADC底层驱动,引脚配置,时钟使能- W/ A% X9 G3 ~9 `. V% L
- //此函数会被HAL_ADC_Init()调用- r$ f2 X( `' N5 E, [
- //hadc:ADC句柄
V2 q1 r" D0 Y E! |, A/ R - void HAL_ADC_MspInit(ADC_HandleTypeDef *hadc)
' T6 P% f7 E: m$ W- A _! f7 L( H - {
$ r7 u( w* F" V3 X3 m( F5 `8 Y; t$ y - GPIO_InitTypeDef GPIO_Initure;
: p( e7 q) G1 d0 ] - __HAL_RCC_ADC1_CLK_ENABLE(); //使能ADC1时钟
' a! B9 s; H$ l% L - __HAL_RCC_GPIOA_CLK_ENABLE(); //开启GPIOA时钟
: B. I4 ]% { W# C( N - # c" ]) t* d7 y
- GPIO_Initure.Pin = GPIO_PIN_5; //PA5
, v5 L" \6 @* [* S; j - GPIO_Initure.Mode = GPIO_MODE_ANALOG; //模拟
6 @' H" }" X5 z5 @& K - GPIO_Initure.Pull = GPIO_NOPULL; //不带上下拉
, Z8 l$ u/ J5 x' {, `: V - HAL_GPIO_Init(GPIOA, &GPIO_Initure);
( v" h+ z E- R6 ?) t$ g& s9 t, \) B - }4 p5 ~) @/ |3 |7 p9 i0 z8 c
, ^, v! e' r q* s6 W- A* {9 H: ]- //获得ADC值
$ K. ~. {4 k1 m9 {) e. T - //ch: 通道值 0~16,取值范围为:ADC_CHANNEL_0~ADC_CHANNEL_16
7 w& n$ B. Z, }6 B4 F3 d - //返回值:转换结果
, g4 Y; F7 n/ F }9 o1 X+ {7 {# F* L- s - u16 Get_Adc() A! y& r! c. E/ m# j% @# M
- {( d' `5 Y1 U+ @
- HAL_ADC_Start(&ADC1_Handler); //开启ADC
( S% Z& ^8 m& e7 x4 J5 i, I: w: X - HAL_ADC_PollForConversion(&ADC1_Handler, 10); //轮询转换
$ M0 i1 ~: [2 `& s! L( Z, y/ M! K' q - return (u16)HAL_ADC_GetValue(&ADC1_Handler); //返回最近一次ADC1规则组的转换结果$ [5 g [, |3 @7 |
- }
复制代码
2 u7 b0 m; u. amain.c中,主函数初始化之后,直接读取adc的值,并打印。7 D5 c' n4 N9 k% h
+ B0 f; \) O9 Q5 x! z8 n' {
- #include "sys.h"
4 W7 f- b5 V7 t - #include "delay.h"
/ a. z" c. V2 V9 N. h3 j) d - #include "usart.h"& W/ w$ _( R3 A: U% `- n
- #include "adc.h": K$ S# `) S0 n$ y: o
( t" g0 W; m& o$ `! |- int main(void)- q- q6 J; F- Q; ?+ |& {$ Z% g
- {
+ H" Z0 J1 C9 Q - u16 adcx;! i7 ]: @; l4 ?9 E9 ~' x6 E; B, e
- Cache_Enable(); //打开L1-Cache
- W3 _& l; e5 Q+ i3 g7 f+ n$ y - HAL_Init(); //初始化HAL库9 W1 q$ W6 U3 Z% t$ v
- Stm32_Clock_Init(432, 8, 2, 9); //设置时钟,216Mhz
; W" W6 r3 o% r( \) @$ f) W: n - delay_init(216); //延时初始化3 p. k- f& P1 e& o. P& B' [9 u
- uart_init(115200); //串口初始化
$ u& z0 q( v; D( i; \2 O& @5 @ - MY_ADC_Init(); //初始化ADC1通道54 P E7 q! ~1 H- r7 G' B/ A, }
-
5 |8 y6 z+ P6 C, o0 u8 ?: [- n8 V4 F1 I - while (1)
/ V7 n; n* B3 Q; r* Q1 l - {
- \+ i! w! u( z2 f9 i; v0 K - adcx = Get_Adc(); //获取通道5的转换值,20次取平均
% K4 Z9 R/ w$ @9 `- Y& r' u - printf("%d\r\n", adcx);; k) Q) e T4 W9 y6 A
- delay_ms(250);( D) Z1 G7 k0 ]& E
- }
. G% D! w9 W4 p& ]- g: r; z - }
复制代码
& Q' T, C0 s. _' l- ]如果需要对多个通道进行轮询读取,可以稍微修改一下函数Get_Adc,在每次读取之前设置一下需要转换的通道:3 @, u' b. |2 u, `
, j4 T. F) V4 ^' `$ u- //获得ADC值5 `8 u+ x& \5 C( k
- //ch: 通道值 0~16,取值范围为:ADC_CHANNEL_0~ADC_CHANNEL_16
/ E! m% q6 R! i, q: A7 Y T% F - //返回值:转换结果
" f7 D$ q4 p e" l F# U4 L* A" m - u16 Get_Adc(u32 ch)
; } S: L2 \7 M0 L - {
* Z0 \; A5 s1 ?) u. j1 {3 r - ADC_ChannelConfTypeDef ADC1_ChanConf; h3 N9 H% ~2 O* ~
( f. P* f& g0 V/ E$ @- ADC1_ChanConf.Channel=ch; //通道- L. Z. k- S7 D) M& h; O7 I9 _4 G8 i
- ADC1_ChanConf.Rank=1; //1个序列
; P! V8 I* q, J% B8 N - ADC1_ChanConf.SamplingTime=ADC_SAMPLETIME_480CYCLES; //采样时间
. B' m: K: o# s! _ - ADC1_ChanConf.Offset=0;
/ T( E/ m2 r- }0 o - HAL_ADC_ConfigChannel(&ADC1_Handler,&ADC1_ChanConf); //通道配置. w; h* x+ w9 v8 c
- $ \0 G# S: \4 T4 I
- HAL_ADC_Start(&ADC1_Handler); //开启ADC4 b" D: v/ p& f* N
- B9 d, t0 r) u& h7 A
- HAL_ADC_PollForConversion(&ADC1_Handler,10); //轮询转换
- `& k) j/ R# u
+ H, `; v, h- Q- return (u16)HAL_ADC_GetValue(&ADC1_Handler); //返回最近一次ADC1规则组的转换结果
- }9 X5 p* b# G - }$ h1 n# S' r& r! }" _! z5 j) x) M
复制代码
0 l+ p0 T8 t, B7 _ t8 V! v* r) _0 K2 I
4 ~" N! ~/ B- L8 `2 g4 z( N, k
|