基于HAL库,实现最简单ADC采集。
2 z/ z2 x/ e& b8 ?2 U第一步,使用CubeMX配置时钟。" m7 Y- V5 h' X' `/ ^2 f! L9 n% J
$ J$ I& u6 l& ~( ^" l
3 f( y& u/ m" D* O3 E' k: b- U9 c; Y% v/ o
然后是adc的配置:
0 Y/ }6 c+ |" C7 p* [. W: r/ N9 B& T5 n
! {4 u+ d M3 o3 U. u T3 N* Z/ k) d1 O
将,稍微修改一下风格,并手写头文件和源文件。
1 m2 e7 q9 p! f! x7 G7 K
. l! H3 Y6 W9 E& |1 Wadc.h很简单,就不说了。
/ S# _" D. z3 |- k/ J/ V- #ifndef __ADC_H9 F8 o# B! a2 s! m' B
- #define __ADC_H
* A) P: e" w% z* d3 F0 b - #include "sys.h"2 ?: ~1 V7 @( E: `/ R* G$ q' {
5 o9 }0 x! L6 A- void MY_ADC_Init(void); //ADC通道初始化
, F4 d1 n* N. C0 s' D& L - u16 Get_Adc(void); //获得某个通道值 " t4 r4 Q3 ^5 J, X) j
- #endif
: x& |: k0 H. q! \2 z
复制代码
* S# j' Q0 c& J; b) e" C$ {* E其中,MY_ADC_Init和HAL_ADC_MspInit的内容完全是根据CubeMX生成的代码写的,就改了一个变量名字。Get_Adc则简单了,当我们需要获取adc的值的时候,先HAL_ADC_Start启动ADC,然后HAL_ADC_PollForConversion等待转换完成,最后HAL_ADC_GetValue返回结果。
; N$ Y% H" ?" y/ N; i0 Z( C1 v- z- #include "adc.h") b! @6 D- e- b* i- h1 w, H
- #include "delay.h"+ q# J- d% S' V, k1 B8 J
- 9 o# {/ ?. k: B7 c/ l) n: A* \
- 4 f% C! ~- ^: l, p
- ADC_HandleTypeDef ADC1_Handler; //ADC句柄
" D9 E( w) Y4 Q) B - ADC_ChannelConfTypeDef ADC1_ChanConf; //ADC通道配置句柄( a. M2 |+ V2 j4 K* t3 v; ^
- 3 O2 A& G, U; [$ h* q
- & A; s7 w5 [ [. z, x, X& K
- //初始化ADC
0 ^+ e9 q$ }$ Q# z! w - void MY_ADC_Init(void)2 U) _4 b0 i$ J6 j5 v2 C
- {
4 u7 a5 {& ~# \5 O% s# [ - ADC1_Handler.Instance = ADC1;- M/ Z& [; V4 R0 S/ _. z
- ADC1_Handler.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4; //4分频,ADCCLK=PCLK2/4=108/4=27MHZ6 a6 O# |+ G2 x# g2 E0 `
- ADC1_Handler.Init.Resolution = ADC_RESOLUTION_12B; //12位模式/ ~- X' a! w5 I
- ADC1_Handler.Init.ScanConvMode = DISABLE; //非扫描模式+ \8 S" M. \" _/ h4 o$ g. |
- ADC1_Handler.Init.ContinuousConvMode = DISABLE; //关闭连续转换" n- F% L, U5 q, R
- ADC1_Handler.Init.DiscontinuousConvMode = DISABLE; //禁止不连续采样模式
: q' M' ~/ O5 H0 A& w8 ] - ADC1_Handler.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE; //使用软件触发
2 p" _: ?+ l/ N* K - ADC1_Handler.Init.ExternalTrigConv = ADC_SOFTWARE_START; //软件触发/ [2 p/ c" A, m0 J4 S, m, O1 w7 l0 C4 g
- ADC1_Handler.Init.DataAlign = ADC_DATAALIGN_RIGHT; //右对齐
# F. X9 ]8 v) W, t+ I - ADC1_Handler.Init.NbrOfConversion = 1; //1个转换在规则序列中 也就是只转换规则序列1- N$ r* l" L3 X- ?
- ADC1_Handler.Init.NbrOfDiscConversion = 0; //不连续采样通道数为0( ^0 G0 ?" {1 }1 [9 s) I: |1 B! J
- ADC1_Handler.Init.DMAContinuousRequests = DISABLE; //关闭DMA请求1 j1 P. K1 y' o1 F% z" z" k
- ADC1_Handler.Init.EOCSelection = DISABLE; //关闭EOC中断$ @: V+ V G) o$ o2 H6 o
- HAL_ADC_Init(&ADC1_Handler); //初始化7 g$ R! J) d0 J3 F& L* Z! Y. @
- 7 f1 r: E2 R. p, `* l- h5 D: p# C
- ADC1_ChanConf.Channel = ADC_CHANNEL_5; //通道5 PA56 \8 [6 {* ?' _8 H# u
- ADC1_ChanConf.Rank = 1; //1个序列
9 l. _& \/ i- S$ b - ADC1_ChanConf.SamplingTime = ADC_SAMPLETIME_480CYCLES; //采样时间9 I! T* M& O% o# Z8 t
- ADC1_ChanConf.Offset = 0; T4 [+ n+ ]2 C" I8 v0 _
- HAL_ADC_ConfigChannel(&ADC1_Handler, &ADC1_ChanConf); //通道配置! G W7 m8 c+ S1 [/ q! i1 H( \1 Z( g
5 d- J: } o5 q- {2 w0 S$ q- }
0 {. o4 d8 O' [ p) ^4 i2 q
3 V# N3 B6 T: S- //ADC底层驱动,引脚配置,时钟使能
$ w% T5 w& h1 B5 d - //此函数会被HAL_ADC_Init()调用3 ^( ]3 O4 J/ c
- //hadc:ADC句柄/ w. a! z- Z6 R `" ~/ W9 d
- void HAL_ADC_MspInit(ADC_HandleTypeDef *hadc) W# K# U4 v5 r; R/ f& H+ ]3 @
- {3 N* p) l- p: ~( ^; W3 a
- GPIO_InitTypeDef GPIO_Initure;. s9 H, w1 h+ b# C' p7 Z
- __HAL_RCC_ADC1_CLK_ENABLE(); //使能ADC1时钟
! V( r) `" q6 S |6 o - __HAL_RCC_GPIOA_CLK_ENABLE(); //开启GPIOA时钟: O4 v: B9 X" M- E6 v
- ( T! g) l2 ?: R) k
- GPIO_Initure.Pin = GPIO_PIN_5; //PA5
9 J/ M3 O8 ~. g: ~* S - GPIO_Initure.Mode = GPIO_MODE_ANALOG; //模拟
' u1 {; _6 h k8 A2 R5 Y: z - GPIO_Initure.Pull = GPIO_NOPULL; //不带上下拉' \6 i; C8 a5 d1 m* c
- HAL_GPIO_Init(GPIOA, &GPIO_Initure);' @9 k+ N4 k# ~, _
- }
% c% l% E9 L$ r; o& ~
2 s( Q; j4 r$ F) V- //获得ADC值
4 |! ^* u$ i3 v9 H# ?# K4 {' k0 m1 t- _ - //ch: 通道值 0~16,取值范围为:ADC_CHANNEL_0~ADC_CHANNEL_163 ?* ]' m# |5 L0 t/ s9 Q9 x6 B5 S& e
- //返回值:转换结果
! R. A" q1 q% w* l - u16 Get_Adc()
$ e, H$ r7 V2 Z1 n' A1 }# Z' Z - {9 c* @9 R( v/ \1 [0 a& l' j
- HAL_ADC_Start(&ADC1_Handler); //开启ADC
0 j+ k2 U5 W$ k - HAL_ADC_PollForConversion(&ADC1_Handler, 10); //轮询转换; t1 e4 ]4 ^% m, @4 z: K
- return (u16)HAL_ADC_GetValue(&ADC1_Handler); //返回最近一次ADC1规则组的转换结果
0 _9 E" g3 y* K4 d - }
5 r7 X; H' o/ K5 {# B: [
复制代码
( D4 i" H. \( f) s, Smain.c中,主函数初始化之后,直接读取adc的值,并打印。
. C6 E# k+ D5 g, O% _- #include "sys.h"
6 p* Y* @; n5 g5 M- I5 v b8 B f - #include "delay.h"
! x5 g" s6 [% Q* p- z - #include "usart.h"" Y) o2 a) _; X; f4 {! M3 Z4 ]/ ~( a
- #include "adc.h"0 @3 i' ]2 F" {- E& q
- # A( T% z% a2 |6 s7 H! s y& W
- int main(void)& l* C; _ i @6 n- b
- {
1 q- A9 {2 S/ S - u16 adcx;
2 N2 f8 k, ^7 C4 a - Cache_Enable(); //打开L1-Cache+ {* ^, C* u6 M/ t. S
- HAL_Init(); //初始化HAL库
, |' V8 f" q4 W) q - Stm32_Clock_Init(432, 8, 2, 9); //设置时钟,216Mhz% J1 s5 F* L' A- W
- delay_init(216); //延时初始化0 r9 D6 o1 N5 u
- uart_init(115200); //串口初始化( Q* ` q% ^) V% ~4 B; s- h* t m
- MY_ADC_Init(); //初始化ADC1通道5
0 Z, O9 e1 G0 ?- C% G7 i ` - 5 U' o' |2 k& i: Z7 v! q2 s+ j
- while (1)
9 w f5 z! {& z% Y1 K+ k* L - {, c' ]5 L! |8 m+ y! Y/ i. [3 J
- adcx = Get_Adc(); //获取通道5的转换值,20次取平均4 p! V& \, m' Z
- printf("%d\r\n", adcx);& h N5 D, T+ p6 `
- delay_ms(250);
3 n3 W/ f- w V4 x j4 r6 D - }2 l& a/ e1 w( s- C1 X: w$ p0 P7 b
- }
, [1 f, b0 g& c- X7 h
复制代码
% ^+ l" ~8 ~; C9 O3 r& R" N5 R如果需要对多个通道进行轮询读取,可以稍微修改一下函数Get_Adc,在每次读取之前设置一下需要转换的通道:
- Q8 M9 r$ n# L1 s9 @0 T- //获得ADC值1 N( Y( l& v( x8 `
- //ch: 通道值 0~16,取值范围为:ADC_CHANNEL_0~ADC_CHANNEL_164 g2 R+ N) A% Q* I/ V+ \# {. A
- //返回值:转换结果2 Z: [* m$ `% `& s
- u16 Get_Adc(u32 ch)
$ k# s$ F3 x4 _5 a - {
- C9 j/ c' Q- R2 E - ADC_ChannelConfTypeDef ADC1_ChanConf;5 v/ y- K+ t' @5 \7 c1 [7 `
- " N$ W" Y! M1 C9 P6 d
- ADC1_ChanConf.Channel=ch; //通道: E" W4 s; ?1 f1 \& T7 n5 c
- ADC1_ChanConf.Rank=1; //1个序列
1 s0 V( ~& k r& O8 n" i$ t - ADC1_ChanConf.SamplingTime=ADC_SAMPLETIME_480CYCLES; //采样时间
& U) O* e& s0 z E& [( X6 Z1 r - ADC1_ChanConf.Offset=0;
3 d1 E7 Z# O* V - HAL_ADC_ConfigChannel(&ADC1_Handler,&ADC1_ChanConf); //通道配置6 F8 A9 Z% a5 r' |
- . X, M0 F2 g9 F) L
- HAL_ADC_Start(&ADC1_Handler); //开启ADC
# {$ a2 c8 P) Y m8 a -
: `) j0 U! y Y- u - HAL_ADC_PollForConversion(&ADC1_Handler,10); //轮询转换
7 W# }( W, z4 Y a% a: X/ p9 U& b - 2 D# h5 V: o3 v) |5 N
- return (u16)HAL_ADC_GetValue(&ADC1_Handler); //返回最近一次ADC1规则组的转换结果3 m# Y3 D0 l- a9 h& n
- }
复制代码 ————————————————
3 n h. {" O8 c7 y: k8 f) d5 s" ~版权声明:小盼你最萌哒
, h' j }/ f8 t" q! K0 n) b& K1 X, t4 R如有侵权请联系删除
6 Z. P+ X8 A! e2 |- L% ]' n- y( p
3 t; M- K$ E- M) e' a) {2 g
|