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

STM32CUBEMX + ADC(单通道,双通道DMA)

[复制链接]
STMCU小助手 发布时间:2022-11-1 17:10
1.工具# J  J8 S! O0 [* K+ G! i' i
IAR  ]* _' {/ P, y5 M( `5 v# x
STM32CUBEMX
2 U/ I/ E" r* s, ]开发板STM32F411VET6
5 A5 @3 n! x6 j  p. y/ _5 e2 V9 Z
# D2 g* _, `% w. {2.工程配置
/ d2 x" F9 M9 p2.1 单通道

3 `% Z1 q3 \1 ?! {  c# _4 A+ i2.1.1系统时钟RCC、SYS配置1 `- s2 c9 s( _  P1 T

$ }9 z2 r" |% c: J& C: ^ 62a4cd2f2edc4af387c7f65f0421ee2b.png
3 r3 q4 y- ^( _( D( w4 b! ~- M) y5 ~2 B5 ?0 ?" B1 L% D
2.1.2 ADC配置,这里强调2点,
. P5 {1 r1 Y! j4 q% X! F; ~7 F, Y+ h6 Z( R8 \
使用ADC1——>IN4(通道4),本案例使用F4开发版,在12bit分辨率下,最小转换时间为15周期(最小转换时间 > 采样时间,具体可以百度),本案例转换时间为 15/16M = 0.937us
3 c! V5 T4 @: U5 V& s0 s4 |( ~; J; {' Z
(F4)最小转换时间:# d" Q$ i' i, B- i
8 U, `" N* J' c# g# O
​ 12bit——>15周期
9 u4 b" E" U5 c1 P5 ?3 a5 Z. r2 y& c" r/ y0 {% c$ W7 s
​ 10bit——>13周期# K4 M9 y$ G- m! `8 n& H9 x0 J, X

" b0 T2 i( t' X​ 8bit——>11周期0 z  w7 P7 P. @, ^7 o( }# @
. ^+ f  w7 U5 ^, N
​ 6bit——> 9周期  A7 ?" q3 _+ k0 ^5 w% }9 q
/ H6 j& r9 w3 R2 h6 S* K
45553ec08a544a9e83894809fc42b944.png
) F5 B9 n; q# S- E- F: v
: {9 E4 Z7 Q7 `9 p: D/ O注入模式,可以这样理解:把注入模式看作为中断,若果有注入,注入优先(相较于规则),完成之后在继续规则模式
# r9 S9 F5 O0 K" M) H9 T
$ `6 a' m2 M# S) F 06f78b4705fc41299c95c7bab4e18624.png
$ n! p2 K9 _$ ^+ `
6 P7 i8 N7 t( j7 E1 f1 F2.1.3 配置工程文件名、路径、ToolChain/IDE——>GENERATE CODE ,完成之后打开项目/ a/ q# b- z, Y" Q5 Y* o3 ~

. u, w, e' v% q8 v$ Lmain.c) e0 N3 Y$ W' c% @

# _2 t4 i5 r+ l0 X# t. ~" |
  1. #include "main.h"
    ! @2 o$ h9 ]3 ?% o' X% N6 f9 `) o$ ^
  2. #include "adc.h"
    5 y! s8 \0 b  n# i
  3. #include "usart.h". x, C, H; ^# l$ v) m) c
  4. #include "gpio.h"
    4 L/ c& O- }/ b4 p- b1 q# [
  5. #include "stdio.h"
    . g7 K) ~  G1 t( U/ n+ V4 F% o, }
  6. void SystemClock_Config(void);
    1 X  d* u0 R$ d* `0 d0 r

  7. , h/ s9 R# o# j7 r4 w
  8. uint32_t ADC_Value;
    ' P6 s* G: s/ d6 h" j; m

  9. $ a3 x2 q& M' c5 V9 z% K' E
  10. int main(void)! c3 w; A- E( C
  11. {4 k& Y6 ?& L* E
  12.   HAL_Init();6 m+ C, y8 s: Q
  13.   SystemClock_Config();9 f/ j3 ?0 H" E9 i( t

  14. % \, g; k1 O; {' u
  15.   MX_GPIO_Init();+ |9 R! {- n2 O
  16.   MX_ADC1_Init();
    3 {0 D7 U7 D& d- w3 b' G
  17.   MX_USART2_UART_Init();
    % |# t3 _5 r9 h+ o" y7 e9 K

  18. ) H7 [/ L0 b, D6 @: F- H
  19.   printf("start\r\n");" h0 B5 R# I% U; L1 `8 b
  20.   while (1)
    , n. D$ S" a/ x$ z" V4 t
  21.   {
      O, _" \: F' l& ^: e8 f' ^
  22.      HAL_ADC_Start(&hadc1);     //启动ADC转换: x* A7 b( P* l2 {9 `$ `6 Z$ S
  23.      HAL_ADC_PollForConversion(&hadc1, 50);   //等待转换完成,50为最大等待时间,单位为ms% u7 o. c( v, G' B9 S# s( B

  24. ; t5 y! O' K2 Z# ~& g
  25.      if(HAL_IS_BIT_SET(HAL_ADC_GetState(&hadc1), HAL_ADC_STATE_REG_EOC))  r' f! u1 d/ a7 F. S& d
  26.     {' a3 I& Y# J6 O
  27.       ADC_Value = HAL_ADC_GetValue(&hadc1);   //获取AD值  k: N& {7 J7 P/ F8 g

  28. % n, v6 U# M- u* g' q" P
  29.       printf("ADC1 Reading : %d \r\n",ADC_Value);//采样的值
    & L7 k& T" b5 E
  30.       printf("PA4 True Voltage value : %.4f \r\n",ADC_Value*3.3f/4096);
    2 b3 u0 @5 ~" t& s$ i- p
  31.           //转化后的电压值9 M* ^. R  d/ e2 E% T
  32.       }1 T- b$ L! T$ L) u8 K- u6 @4 F
  33.           HAL_Delay(1000);
    % O# A0 X3 b# j7 w/ ^5 o! O7 e
  34.   }
    $ W6 h( ?$ g+ N. o+ E
  35. }
复制代码
. L! |  ~* i) G, M& c! }
2.2 单通道+DMA- K2 U  W, a( J0 x; R
2.2.1 STM32CUBEMX配置与单通道大致一样,需要修改的见下图(开启DMA请求,并在DMA配置中添加ADC1)
+ ?! `7 C9 X2 p7 o6 ~" p" \* |8 J  a9 ?/ G4 K( E0 X, u
ddf17ffe5ce64e89af7b8eac1f9cfd48.png
0 v5 x+ R  q5 L% J
9 q7 o& D. x. S4 g——>注意:DMA配置里要选择 Mode选择Circular,Data Width选择 Word,(如果是HalfWord,则会将采集到的数值进行合并,范围超出2^12 = 4096)
7 Q) E, ]$ l9 p6 w$ V! @0 Z, I% ~
. `" Q, \* J) s5 R" k c488036bbd5b456d8052ef2cc487438f.png
" ^0 ?5 b9 W4 [9 U4 {
8 C5 A  m1 b) p  @4 j% W2.2.2 配置工程文件名、路径、ToolChain/IDE——>GENERATE CODE ,完成之后打开项目0 E8 x; w* t8 F- x0 M) L, j

