实现了定时器加DMA的等周期采集。
' z5 O4 O7 F+ X- H5 Wadc.c:' E: k9 Q4 A/ U; c) ^# B9 m
- #include "adc.h"8 p$ v2 l- Q& g* k8 N
- #include "delay.h"
: ?0 |. f/ w# W, y - * l6 e' n! f+ T* V5 E
- ADC_HandleTypeDef ADC1_Handler;//ADC句柄& K, Y3 o' s- w
- DMA_HandleTypeDef ADC1DMA_Handler;
( {" O1 u) z& l( d3 s - ADC_ChannelConfTypeDef ADC1_ChanConf;
+ \6 d s+ a0 @, _+ q - 4 C# }# e- e3 y; n9 q
- TIM_HandleTypeDef TIM2_Handler;
* u5 |# B, s) G( w/ r - TIM_OC_InitTypeDef TIM2_CH2Handler;2 O2 w$ T% C" W3 A4 v" f
- uint16_t buffer[128];0 q2 J6 e% \! _% N
8 r8 d; p% H9 z$ W- static void MX_TIM2_Init(void)
0 e/ R2 r' \0 Q; o6 y* u0 f0 | - {
" c; H2 I- F6 Z+ b5 d) {( Z - __HAL_RCC_TIM2_CLK_ENABLE();9 A: f1 }/ d4 n' N9 O/ |" C4 C
-
* Y1 p$ _4 S( e4 u# Q9 o' L - HAL_NVIC_SetPriority(TIM2_IRQn, 1, 3);& _7 ?! V8 O6 ?( G
- HAL_NVIC_EnableIRQ(TIM2_IRQn);
4 {% e+ q; r( u - % Z O: r1 ]" x* A2 ]" k7 d
- TIM2_Handler.Instance = TIM2;
: b! s* T; W( M0 ]; \ - TIM2_Handler.Init.Prescaler = 10800;; |! o: I" s/ b' |
- TIM2_Handler.Init.CounterMode = TIM_COUNTERMODE_UP;2 X$ j2 S' |1 w1 b7 d" a/ ]/ x/ P
- TIM2_Handler.Init.Period = 20000;. z; `$ @: C* B- y8 d7 W) [
- TIM2_Handler.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;# ~& h) G* c! v( C" {# f# c
* x! ~0 a* s4 {+ p8 S' J- HAL_TIM_PWM_Init(&TIM2_Handler);
6 o% J" G+ Y0 A
- a2 {6 j; Q2 S0 `- + |8 n! K( y- S( I- X% C( R5 E
- TIM2_CH2Handler.OCMode = TIM_OCMODE_PWM1;2 T1 h) I3 c6 K% f. d: y- w& W
- TIM2_CH2Handler.Pulse = 10000;
$ A, I4 e. l" C. J* C - TIM2_CH2Handler.OCPolarity = TIM_OCPOLARITY_HIGH;
! M$ `7 w" g5 V: E - TIM2_CH2Handler.OCFastMode = TIM_OCFAST_DISABLE; B; o$ R0 M0 @# l& ~2 j v
- HAL_TIM_PWM_ConfigChannel(&TIM2_Handler, &TIM2_CH2Handler, TIM_CHANNEL_2) ;
% b/ m2 Q; v( G' p* ?0 D8 ~ - 1 W7 f4 q# w/ L3 L
+ J& U3 |! b& s4 k- __HAL_TIM_ENABLE_IT(&TIM2_Handler, TIM_IT_UPDATE);! E2 M* v; S) J* W
- TIM_CCxChannelCmd(TIM2_Handler.Instance, TIM_CHANNEL_2, TIM_CCx_ENABLE);
7 C( x: Y; J$ l3 k6 n - __HAL_TIM_ENABLE(&TIM2_Handler);
& D! w( x0 S0 _: t; b/ H* G( ^7 ~ - }
) T5 o7 [# C( V& M. A$ t
+ J% [: I% C j$ E& d. L/ Z2 B( R
, C: O* i$ ^. C# H0 ?- void TIM2_IRQHandler(void)
: R3 F$ Q! r; ~ - {
% V& o0 i8 R8 y# e - HAL_TIM_IRQHandler(&TIM2_Handler);3 O3 W+ G- b' ?7 s! G8 a6 K- X6 \
- }; F, I# @: s4 ~7 [4 k2 H" e4 f
4 a# \8 W% O/ O5 V
3 D: Y: U+ j( }- void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
6 I4 c( B2 e+ G/ Y6 l/ _7 @ - {2 i& L# w3 r9 Y5 x3 d2 t
- if (htim == (&TIM2_Handler))
/ ~6 M7 k( @. n9 }" F - {. @' Y$ K6 A, z6 Y- j
- printf("timer irq\r\n");
4 y9 e0 H- |2 P. X% O6 Y - }2 `% Z! k- B( ^* _* I$ o
- }
0 n# U- K! g6 n1 K& U0 Y - 1 r0 c, e3 j; J# I- U
- : p: l/ |$ P6 Q. S) n
- void HAL_TIM_PWM_MspInit(TIM_HandleTypeDef *htim)
& D5 F9 u: @3 z- d& g2 Q - {
( g; J# s6 n1 }9 a1 H - GPIO_InitTypeDef GPIO_InitStruct = {0};3 g; T' p! p. o# D1 d7 u, e
4 B4 g* S% ?$ S' g7 y, i- __HAL_RCC_TIM2_CLK_ENABLE();
, G1 E/ q7 _; ^7 y - __HAL_RCC_GPIOA_CLK_ENABLE();5 E- Z/ U! d5 e9 ^
- GPIO_InitStruct.Pin = GPIO_PIN_1; ?4 N& Q1 g, Q9 B+ ^5 M6 y
- GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
' m4 e' }) W. x0 i# r: { - GPIO_InitStruct.Pull = GPIO_NOPULL;
* X+ s1 [3 U- N- T; w$ v# F ` - GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;# F0 B7 x5 a2 k* A4 y& `8 M( E7 O j
- GPIO_InitStruct.Alternate = GPIO_AF1_TIM2;
: m, `8 g8 r$ P' l# g- q, P. F - HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
9 c, i% P8 {1 z7 b* o |6 b - }- y' h L+ [. T9 e) `. M$ J
" K$ |) J; D/ W% j) }$ E6 g- 6 y5 F ]- b) H' c# O
2 G; W0 _7 N5 \) _0 ~- //初始化ADC7 R1 f% s/ Y$ [
- //ch: ADC_channels
0 k( _" K. T5 D1 _) U7 g9 h - //通道值 0~16取值范围为:ADC_CHANNEL_0~ADC_CHANNEL_16$ A9 h8 S1 j2 X( M; _
- void MY_ADC_Init(void)
6 L% w. p5 a; W2 h# [" S8 r - {. I( p' C, S3 l% v
- __HAL_RCC_DMA2_CLK_ENABLE();7 K; I6 B% ~8 K/ u4 ~4 e8 b
- HAL_NVIC_SetPriority(DMA2_Stream0_IRQn, 0, 0);& S6 V/ n1 r/ w. c
- HAL_NVIC_EnableIRQ(DMA2_Stream0_IRQn);) D4 o. k3 [0 Y$ u5 o6 @( u3 P. Z
- 9 W3 i. X, u: i7 f! E& C$ m
- ADC1DMA_Handler.Instance = DMA2_Stream0;8 w F! A t+ w1 S6 I( j
- ADC1DMA_Handler.Init.Channel = DMA_CHANNEL_0;* n# R* ?" R- h* \2 r r
- ADC1DMA_Handler.Init.Direction = DMA_PERIPH_TO_MEMORY;
8 y$ K1 j* k2 Z! g - ADC1DMA_Handler.Init.PeriphInc = DMA_PINC_DISABLE; //外设非增量模式
2 p. K" y6 U6 p6 } - ADC1DMA_Handler.Init.MemInc = DMA_MINC_ENABLE; //存储器增量模式
9 L" P. ^1 W$ ]* W9 L* H6 x; O - ADC1DMA_Handler.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; //外设数据长度:16位
" S8 I e& a: ` - ADC1DMA_Handler.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; //存储器数据长度:16位2 @" L% w/ r5 m4 x/ y
- ADC1DMA_Handler.Init.Mode = DMA_CIRCULAR; //传输一次就结束
/ E- o d6 r2 g0 o9 c( x% r" C - ADC1DMA_Handler.Init.Priority = DMA_PRIORITY_LOW; //中等优先级5 d: b# g# r5 H/ l7 k
- ADC1DMA_Handler.Init.FIFOMode = DMA_FIFOMODE_DISABLE; /* 禁止FIFO*/
) A8 S; B) i! X, D" R6 a/ w) O
0 b `* v, U. n9 I5 y/ e) M5 w- HAL_DMA_Init(&ADC1DMA_Handler);1 |" Z" e9 l. F2 \3 m3 I3 |+ a2 b4 W
- 3 e j$ b1 ^6 f6 `4 G7 W3 T
- __HAL_LINKDMA(&ADC1_Handler, DMA_Handle, ADC1DMA_Handler); //将DMA与ADC联系起来- ]! U: }# g2 C
- 0 k/ a% b/ O/ C# ^* C$ {
$ ~, p: ]$ X0 f; y) Y% h; b) l8 F) z) D- ADC1_Handler.Instance = ADC1;
5 D2 P3 |3 `* b9 P - ADC1_Handler.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4; //4分频,ADCCLK=PCLK2/4=108/4=27MHZ
2 Y. |7 g- \5 ^- x2 g7 l& v: M - ADC1_Handler.Init.Resolution = ADC_RESOLUTION_12B; //12位模式( G1 l- Y1 [4 ?0 G; k3 }% U
- ADC1_Handler.Init.ScanConvMode = ENABLE; //非扫描模式! P& ^0 R# ], k- M* C6 v4 s( m
- ADC1_Handler.Init.ContinuousConvMode = DISABLE; //关闭连续转换
3 q) p& C1 W& U4 m - ADC1_Handler.Init.DiscontinuousConvMode = DISABLE; //禁止不连续采样模式
, U, P+ k q, W - ADC1_Handler.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_RISING; //使用软件触发
3 j+ s' e- a# c9 P; F7 { - ADC1_Handler.Init.ExternalTrigConv = ADC_EXTERNALTRIGCONV_T2_CC2; //软件触发
! c t: C4 ^8 a& F4 f L# b - ADC1_Handler.Init.DataAlign = ADC_DATAALIGN_RIGHT; //右对齐
" ~2 n4 n/ `) Q) Q - ADC1_Handler.Init.NbrOfConversion = 2; //1个转换在规则序列中 也就是只转换规则序列1
) l# f$ p- W1 G( p& I q( _: d; c# Y) ] - ADC1_Handler.Init.DMAContinuousRequests = ENABLE; //关闭DMA请求
# B9 _# g4 W5 a - ADC1_Handler.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
?* _5 W o/ H4 d+ r - HAL_ADC_Init(&ADC1_Handler);( W/ M7 M9 L& x0 C2 q
- " C2 s5 K. ]$ L3 F/ H& t( c+ X' ?
- ADC1_ChanConf.Channel = ADC_CHANNEL_5; //通道( I) ~& X* O1 R$ o
- ADC1_ChanConf.Rank = 1; //序列1
; _4 P+ h+ |0 j$ c+ }) [ - ADC1_ChanConf.SamplingTime = ADC_SAMPLETIME_480CYCLES; //采样时间$ p6 [8 f2 t: N |$ z7 r8 P' l) J" i
- ADC1_ChanConf.Offset = 0;' L) p: r5 } G
- HAL_ADC_ConfigChannel(&ADC1_Handler, &ADC1_ChanConf); //通道配置& j/ ~. j6 K+ ]" l6 i
$ u8 T0 z3 l$ m: O. s* Z- ADC1_ChanConf.Channel = ADC_CHANNEL_6; //通道' O$ s" S0 L/ V" N
- ADC1_ChanConf.Rank = 2; //序列2
" c6 m# n; I3 M; D: X" @ - ADC1_ChanConf.SamplingTime = ADC_SAMPLETIME_480CYCLES; //采样时间4 K7 l; k- T& `- j
- ADC1_ChanConf.Offset = 0;# _; y' u# A; ^: L+ S
- HAL_ADC_ConfigChannel(&ADC1_Handler, &ADC1_ChanConf); //通道配置
! p+ x4 H- a# g5 L- J
7 r/ Y# X. T- i: q5 k b; c Q0 Q- * M' _$ ^! E) g
- MX_TIM2_Init();
( l# Y8 a8 V) A) b) }3 T& Y - HAL_ADC_Start_DMA(&ADC1_Handler, (uint32_t *)buffer, 128);
+ T0 o! ^# e5 U - }
9 _: s; ?1 M/ O1 v4 [8 j
6 _- V% P; l7 U% x& B9 s- Z+ |- //ADC底层驱动,引脚配置,时钟使能
6 q0 r% r1 B, F - //此函数会被HAL_ADC_Init()调用+ g. L+ c, k& z( p
- //hadc:ADC句柄; P2 A1 Y: c% A8 a" T9 v
- void HAL_ADC_MspInit(ADC_HandleTypeDef *hadc)
& i; y; ^4 c( K% c - {+ |/ t& T: C, o& {7 D! j' B
- GPIO_InitTypeDef GPIO_Initure;
6 n+ E. f. l3 ^* x+ F. A8 D/ ^% G - __HAL_RCC_ADC1_CLK_ENABLE(); //使能ADC1时钟0 Q- f! C+ y1 x* C$ Y) m
- __HAL_RCC_GPIOA_CLK_ENABLE(); //开启GPIOA时钟
; }8 q s; b- t4 L8 w6 c; P - 5 o3 Y+ l, F- d) e1 u- g
- GPIO_Initure.Pin = GPIO_PIN_5 | GPIO_PIN_6; //PA5
3 K' N. L8 O/ X1 x - GPIO_Initure.Mode = GPIO_MODE_ANALOG; //模拟, B q# z% F& I! M# Y9 u
- GPIO_Initure.Pull = GPIO_NOPULL; //不带上下拉0 V; S9 A3 S2 e7 b% F
- HAL_GPIO_Init(GPIOA, &GPIO_Initure);
* u7 _- y* X1 X( L& F; s2 W0 F - }/ k8 p" @- U1 ?8 Z
8 }3 a7 ]$ u6 z( l9 [- void DMA2_Stream0_IRQHandler(void)
# H6 x9 `2 R4 R* l# \ - {
( g" m6 B1 i7 l# V! s6 r: v$ c - HAL_DMA_IRQHandler(&ADC1DMA_Handler);
& X ^- H [8 u) k7 _: s - }0 L, M/ ]" J1 h F/ B# o
5 W/ ~: L* J& S3 F8 @0 F& x- void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc)- C9 } o2 U! }5 N0 a
- {
7 q- e' N& n$ L - printf("DMA transfer complete\r\n");
+ {" D$ X# g, g9 u5 j - }& t; f8 p4 c, {" y
- void HAL_ADC_ConvHalfCpltCallback(ADC_HandleTypeDef *hadc)
4 E) F8 T$ A& e' g3 a: r - {2 A9 T: d# H+ l) [% ]! e1 h( t9 c
- printf("DMA Half transfer complete\r\n");) l y. P9 x6 N
- }, u3 K" q( M" h/ v9 k3 B5 ~* ?2 D9 i8 v
- ) }. X4 B x* F3 H& g2 H- L, O
- void HAL_ADC_ErrorCallback(ADC_HandleTypeDef *hadc)$ A, _4 S. t; N' s5 X! W
- {
" _$ i' j# O+ x- _ - printf("DMA transfer error\r\n");
- |% F5 T X3 u+ ~1 I0 D, R - }
4 |, B4 X1 d: V& ]3 q& E, f
复制代码 / C7 L2 w Z1 S8 M
main.c:
% N* \6 V6 L- Q- #include "sys.h"- O$ ?% h( _6 p. E9 R' { m2 c
- #include "delay.h"7 O' [( d1 N9 p- S
- #include "usart.h"
( f+ c. A$ @, m2 w) v# u
& l; d& w- g( r- ^0 Y- #include "adc.h"0 Y" i1 h1 z) [" C1 \9 q% P8 ^' c
- 5 d. ?, [2 \" L: K# {7 C- t
- extern uint16_t buffer[128];
/ z$ a0 R( |+ V$ u- y T$ d
. f( D7 _" @% E6 u6 i- void show()
# u* X! n4 L% E, Z: |8 ` - {6 v1 }6 H0 a0 `9 O0 c# |( J
- int i;
l a9 Y! U% C- k& Z - printf("\r\ndata:");
, b/ G& \1 x9 i2 O - for (i = 0; i < 128; i++)
. c3 [% @8 U6 @5 i2 n) k - {0 R8 j- Y3 y: X+ o, l1 U3 ?
- if (i % 16 == 0) printf("\r\n");# _8 E8 ~: H4 U! n. ], Z' U
- printf("%6d", buffer[i]);+ U8 s* K' |- l1 g
- //buffer[i]=0;# c+ }) C' d. d7 s5 L: F& v7 d
- & I7 n. u2 x0 K( P5 o
- }
" m% S2 O# w9 ~0 u - printf("\r\n");# s2 l- |4 J6 v' C% I7 h0 E9 ]* h7 m
- }
* [& J, {" ~4 n& R5 z Y+ b - % P& S4 ^% i; ?+ j
8 ]; \% C: g$ n( |+ o) o- int main(void), k# S+ j) \) a; Y2 e
- {- }4 a" {) \3 l( j! ` V. y' I
- //Cache_Enable(); //打开L1-Cache* I! l# E( P7 a6 ~% ]' H$ }/ Q9 y
- HAL_Init(); //初始化HAL库& R0 O) o: f0 F
- Stm32_Clock_Init(432, 8, 2, 9); //设置时钟,216Mhz! d' ? @+ \4 ^' e d
- delay_init(216); //延时初始化
5 O' e% S: M& d! c {: L) l - uart_init(115200); //串口初始化
+ u& ^5 k+ T$ O( v' @" w* V0 r6 h - 4 t% C- v; b3 R& E. u5 W- G! b
- printf("\r\n\r\n\r\n---------------------------------------\r\nstart\r\n");
' |- E" Y! b8 K% f. @( \# Y - MY_ADC_Init(); //初始化ADC1通道52 w$ `4 o* y; `: L
-
, U: a) }% }8 |- J7 X - while (1)
4 u4 m5 l9 }" q9 t& N$ Q' R - {2 K$ j2 X3 y" M' i( |
- show();
& Y& F' f: s& W4 m# X$ K9 d+ v - //printf("cnt:%d\r\n",TIM2->CNT);' h7 |- y/ e! J6 ~9 l$ K
- delay_ms(1000);
* z0 w/ l9 U3 R O - }+ O& \# t: n! J! b: u3 S7 \
- }& o- `" |) ~1 J5 g% d
- * l4 `* K; L6 x- e
复制代码 $ r& w/ [ G8 n: _
因为定时器是2s采集一次,主函数是1s打印一次,所以显示结果如下:
1 Y2 Y2 O6 m2 s h
1 {4 P5 ?) l" M1 j
6 H0 Y6 k$ i7 r
6 X: h+ T8 x+ n) W: K, l————————————————
) z5 F/ _$ K+ O1 \: W/ m, L版权声明:小盼你最萌哒
1 J& ]- ^) u. P- v e, J3 U0 F" H& j如有侵权请联系删除$ L+ G) V' y5 w! d! L
- d8 A$ e5 g/ [/ h0 q+ ~1 n: `2 ]' h2 P4 f1 V1 `
|