你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【经验分享】STM32F7实现ADC采集(软件触发+DMA传输)

[复制链接]
STMCU小助手 发布时间:2021-12-12 21:25
前面完成了STM32F7实现ADC采集(软件触发+轮询),但轮询的时候CPU得不到释放,在此基础上,这里实现DMA的传输。# W6 W( Q$ L  G
由STM32F7的中文参考手册可以知道,ADC可以使用DMA2的数据流0:+ l0 R: }  Z: Z# ?" J5 P7 p

3 ~! H; P" h# @8 @+ X
20200419132332456.png

2 `- U& D2 e) j, t  k
0 ], f- k$ y& Y1 y使用CubeMX配置DMA:
5 Z* _3 B) _! S7 o
20200419132658526.png
8 O& z( t" g! W$ {' ^$ @* C

; f9 T! q; a- J- f) L- m! Q$ Z6 aadc.c内容如下:
4 z& W1 }" F+ q. h: _+ u! ~& K7 I$ G$ S7 P5 e( m  O; V  {' d6 w
  1. #include "adc.h"
    , ^6 c! A; t% T4 F
  2. #include "delay.h"$ @8 C0 l$ L. _# B

  3. " r$ v* {1 O0 P
  4. ADC_HandleTypeDef ADC1_Handler;//ADC句柄- O" o7 Y: p7 _* q, [
  5. DMA_HandleTypeDef ADC1DMA_Handler;
    ) Q6 T" Z* n: M# t6 ]
  6. ADC_ChannelConfTypeDef ADC1_ChanConf;
    4 _/ ?3 ^1 ^) E9 v( ^9 z
  7. 6 [" C+ K+ j" \, a. J% g
  8. uint16_t buffer[128];
    / Y7 \4 h8 M& e* r; o
  9. 5 w7 d: W2 P2 z5 l
  10. /*下面的函数写完才发现没有用*/
    5 B# P+ m9 S6 i; @8 Q$ Y
  11. //void ADC1DMA_CpltCallback(struct __DMA_HandleTypeDef *hdma)
    ! a+ `( m( U! {$ W( w( t( t! H
  12. //{
    + j( f9 i6 `1 @$ [( D2 _8 d
  13. //    printf("DMA transfer complete\r\n");1 e" h) u% q( s+ Q
  14. //}, \1 e9 r: t/ R5 `0 Z5 S$ U/ v7 M
  15. //void ADC1DMA_HalfCpltCallback(struct __DMA_HandleTypeDef *hdma), e  O$ e: b, R% E: k/ P
  16. //{" h9 f+ F) G9 O  e
  17. //    printf("DMA Half transfer complete\r\n");  c0 M' Y0 U3 Q5 k
  18. //}2 n& _; E! u' P& Z
  19. //void ADC1DMA_M1CpltCallback(struct __DMA_HandleTypeDef *hdma)
    & ]! N' A+ Q. s- V6 D3 M% k& w
  20. //{
    8 c1 n9 v% e' E# ~2 |/ r
  21. //    printf("DMA transfer complete Memory1\r\n");" O1 Z  D: ~: d6 [/ B$ S( K0 Z
  22. //}
    2 p2 o5 {( o3 U% Y; x  G
  23. //void ADC1DMA_M1HalfCpltCallback(struct __DMA_HandleTypeDef *hdma)
    5 V) N+ [0 c& R4 D  t3 O; `& Q+ d
  24. //{0 K7 Y. A! `) G" S4 m. D5 f' O9 E
  25. //    printf("DMA transfer Half complete Memory1\r\n");% t0 C7 T4 y4 R3 Z+ E
  26. //}
    ) `7 R! D3 q" O7 H: u. ~" g( e
  27. //void ADC1DMA_ErrorCallback(struct __DMA_HandleTypeDef *hdma)
    . q/ v, @' r& B- \5 r( q* Y
  28. //{
    ) a$ J7 ~/ ~$ _! @) r# i# N1 E
  29. //    printf("DMA transfer error\r\n");0 l0 d' X! l: d+ U  W' i
  30. //}
    9 |2 z! E* D1 Y. A4 y9 }6 u  f
  31. //void ADC1DMA_XferAbortCallback(struct __DMA_HandleTypeDef *hdma)" I+ M0 ]! N5 C# W0 X, y
  32. //{: N9 c& Z( S6 ^8 v# X- @
  33. //    printf("DMA transfer Abort \r\n");
    2 x2 T- L  b0 d7 Y" V
  34. //}0 a! m$ ^1 P! [' g1 Y8 o5 a9 e
  35. 1 C4 _' C/ N- [5 g8 }  u/ {- q

  36. 9 W) k# Y' p4 _7 R
  37. //初始化ADC8 t" Y* J- t3 a8 y  r
  38. //ch: ADC_channels
    6 I9 E9 c; ~- m) c0 Q& f
  39. //通道值 0~16取值范围为:ADC_CHANNEL_0~ADC_CHANNEL_165 H2 ~2 [) P2 y8 f
  40. void MY_ADC_Init(void)
    5 O. {7 ^/ V! ^# T! T- a# O, S1 `/ \
  41. {7 c* n3 G6 W& e
  42.     __HAL_RCC_DMA2_CLK_ENABLE();
    2 P( ^$ h/ Z& ]- s. L, z, J- z/ N
  43.     HAL_NVIC_SetPriority(DMA2_Stream0_IRQn, 0, 0);9 s8 L2 S% s4 K4 \- @9 o0 `$ a
  44.     HAL_NVIC_EnableIRQ(DMA2_Stream0_IRQn);! G; E. g5 [; @+ L& m

  45. 8 Y. L7 i: |" E. o  M
  46.     ADC1DMA_Handler.Instance = DMA2_Stream0;# S. l  w) R# C9 {/ r* p  n; j
  47.     ADC1DMA_Handler.Init.Channel = DMA_CHANNEL_0;0 K' {! q- \! x  n$ z& N
  48.     ADC1DMA_Handler.Init.Direction = DMA_PERIPH_TO_MEMORY;% ]0 A  }5 a4 O0 X$ x7 I  U6 Z, o- b
  49.     ADC1DMA_Handler.Init.PeriphInc = DMA_PINC_DISABLE;               //外设非增量模式
    4 a0 a/ |7 B% ~- w3 M( e
  50.     ADC1DMA_Handler.Init.MemInc = DMA_MINC_ENABLE;                   //存储器增量模式
    3 B, ]' _9 B1 ^* L- t
  51.     ADC1DMA_Handler.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;  //外设数据长度:16位5 C+ N7 E2 G5 Q+ q' {
  52.     ADC1DMA_Handler.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;     //存储器数据长度:16位' R6 @3 E( D' D
  53.     ADC1DMA_Handler.Init.Mode = DMA_NORMAL;                          //传输一次就结束" w& R2 {2 O5 c4 ]
  54.     ADC1DMA_Handler.Init.Priority = DMA_PRIORITY_LOW;             //中等优先级# D; P& d9 j9 e3 T/ p
  55.     ADC1DMA_Handler.Init.FIFOMode = DMA_FIFOMODE_DISABLE;            /* 禁止FIFO*/
    6 a* q* U6 k+ I9 b# [: Y
  56.     /*自己增加中断回调函数*/
    1 A0 U1 J. |4 U9 e- a
  57. //    ADC1DMA_Handler.XferCpltCallback = ADC1DMA_CpltCallback;
    " E9 G3 x+ z' w& j6 l5 H
  58. //    ADC1DMA_Handler.XferHalfCpltCallback = ADC1DMA_HalfCpltCallback;
    5 `: `& Z$ i' |4 _- ?  n
  59. //    ADC1DMA_Handler.XferM1CpltCallback = ADC1DMA_M1CpltCallback;# Z( Q* N! c9 L/ \5 s( S
  60. //    ADC1DMA_Handler.XferM1HalfCpltCallback = ADC1DMA_M1HalfCpltCallback;
    . p. _1 W3 _) ?8 K# Q, N
  61. //    ADC1DMA_Handler.XferErrorCallback = ADC1DMA_ErrorCallback;0 x. n1 i4 S5 r: U+ y% Q, Y0 l
  62. //    ADC1DMA_Handler.XferAbortCallback = ADC1DMA_XferAbortCallback;
    4 }5 T- j/ X4 a, C5 m- s; d5 S% R1 H
  63.     /*最后发现并没有什么用*/+ H% E7 O$ n$ h- K, D8 m" d
  64.     HAL_DMA_Init(&ADC1DMA_Handler);. y3 l7 W/ L3 n3 ?
  65. : C* b* u1 x5 I# l% n% L
  66.     __HAL_LINKDMA(&ADC1_Handler, DMA_Handle, ADC1DMA_Handler);                //将DMA与ADC联系起来
    & A% _1 D1 k. F2 V" L' i1 ^
  67. $ u/ f) Z2 F& D6 C9 ^) E
  68. 5 o8 J7 R: Z* K6 |* c
  69.     ADC1_Handler.Instance = ADC1;
    % s* X- t. Q0 a8 u. Z9 S, {
  70.     ADC1_Handler.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4; //4分频,ADCCLK=PCLK2/4=108/4=27MHZ$ ?6 E; _$ Y( R. i9 d: ?; r3 q
  71.     ADC1_Handler.Init.Resolution = ADC_RESOLUTION_12B;           //12位模式
    2 L6 S- W0 t4 O9 ^
  72.     ADC1_Handler.Init.ScanConvMode = DISABLE;                    //非扫描模式  Z) _0 s" [) _1 Z: q/ O- `7 g
  73.     ADC1_Handler.Init.ContinuousConvMode = DISABLE;              //关闭连续转换' ?% q! S/ ^' @: {1 n" D2 R
  74.     ADC1_Handler.Init.DiscontinuousConvMode = DISABLE;           //禁止不连续采样模式  x# I$ G& B$ P! P: v
  75.     ADC1_Handler.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE; //使用软件触发$ a* ?% D" A. d( N& J0 v
  76.     ADC1_Handler.Init.ExternalTrigConv = ADC_SOFTWARE_START;     //软件触发
    9 y" k. x# o: c" R* a0 S
  77.     ADC1_Handler.Init.DataAlign = ADC_DATAALIGN_RIGHT;           //右对齐. x$ \. r) H, Z# N
  78.     ADC1_Handler.Init.NbrOfConversion = 1;                       //1个转换在规则序列中 也就是只转换规则序列1+ U$ L2 R8 t' b6 x
  79.     ADC1_Handler.Init.DMAContinuousRequests = DISABLE;           //关闭DMA请求
      t' e- S1 e4 F  a
  80.     ADC1_Handler.Init.EOCSelection = ADC_EOC_SINGLE_CONV;        7 Y( A2 K; N! l3 |7 u1 K0 `
  81.     HAL_ADC_Init(&ADC1_Handler);
    2 a5 W0 F& N+ {; G0 v( d8 a

  82. , a* S' i: ^5 o0 _' L! B
  83.     ADC1_ChanConf.Channel = ADC_CHANNEL_5;                                 //通道& Y- k. }; B9 l' T
  84.     ADC1_ChanConf.Rank = 1;                                     //1个序列8 w$ _" L1 f: Z% m* @
  85.     ADC1_ChanConf.SamplingTime = ADC_SAMPLETIME_480CYCLES;      //采样时间& G7 i$ Z6 J3 Z5 f3 A
  86.     ADC1_ChanConf.Offset = 0;
    6 L, y8 L2 K1 C1 |+ \
  87.     HAL_ADC_ConfigChannel(&ADC1_Handler, &ADC1_ChanConf);       //通道配置! f1 [5 D0 |% W! ]+ V9 }7 [

  88. 4 l4 f, o/ j, i) m, {0 G; L
  89.     HAL_ADC_Start_DMA(&ADC1_Handler, (uint32_t *)buffer, 1);9 c4 ~2 g% F: h% g9 ~& i
  90. & x! Q. ~7 D$ [) y$ w& P/ m/ i
  91. }0 G9 W' a' `1 a4 T* W& `7 V
  92. 0 r7 ], M$ C) g! C  N/ C2 M
  93. //ADC底层驱动,引脚配置,时钟使能
    # [4 q+ x9 e: u8 x$ T
  94. //此函数会被HAL_ADC_Init()调用1 e) {0 K5 ^+ \
  95. //hadc:ADC句柄
    1 Y+ [. y( P7 Q. ]* U! W
  96. void HAL_ADC_MspInit(ADC_HandleTypeDef *hadc)
    7 }* N# K' q2 R* A  {
  97. {
    ) d! U3 y! q5 W2 k
  98.     GPIO_InitTypeDef GPIO_Initure;/ c+ Z+ D4 S: N- O- }9 D
  99.     __HAL_RCC_ADC1_CLK_ENABLE();            //使能ADC1时钟5 y  f0 e# k) F
  100.     __HAL_RCC_GPIOA_CLK_ENABLE();           //开启GPIOA时钟
    ) H2 L) q; e) A% `( I7 ]) e" U! T; E; h; Y

  101. 3 ~& v% r; b* Q" O( J) G# F; h
  102.     GPIO_Initure.Pin = GPIO_PIN_5;          //PA55 |# R' v  p$ ]0 Q; A6 I; G+ V$ D  x
  103.     GPIO_Initure.Mode = GPIO_MODE_ANALOG;   //模拟- c/ ~2 @: V9 b- }5 E
  104.     GPIO_Initure.Pull = GPIO_NOPULL;        //不带上下拉9 h' n' u: w" v
  105.     HAL_GPIO_Init(GPIOA, &GPIO_Initure);. W% {1 D  K$ i
  106. }
    / }4 d7 Z! \3 M& o  I

  107. * A; D% y& J! n  z
  108. void DMA2_Stream0_IRQHandler(void)( f  y' F) \4 T! q3 Y) ?  b: M
  109. {. x0 I3 E7 @2 X! B" U
  110.     HAL_DMA_IRQHandler(&ADC1DMA_Handler);
    9 Z' o5 d7 U4 a7 p$ W( _2 A! G
  111. }
    $ x4 o) }- }0 n; G; I2 a+ `

  112. $ ^$ v0 ~$ ~' O1 v+ Q
  113. void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc)3 e4 l/ A8 f" E1 F& @2 B) m
  114. {# X; q5 E( X! |6 \3 Z; n, Q  Z
  115.         printf("DMA transfer complete\r\n");# n1 J% Y. J- q6 w$ O
  116. }; p0 a% M# C  _: `9 n- |
  117. void HAL_ADC_ConvHalfCpltCallback(ADC_HandleTypeDef *hadc)
    $ O. G7 b2 r" ~' y# t
  118. {
    ( j+ h: y& I# i2 i' H( b! v
  119.         printf("DMA Half transfer complete\r\n");
    / {; }) F8 G) N# N" Q! \) a0 x9 _
  120. }
    ) a( o: ^- E* X$ g" h% f% G
  121. # J6 g: b7 h# i  m3 f9 R( y1 N% u1 \
  122. void HAL_ADC_ErrorCallback(ADC_HandleTypeDef *hadc)
    ( I7 h3 t4 l% n! o6 K9 J
  123. {) f0 R6 Z" u1 x8 Q0 J
  124.         printf("DMA transfer error\r\n");. {) [9 X7 x+ L: ?7 ~, A
  125. }
复制代码

8 d9 u9 M& q$ [: f! {! L: |  `注意,代码里注释的部分是,虽然我们在对DMA初始化的时候,我将DMA相应的回调函数参数都设置好了,但初始化完成之后,其中有三个函数并没有指向我们设置的函数,而是指向了具有__weak属性的三个函数。) y( R8 f5 X. G3 N3 D3 B0 y$ I
1 x2 ~0 L) }6 Q4 j( s/ r4 C$ i3 f
20200419141009399.png
/ F+ W+ ?+ M. ^& b$ S! E  F! h
+ h9 x  u. H0 e3 p. ~& F
这是因为在进行ADC初始化的时候,重写了ADC使用的DMA的回调函数。4 Q& p& N( F; \% D

+ m/ V( K3 e' p6 h, G" t( M
20200419141507473.png

. l  P& l' H) l/ `. I( f. U7 I* [+ k8 ^
所以最终是直接重写三个函数就行了,不用再去设置。5 ^! l) t7 j, m6 T

" `( `* N! U, ~* a  O* V( ~1 Kmain函数中也不需要去调用,直接打印数据就可以了。
: B8 J5 f. Q. L3 Y/ `! A& o. c6 n! F# Q
  1. #include "sys.h"0 P# b6 K% {, P6 |+ {
  2. #include "delay.h"# s! `' ^2 d1 W
  3. #include "usart.h"
    / T) n$ A8 R4 L

  4. - x+ u" C7 z: x: `7 A6 ]1 d
  5. #include "adc.h"
    2 \! @2 p- \; n9 g: g

  6. + [+ V) A' o; n) A
  7. extern ADC_HandleTypeDef ADC1_Handler;//ADC句柄* C$ {* E( r& a: Y, f
  8. extern uint16_t buffer[128];& r7 e# V7 E! F  f- l5 U  c8 Z

  9.   t3 w$ {; _, L  ^: C, @
  10. void show()9 @% d3 C1 z9 n, d- q2 Y# }
  11. {! |$ l; Y4 ]7 U2 j! O# W& q0 m
  12.     int i;
    5 C$ Y: N8 q2 v$ E
  13.     printf("\r\ndata:");
    0 L' s* g. ]. ?+ _( n2 X
  14.     for (i = 0; i < 128; i++)& u7 K$ R  g! b7 e
  15.     {. K: L. T  ]% S+ k: |+ n
  16.         if (i % 16 == 0) printf("\r\n");
    , Z) x$ u+ F' [7 J
  17.         printf("%6d", buffer<i>);5 A- d* U/ o6 D0 i# e. D
  18. # e. ~6 ?% u: \6 p8 ^
  19.   </i>  }' L$ q4 h3 A* d+ e
  20.     printf("\r\n");# P1 L* y2 z1 `. L( ?" h! ?, ~! V9 W
  21. }4 ]  h6 M7 k1 h9 P
  22. 4 q' q1 v+ B/ V6 f  ^

  23. 3 A/ D0 M1 o1 a5 [( ?  @; P
  24. int main(void)5 b- M" {# W& ^' m
  25. {
    - u  @) R1 R7 F. ~+ l
  26.     Cache_Enable();                 //打开L1-Cache; Z7 S5 N8 ~& j) V( f: J" b
  27.     HAL_Init();                     //初始化HAL库- s! A8 \! S2 o; J& Y8 M
  28.     Stm32_Clock_Init(432, 8, 2, 9); //设置时钟,216Mhz
    4 G2 h" C$ P0 |
  29.     delay_init(216);                //延时初始化
    % [& h1 s4 D6 N+ L
  30.     uart_init(115200);              //串口初始化4 i7 _8 C2 x- z* ?. E# a
  31. ; s0 r' ^0 g: D! U2 {& @( d6 k
  32.     printf("start\r\n");
      Z- @' I  Q- c  p8 o* N1 g: O
  33.     MY_ADC_Init();                  //初始化ADC1通道58 h" A& A! o; @" ~$ M$ A( l

  34. : n/ ]0 V' n6 y! v% b
  35.     while (1)
    * ?8 t# M' e) F) {
  36.     {0 I+ H- H1 j  d$ J
  37.         show();
    6 v# l: _9 v' b  H3 P% \
  38.         delay_ms(1000);4 O3 Z/ }6 \% V
  39.     }* L% U$ x: F$ h3 s* P" y
  40. }
复制代码
/ A: k& t6 Q3 V! F% s/ x
实际打印结果如图:
: M/ i3 r' k( W7 U/ s
- f$ F" _* B7 {/ Y* Z
20200419142446515.png
: u" [, `& i$ ?0 o
7 E: z0 A2 z4 m( @1 `# G4 u1 n/ l
当我们需要进行多个通道采集的时候,先修改CubeMX配置,改为扫描模式,修改规则通道的转换数目,修改相应的Rank内容:
. T( {2 K. D0 i0 J$ N3 H! W+ e* q" Q% j: ]1 E& A! ]
20200419142957395.png
. O3 O' `% v  y0 Q# L, T

) d2 [. b! s# f* E0 Y& R! s生成完代码后,启动函数长度修改位转换长度:
) ~7 L3 F7 d) x4 c/ _8 a6 q3 S6 l& I) @4 V( J& ^7 K9 H
  1. HAL_ADC_Start_DMA(&ADC1_Handler, (uint32_t *)buffer, 2);
复制代码
/ A: L. l! h* [9 o( g7 P
修改后的ADC完整代码如下:( v1 U$ T. ?. ~
" O% u. I$ B0 C  \) E1 {! }3 {
  1. #include "adc.h"
      D3 p, {5 G6 K# j' O% v( Y
  2. #include "delay.h"
    & L- m  m" X' D/ U# s( P
  3. % d) k1 B: W* a' A8 D7 X) U" t' `
  4. ADC_HandleTypeDef ADC1_Handler;//ADC句柄. w* [: w' {  d6 R; Q8 Z' g; C
  5. DMA_HandleTypeDef ADC1DMA_Handler;
    $ o0 z; S) ]; {& O
  6. ADC_ChannelConfTypeDef ADC1_ChanConf;4 |3 @; ]3 T  ]

  7. / b1 g+ k: B' Q' Z; M5 F
  8. uint16_t buffer[128];
    % L+ n$ o9 F5 D7 P* k# G6 |9 V

  9. ( P! V# t0 W1 J

  10. & C4 ~5 m2 B% r* D* n! F
  11. //初始化ADC
    4 Q  F! v1 J! u" f) ]5 E
  12. //ch: ADC_channels
    $ n: y& L$ V6 W/ p4 C5 c, F
  13. //通道值 0~16取值范围为:ADC_CHANNEL_0~ADC_CHANNEL_160 T% ^7 F, }' \2 X' ]
  14. void MY_ADC_Init(void)2 `! Z9 Z3 M! W" m; `
  15. {
    0 F8 w0 p( Z: C1 N0 L2 T6 ^. _' U
  16.     __HAL_RCC_DMA2_CLK_ENABLE();
    % a; u( D$ K' F7 @# W4 h4 ^. Z6 }) y
  17.     HAL_NVIC_SetPriority(DMA2_Stream0_IRQn, 0, 0);
    2 E+ f6 I0 c3 b6 ?' y1 T; E7 Y2 h+ w
  18.     HAL_NVIC_EnableIRQ(DMA2_Stream0_IRQn);/ L3 j  X8 ?2 @) Y- d* _2 G

  19. + A4 ]# O0 G- M) V( i
  20.     ADC1DMA_Handler.Instance = DMA2_Stream0;
    7 z# f2 W+ A& x; a, S3 _& t* A7 D
  21.     ADC1DMA_Handler.Init.Channel = DMA_CHANNEL_0;3 h1 c' l, X5 \) b7 I
  22.     ADC1DMA_Handler.Init.Direction = DMA_PERIPH_TO_MEMORY;- y' ]3 [# n+ q. z4 @- q
  23.     ADC1DMA_Handler.Init.PeriphInc = DMA_PINC_DISABLE;               //外设非增量模式& Y  @! @2 t8 A' F( {
  24.     ADC1DMA_Handler.Init.MemInc = DMA_MINC_ENABLE;                   //存储器增量模式
    ; s* B+ m% e: A/ x* V0 o
  25.     ADC1DMA_Handler.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;  //外设数据长度:16位7 O& b4 i6 d! t$ {7 x  S
  26.     ADC1DMA_Handler.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;     //存储器数据长度:16位* f+ j; K& @( r' U
  27.     ADC1DMA_Handler.Init.Mode = DMA_NORMAL;                          //传输一次就结束
    " B% |* ?# S9 m& P' h. S/ N. F# Y
  28.     ADC1DMA_Handler.Init.Priority = DMA_PRIORITY_LOW;             //中等优先级
    - a/ S) l5 V0 R
  29.     ADC1DMA_Handler.Init.FIFOMode = DMA_FIFOMODE_DISABLE;            /* 禁止FIFO*/! s6 ?- W) }! d2 J2 Z  ~

  30. ; v' V, a) X& B. C4 j& _& K
  31.     HAL_DMA_Init(&ADC1DMA_Handler);
    ( W; x# x$ Y0 m3 O7 Z# Q' u, {
  32. : _5 U) M% C: j) _+ _
  33.     __HAL_LINKDMA(&ADC1_Handler, DMA_Handle, ADC1DMA_Handler);                //将DMA与ADC联系起来  r& H  f% X5 g9 X4 L

  34. ! E$ J% _9 P1 @% E, N

  35. & m  \  O7 {$ T) r
  36.     ADC1_Handler.Instance = ADC1;" T2 G2 h7 {5 L; Y& I7 n2 x
  37.     ADC1_Handler.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4; //4分频,ADCCLK=PCLK2/4=108/4=27MHZ
    / x" N; M3 i+ q% e5 E
  38.     ADC1_Handler.Init.Resolution = ADC_RESOLUTION_12B;           //12位模式, r4 v/ v2 D5 [; Q( W$ Q" r
  39.     ADC1_Handler.Init.ScanConvMode = ENABLE;                    //非扫描模式
    # _" o. o3 Z  [
  40.     ADC1_Handler.Init.ContinuousConvMode = DISABLE;              //关闭连续转换
    , C. `( L) }" C( m1 k
  41.     ADC1_Handler.Init.DiscontinuousConvMode = DISABLE;           //禁止不连续采样模式6 D' O7 B& m) E+ N" r) P) H* ~% Y
  42.     ADC1_Handler.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE; //使用软件触发8 B3 Z. f) ?6 g3 I
  43.     ADC1_Handler.Init.ExternalTrigConv = ADC_SOFTWARE_START;     //软件触发7 y2 C3 s3 S3 g4 k1 O, S
  44.     ADC1_Handler.Init.DataAlign = ADC_DATAALIGN_RIGHT;           //右对齐
    ! W) a* K* I) q, t
  45.     ADC1_Handler.Init.NbrOfConversion = 2;                       //1个转换在规则序列中 也就是只转换规则序列13 i, P2 _! P9 a$ c0 u" z
  46.     ADC1_Handler.Init.DMAContinuousRequests = DISABLE;           //关闭DMA请求" E6 }3 w0 v1 L! C) Y& D2 @
  47.     ADC1_Handler.Init.EOCSelection = ADC_EOC_SINGLE_CONV;        
    + @  S9 S  V3 j6 a
  48.     HAL_ADC_Init(&ADC1_Handler);' M5 r  w( r6 f0 @  c7 H

  49. / b$ i1 h. I# I6 d7 c! p
  50.     ADC1_ChanConf.Channel = ADC_CHANNEL_5;                                 //通道
    $ t0 M2 I, L7 P! J! @4 ?( ?/ A* b
  51.     ADC1_ChanConf.Rank = 1;                                     //序列19 {" A6 F) E8 o% j3 ]
  52.     ADC1_ChanConf.SamplingTime = ADC_SAMPLETIME_480CYCLES;      //采样时间, v/ a4 x0 x+ D" L4 J  _6 `& R
  53.     ADC1_ChanConf.Offset = 0;: @1 y. g0 ]# b( U  ]. |
  54.     HAL_ADC_ConfigChannel(&ADC1_Handler, &ADC1_ChanConf);       //通道配置3 x4 m' `. u1 e

  55. 3 O" {) d) `: c
  56.     ADC1_ChanConf.Channel = ADC_CHANNEL_6;                                 //通道
    0 C0 N$ V' x0 W3 W- ]& j
  57.     ADC1_ChanConf.Rank = 2;                                     //序列2
    4 F0 a5 ^1 z) \/ x
  58.     ADC1_ChanConf.SamplingTime = ADC_SAMPLETIME_480CYCLES;      //采样时间
    , r4 v0 T& w  ~# Q- J
  59.     ADC1_ChanConf.Offset = 0;% t2 q- p7 [% E: ^4 K1 ~
  60.     HAL_ADC_ConfigChannel(&ADC1_Handler, &ADC1_ChanConf);       //通道配置$ P' H2 a8 I# y) R
  61. 2 z3 y( ?+ j; ~% _( Y2 A
  62.     HAL_ADC_Start_DMA(&ADC1_Handler, (uint32_t *)buffer, 2);
    7 Z  A2 W5 W# ]2 V1 l
  63. . g  p/ _" @9 a! w! C
  64. }( y- P( m: y( p  w0 _
  65. * Q4 {0 C" F- N$ X
  66. //ADC底层驱动,引脚配置,时钟使能
    4 U+ [: D/ s0 D  U: _$ e
  67. //此函数会被HAL_ADC_Init()调用
    ) }" H( F& b' \* E3 ?* c
  68. //hadc:ADC句柄. e: r( c; ~/ y, Z
  69. void HAL_ADC_MspInit(ADC_HandleTypeDef *hadc)3 |7 q- h! R# u  \
  70. {
    : P3 ?. X, w/ U8 T4 |8 l
  71.     GPIO_InitTypeDef GPIO_Initure;( V9 _9 H* U) X  J6 A
  72.     __HAL_RCC_ADC1_CLK_ENABLE();            //使能ADC1时钟& c( c4 X. J" b0 _7 m) W# J
  73.     __HAL_RCC_GPIOA_CLK_ENABLE();           //开启GPIOA时钟1 g. m" P# d) R( e! i4 S$ I

  74. 9 |' l) t$ }% i, ?8 H' m  t
  75.     GPIO_Initure.Pin = GPIO_PIN_5|GPIO_PIN_6;          //PA5. I# U- Y! m+ J% U+ X! S$ O
  76.     GPIO_Initure.Mode = GPIO_MODE_ANALOG;   //模拟3 J5 m4 l, H% U
  77.     GPIO_Initure.Pull = GPIO_NOPULL;        //不带上下拉8 I! g, u2 j$ `
  78.     HAL_GPIO_Init(GPIOA, &GPIO_Initure);
    8 m+ {- {* T" B4 `# H* w: x5 m, R
  79. }
    + \" Z; O5 P1 l& Y
  80. 7 d# ?* k; p$ I/ b5 C1 I) {. j
  81. void DMA2_Stream0_IRQHandler(void)% @# s: c: e6 L6 i5 \
  82. {* ?0 }6 m' L' D) c/ ]+ K( ]
  83.     HAL_DMA_IRQHandler(&ADC1DMA_Handler);7 h! V6 W3 k6 ]  t/ Y
  84. }; B* g0 T6 e- a
  85. 7 ]1 C, y8 f7 ]4 m' |
  86. void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc)
    7 c, y7 x$ W/ k5 J4 S
  87. {& H/ @. }: Z2 @2 y- S& ?" X
  88.         printf("DMA transfer complete\r\n");- q  ?2 R2 `" l+ v
  89. }
    % P) w; l# \$ C
  90. void HAL_ADC_ConvHalfCpltCallback(ADC_HandleTypeDef *hadc)
    7 }, [4 F: f8 I8 J7 l
  91. {
    7 P! J7 C- V$ r: V: g
  92.         printf("DMA Half transfer complete\r\n");
    6 C4 Q4 e  Q5 k. l( S. S. o8 M
  93. }
    , k7 [- q0 ^' O' E7 b

  94. 2 q: z8 I' I1 w& Z4 A
  95. void HAL_ADC_ErrorCallback(ADC_HandleTypeDef *hadc); z# s6 @* Z, v4 S9 a
  96. {
    3 z3 w, a: n& h- S) p; I
  97.         printf("DMA transfer error\r\n");  V; ^2 h' g! f9 u4 k3 a- q
  98. }  A/ x' W; p3 }7 F) b/ Y
复制代码
3 s. s  y% y8 Z' C+ v/ k
效果如图:
- h- T# L) w8 U, W6 f
; x6 ~7 W# O& n, N- K( [, ]
20200419143301632.png

7 E; y$ W2 N) ~9 j# E% [9 r# ~$ U; A
- G' e0 O% Y# h! [- c
1 P3 |' G$ M( s/ l9 E

! Y4 \% D9 e4 N2 y: x: a, O
收藏 评论0 发布时间:2021-12-12 21:25

举报

0个回答
关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新和工艺
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版