4 J% B& L+ W! K' D" u. cmain.c; {' y+ w- b9 B5 U4 d  n9 D! p
  1. #include "main.h": H+ y9 Q' ]: l! Z
  2. #include "adc.h"; Y, ~" h6 p" {5 {
  3. #include "dma.h"7 s6 P4 S+ j2 L9 B
  4. #include "usart.h"
    ' S& v9 z3 Z- A( G6 |( Z( A
  5. #include "gpio.h"; M2 _; l( ?) f0 Y1 B) {' t, T: c
  6. #include "stdio.h": y5 W6 Z; f& l" e

  7. + R, H' ^7 w8 m
  8. void SystemClock_Config(void);4 d- Q( s- e* b; B9 l
  9. & f' _! ]0 i4 H; \
  10. uint32_t ADC_Value[100];
    6 ^6 n7 K$ K# X3 t" c% U
  11. uint8_t i;
    ( c: q# M  q: b6 J9 S
  12. float ad1 = 0;  U( N7 E% m& N
  13. ( W( b: ~( R3 p5 |( ]) A. ?2 ~: l- ?
  14. int main(void)
      x" _# Z, z3 u& T% c
  15. { / `* `" C5 N! b% u
  16.   HAL_Init();
    ! x7 k0 b' ^# c  G$ I. @) N; v
  17.   SystemClock_Config();' s# [: x/ J+ K" k  X

  18. ! Y' k3 Q' q9 v" ^! n
  19.   MX_GPIO_Init();
    ; }1 i% z5 y% C) }, c6 _6 U
  20.   MX_DMA_Init();4 Y& c2 I9 @! T8 Y( U5 |! i/ S
  21.   MX_ADC1_Init();
    ; B) m& t, D7 _2 L! z: b7 ?4 H/ `: i2 ]
  22.   MX_USART2_UART_Init();
      N" m, |  ]+ M& H5 @6 |7 u" ?
  23.   //开启ADC_DMA采集
    9 }/ O+ G/ m' I  z8 c! `
  24.   HAL_ADC_Start_DMA(&hadc1, ADC_Value, 100);//DMA自动把对应的通道值放入ADC_Value数组内7 D3 [4 h6 i% |+ T: \7 [& ?' e, D
  25. ) @/ T' B1 S3 f, j9 t+ u  C
  26.   while (1)
    1 U+ O$ P4 V9 I8 m% J: D7 A
  27.   {
    / e7 T( ]9 U% d# s5 V0 X1 e9 X$ G
  28.     //数据处理 与 DMA存值 不同步 ,在这里判断下转换是否完成,完成则进行数据处理
    2 v( N, a6 z7 b- `
  29.      if(HAL_IS_BIT_SET(HAL_ADC_GetState(&hadc1), HAL_ADC_STATE_REG_EOC))
      t+ `" A( F# U0 }( c
  30.      {         
    7 w. \3 F6 l" g* X6 G$ F
  31.                   for(i = 0; i < 100; i++)//数据处理 与 DMA存值 不同步  2 M( I: e. e- p, l: g
  32.                   {
    $ p! X' H3 y: A0 A: _! z9 i+ ~
  33.                         ad1 += ADC_Value<i>;       2 `' z, Q& B. f
  34.                   }  
    & ?% \3 Q9 [6 `, v# [
  35.                        ad1 /=  100.0;  I; ?9 n* i, t  F9 K; }' t
  36.                        printf("PA4 Reading Vol Value: %.4f \r\n", ad1*3.3f/4096);
    4 S0 \' H( H; r* y+ @9 m( j
  37.                        HAL_Delay(500);
    & h0 Z& V: O6 S# L+ {
  38.         6 r1 j  m4 D; Q! R0 |! W
  39.      }% h0 c4 Q) H& e9 J1 y) Y

  40. : U/ Z9 m( x  x& L% p1 s
  41.   }) ]0 L6 ^" N$ D$ Y
  42.   /* USER CODE END 3 */( H- t9 N; N+ Y4 C
  43. }</i>
复制代码

5 O5 V6 F0 v  G: m8 I2 qDMA:搬运数据思想
8 u- D) [& T& |* Q( z% x. `将一块内存的数据搬到另外一块内存,(注意内存可位于系统内部,也可位于外部设备,其实就是一块地址,形象的可理解为buf[], 某个寄存器等。); ]5 S/ \1 r2 c, [& `. |3 V
在搬运的时候,1次搬运的数据大小必须是2的n次方(n= 0,1…),只要设置好相应外设的dma映射通道号(这一部分是由hardware designer设计的),以及其他相应配置,并使能DMA功能, 它就自动开始搬运了,(内存到内存这种方式是相对较快的)。7 M$ W, m7 v9 v- i0 K1 L
: D- s# L+ I1 X$ m
2.3 多通道+DMA
! C( J$ i0 J& L( ]1 \2.3.1 STM32CUBEMX配置与单通道+DMA大致一样,需要修改的见下图(2个通道IN4、IN6, 开启连续扫描模式;并注意Rank下选择不同的通道,不配置默认通道 相同,我刚开始没有配置,结果2个引脚采集的值一样,浪费了半天时间找原因…)
1 L5 W( [$ _6 C+ y, v
. C' Z' G& H  ]4 z b72fff4c88c243a2a0382b90a9a193a7.png + m! g- ?8 g! B7 |- _
6c1dc734495f40d099b7646fc5c47ffd.png
8 _7 w, H2 a7 D* P5 W* p) t! j+ H" [
2.3.2 配置工程文件名、路径、ToolChain/IDE——>GENERATE CODE ,完成之后打开项目
- |6 V  `2 H: U% x
# x- {9 h4 q: ?0 S7 s) amain.c  Q/ `' t1 n- @

$ y) B3 X9 Z* L3 E  W% D9 |; j
  1. #include "main.h"( b8 A8 p' f, o
  2. #include "adc.h") z2 c& ~+ j' D3 I! m
  3. #include "dma.h"
    7 @5 C, b# ~" t1 \
  4. #include "usart.h"8 }% b" u. ^0 @. W% T
  5. #include "gpio.h"7 ^  Z; O/ U5 g* p, f
  6. #include "stdio.h"
    8 \, i/ j9 J  U) d/ S0 j
  7. 2 m9 d+ ]# d8 U
  8. uint32_t ADC_1 = 0, ADC_2 = 0;
    , G8 p) F& s% x6 g& }. _( p* W, U
  9. uint32_t ADC_Value[100];
    9 D, z+ `% J" o; U" S0 g8 A
  10. uint8_t i;: E1 g/ o1 k2 G% a

  11. ( M' g6 I% y! z' D: O3 R' A( p
  12. int main(void)
    7 v, N* x1 G7 B3 _% n
  13. {; X2 B# k3 t1 v6 m
  14.   HAL_Init();% J' K+ F9 C( E/ f% W

  15. ! U7 t3 ~+ Q& K, x" q  _7 G* y
  16.   SystemClock_Config();! f; P/ H/ Y9 o. f
  17. 5 R6 T2 L' @1 B& G6 }
  18.   MX_GPIO_Init();3 s: c6 D4 T' D( e# w( [" K
  19.   MX_DMA_Init();
    , l0 _' I- k3 J
  20.   MX_ADC1_Init();
    7 o4 y9 Q3 i( e9 m) k% M5 Y
  21.   MX_USART2_UART_Init();, N! ~$ P9 _- h* c+ ]
  22. 7 E+ H5 F+ ?6 |7 l+ x; D
  23.   HAL_ADC_Start_DMA(&hadc1, (uint32_t*)&ADC_Value, 100);//100数据量& f* ?9 h' ]4 a# X: G- F0 O
  24.   printf("ADC Sampling start\r\n");+ Y( e2 K' Q+ c" @/ a0 I$ b; I

  25. : F8 [2 x% l' W* V6 J4 ~" H0 F# r
  26.   while (1)
    / m4 l' b4 b* P# f
  27.   {8 N' u5 b1 u$ _! n  L
  28. & {! T9 f+ N% Q; E/ B' I# \+ x& f
  29.       HAL_Delay(500);//这里不加延时,采集输出值第一次为0 " R0 Q5 c: O' @1 Q6 i
  30.       for(i=0; i<100;)
    / e# y1 G4 y* ?2 M4 Q# x: H' b
  31.      {5 t/ {) `4 E( n5 A$ Y
  32.       ADC_1 = ADC_Value[i++];   ; A" \1 J% _% k9 \( [! m" d. A
  33.       ADC_2 = ADC_Value[i++];. E0 K+ O3 j3 k
  34.      }$ _/ A2 ~: n* H  Y1 W1 A; O
  35.       printf("double channel ADC test\r\n");
    - d) }1 }; X  c7 e; S
  36.       printf("ADC_1 = %1.4f\r\n", ADC_1*3.3f/4096);" n; l9 Z( G- \+ J3 W2 x, K
  37.       printf("ADC_2 = %1.4f\r\n", ADC_2*3.3f/4096);
    - e3 a0 N- v! `% ~" C$ z

  38.   J0 c3 x9 Y+ U6 h
  39.   }
    / y( [, {& H1 v6 a" ^
  40. 7 G$ C3 K" C3 l7 E( A/ M7 p  E
  41. % ~5 [/ c- |8 l# f
  42.   }0 W9 u% }' O; _! S
  43. }' F) v0 w. l+ q# d# @/ s
复制代码
2 f! _' h( _: a" `
函数HAL_StatusTypeDef HAL_ADC_Start_DMA(ADC_HandleTypeDef* hadc, uint32_t* pData, uint32_t Length);//第三个参数我还是不明白,但是支持数据量,库函数这样解释:
( k0 M' j3 d# J# Y+ z, J, W
& }& h: {1 R, Y& c( v0 E5 s, Y# V5 d' ]很多人说是数据量,不是长度,我很纳闷(数据量分2种情况:& }3 i; @5 U/ \" U, c  w
! Q9 T* D* X& F. @
1.单通道 1次将采集的length个数据存放到存储区,然后执行下一次采集存放,. @2 C2 U4 T- @8 P5 M) L7 Z4 s; v
2.多通道 1次将采集的length个数据存放到存储区,然后执行下一次采集存放,length应为通道数的倍数 保证每个通道的数据量持平
+ U4 a  r, H; P& C- ~————————————————- s" E" `1 q% y, L# L/ x0 R
版权声明:gfanbei
3 N+ z( M. w- i
6 u5 T; i4 i& \3 R  A
7 j2 i- z. B4 p' x* ]3 \6 x
f38a2a0d7066494a9a6e62bbd4d9d7be.png
收藏 评论0 发布时间:2022-11-1 17:10

举报

0个回答

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版