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

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

[复制链接]
STMCU小助手 发布时间:2022-11-1 17:10
1.工具* P) [8 T3 D2 d) B: p9 j
IAR
; i& X$ A6 K( `2 sSTM32CUBEMX
! C3 E# d7 I) e/ Z- o) K& Q开发板STM32F411VET6
2 R- ]  P) e& a. ?+ h6 l* d0 v' B8 C( d# A/ H! u
2.工程配置
# ]  Z* m/ T' q2.1 单通道

( I# J) ?, V$ K: w2.1.1系统时钟RCC、SYS配置
- {3 G) A7 f2 X$ c  P% d7 V1 H2 Y& X) ]+ Y
62a4cd2f2edc4af387c7f65f0421ee2b.png
* C9 o( K! n7 d) Z8 W, A7 H6 o, v( ^/ z) K/ l2 F( g4 \
2.1.2 ADC配置,这里强调2点,
6 l% a+ }& {8 U
! g7 }% i" h: H0 j使用ADC1——>IN4(通道4),本案例使用F4开发版,在12bit分辨率下,最小转换时间为15周期(最小转换时间 > 采样时间,具体可以百度),本案例转换时间为 15/16M = 0.937us5 A# s$ z* Y, b/ \* a' z5 H
' z  R! |  |, Z: g( A' E+ I
(F4)最小转换时间:
1 R* W  a' h* v/ a/ d7 p. o- W" `$ x! d/ Y" O. j
​ 12bit——>15周期( O, N9 A/ O* W8 [3 _- j, L
  d$ W# |7 m& g0 K9 C7 L, M
​ 10bit——>13周期3 c  u) R' B; Z4 U$ T

. {! Z+ J6 O0 ]- E​ 8bit——>11周期
8 i( s1 }  _+ f7 ~7 i! i* v# `/ R4 S' V3 \1 O3 x+ n% K$ X
​ 6bit——> 9周期
4 D7 k$ Z3 _1 ?( L2 G8 X. ~5 j9 @9 W* z5 C$ B! x* ^& B4 I
45553ec08a544a9e83894809fc42b944.png
6 b  p5 D3 _" H, H. i8 }; Q( {& Z: U8 h8 s$ c7 {9 m7 w% G
注入模式,可以这样理解:把注入模式看作为中断,若果有注入,注入优先(相较于规则),完成之后在继续规则模式
8 P( Z! W4 `8 |: K
8 L# M" b9 g) p, ?) \. M" ~) p 06f78b4705fc41299c95c7bab4e18624.png
1 J- a* Q' [* d% t- }7 K& T8 c1 D3 j; I/ c: z$ z! b5 @) u
2.1.3 配置工程文件名、路径、ToolChain/IDE——>GENERATE CODE ,完成之后打开项目
3 e0 U2 U) f) N/ F0 g6 R
" B* X( B7 O, w/ X. M7 d7 j# imain.c
- o5 s. ?" e5 Z* T6 [/ l0 s! j* G+ Q9 p: A$ U0 _3 `
  1. #include "main.h"7 \  F' U3 \1 l* m' M
  2. #include "adc.h"
    7 k% h. y) P4 x, ~# G
  3. #include "usart.h"+ S: k! A; v9 k8 q$ r2 Q* T
  4. #include "gpio.h"  X' k% ~+ |+ A  T3 j$ U2 C8 {
  5. #include "stdio.h"0 i9 v4 z! }' E& |! W9 z! h
  6. void SystemClock_Config(void);$ c' b; O: B6 Y. k' F

  7. 3 H1 j4 ?; q9 `
  8. uint32_t ADC_Value;
    # c& |' k+ {1 k: Q8 Z' R
  9. $ q, y+ a7 c: X: {7 P( `( }, E
  10. int main(void)
    ! P2 G- |& r3 b, J" c* l
  11. {
    ; q0 d6 }- _6 e5 E
  12.   HAL_Init();, i9 p4 E2 Q4 K; Z& W0 z; s1 K7 M
  13.   SystemClock_Config();$ k! z9 q+ }: l3 {  t0 U

  14. 3 j3 ?% Q5 t4 N/ }- e# l+ ~
  15.   MX_GPIO_Init();: l8 x. u- ?  f, Z# `
  16.   MX_ADC1_Init();# A4 r8 M1 Y' i+ R
  17.   MX_USART2_UART_Init();4 e  q% d6 ?. t4 X( O; W3 H6 A

  18. 7 }7 r; e# {& u
  19.   printf("start\r\n");
    . H# a6 `/ n! O) Z- ]0 g9 q, T
  20.   while (1)' ~: L- c1 Q  I9 m& |2 ~
  21.   {
    # O" L4 }& L$ ?  x
  22.      HAL_ADC_Start(&hadc1);     //启动ADC转换
    * W' t$ l3 P  N% v- Y/ d2 L" w
  23.      HAL_ADC_PollForConversion(&hadc1, 50);   //等待转换完成,50为最大等待时间,单位为ms# C! I( A# W, }$ z
  24. 6 c6 W  `9 {1 c* _, o( \* E' h8 [
  25.      if(HAL_IS_BIT_SET(HAL_ADC_GetState(&hadc1), HAL_ADC_STATE_REG_EOC))
    1 ?; L4 l/ f7 x
  26.     {
    7 U* i6 V, P8 T% S% ?
  27.       ADC_Value = HAL_ADC_GetValue(&hadc1);   //获取AD值
    5 W) v9 X% m& O: y3 F0 Y3 A

  28. * i- E0 ^  K1 U* @. b$ Q
  29.       printf("ADC1 Reading : %d \r\n",ADC_Value);//采样的值4 u/ q1 p$ a7 ]' q
  30.       printf("PA4 True Voltage value : %.4f \r\n",ADC_Value*3.3f/4096);
    / i+ w2 }0 ~* s7 o$ N6 I( I( h1 l+ R+ Y
  31.           //转化后的电压值. }& |& Y! L' i
  32.       }7 l  T6 K0 C0 u* z4 n4 e
  33.           HAL_Delay(1000);
    2 t5 Q8 g: ^, g4 L: v8 u) n2 V
  34.   }
    1 i; g" R2 C' c! I
  35. }
复制代码

  }% |# b$ w+ a, s% J3 }2.2 单通道+DMA% \. v' S; t6 N2 v0 X8 J4 ~/ s
2.2.1 STM32CUBEMX配置与单通道大致一样,需要修改的见下图(开启DMA请求,并在DMA配置中添加ADC1)
4 t/ e: H# o, T3 }3 p3 \; Q6 V4 ~( X# U% Z6 p4 C7 `4 }
ddf17ffe5ce64e89af7b8eac1f9cfd48.png 7 m  j6 y9 n; D% C8 S9 M

/ [8 |- e% k2 S/ \, j5 ?  c; G——>注意:DMA配置里要选择 Mode选择Circular,Data Width选择 Word,(如果是HalfWord,则会将采集到的数值进行合并,范围超出2^12 = 4096)0 Y( Y; W7 C0 r' L- e' n$ s2 k
6 S& {: T  q0 ~" F$ ]+ f8 ?
c488036bbd5b456d8052ef2cc487438f.png . k- H# H. n, A( ~# U& |, ?
5 T7 ^# H. o* W' Y/ W( v; S* A
2.2.2 配置工程文件名、路径、ToolChain/IDE——>GENERATE CODE ,完成之后打开项目- f; Y4 K  S9 }" m4 V# s2 w* J. H; |9 x8 a

4 s% @0 z( h, R. U$ {  [+ u) F! Cmain.c- a2 ~) X( I7 h/ a
  1. #include "main.h"( D! R* Z' m! q8 _1 ]  Y7 Y5 c2 Z
  2. #include "adc.h"
    4 Q/ s( c# z* G' k, l0 k2 A
  3. #include "dma.h"3 ]1 b7 R) v0 J$ c* X# f
  4. #include "usart.h"
    7 `: a8 }8 v: N! X" D/ m8 p! C
  5. #include "gpio.h"
    2 s' n: F& K/ {' d$ c& v4 C- B8 o
  6. #include "stdio.h"
    ! K5 p# [0 u2 f; Q0 Y5 f% R* i

  7. 8 B" A4 V8 o2 ]- a
  8. void SystemClock_Config(void);8 G  X9 F0 j* v6 R

  9. & S3 p4 z& H* l4 F0 i4 W3 G
  10. uint32_t ADC_Value[100];+ v6 x6 X) R1 ]" V6 }0 u
  11. uint8_t i;1 d& s3 X) D; ?3 S6 \* A% T5 S( u8 U
  12. float ad1 = 0;
    0 [9 l4 k8 j- L$ ?9 L
  13. 4 _- V# T$ t4 C$ N
  14. int main(void)3 {+ {/ M, }5 P$ T4 l! S# L- W
  15. { 8 U9 Y/ E( H) z6 d8 u: P& }( c
  16.   HAL_Init();
    ' L$ X% {+ f9 u  h
  17.   SystemClock_Config();$ r' B4 d# X% T4 g
  18. 5 C) z4 r! Q) S+ v
  19.   MX_GPIO_Init();
    " J3 R9 Z% _; O) M/ H3 J4 q
  20.   MX_DMA_Init();
    9 z& t/ v, Z; t0 R
  21.   MX_ADC1_Init();! d+ H0 _( Z( u0 }
  22.   MX_USART2_UART_Init();' C6 `, _& v1 ~! b  i1 H! e' ^3 @$ Y
  23.   //开启ADC_DMA采集
    . L$ f; B& ~( b; x3 j
  24.   HAL_ADC_Start_DMA(&hadc1, ADC_Value, 100);//DMA自动把对应的通道值放入ADC_Value数组内8 i% Z6 x" \6 N3 V2 M& P6 b
  25. 1 E% O- W( Q: S$ {* r
  26.   while (1)
    " ^$ L. r. S8 h# {
  27.   {
    . W9 C  r1 A: @
  28.     //数据处理 与 DMA存值 不同步 ,在这里判断下转换是否完成,完成则进行数据处理
    % [6 F$ B/ ^+ ]4 W# |
  29.      if(HAL_IS_BIT_SET(HAL_ADC_GetState(&hadc1), HAL_ADC_STATE_REG_EOC))) |2 R4 n% m$ W4 {! v: `
  30.      {         
    ! C# E7 ^  c  V5 T5 J) Z
  31.                   for(i = 0; i < 100; i++)//数据处理 与 DMA存值 不同步  $ h4 B- z- _  _  Y1 q8 k
  32.                   {6 |4 ?; |0 v/ x7 t
  33.                         ad1 += ADC_Value<i>;       9 n/ w4 b) m7 l
  34.                   }  % A+ _  U4 W1 \( H( l' g( }! s
  35.                        ad1 /=  100.0;" j0 E) J9 O% k' O% u$ f  S- @% M
  36.                        printf("PA4 Reading Vol Value: %.4f \r\n", ad1*3.3f/4096);
    : X- v/ B% b0 K( ?4 P8 |$ ?
  37.                        HAL_Delay(500);2 [- A# ~- ]5 B
  38.         
    : k6 m3 b, D& {$ I: _
  39.      }: V' `) R# Y& ^
  40. , Z/ {" d; T! Z0 x
  41.   }5 h+ R, B: F' G- {) I
  42.   /* USER CODE END 3 */
    0 D; `) \- G# j+ N+ ~
  43. }</i>
复制代码
" L. ]' l, w& K7 c6 X
DMA:搬运数据思想$ u" [) Y6 M# V& m
将一块内存的数据搬到另外一块内存,(注意内存可位于系统内部,也可位于外部设备,其实就是一块地址,形象的可理解为buf[], 某个寄存器等。)# n, ^  W( ^* o+ X
在搬运的时候,1次搬运的数据大小必须是2的n次方(n= 0,1…),只要设置好相应外设的dma映射通道号(这一部分是由hardware designer设计的),以及其他相应配置,并使能DMA功能, 它就自动开始搬运了,(内存到内存这种方式是相对较快的)。* m5 v" \- Z# }( a7 T
- R/ r/ G2 {% v5 |. Q, d% T, w
2.3 多通道+DMA
5 f0 g, X( Z8 m/ m1 x2.3.1 STM32CUBEMX配置与单通道+DMA大致一样,需要修改的见下图(2个通道IN4、IN6, 开启连续扫描模式;并注意Rank下选择不同的通道,不配置默认通道 相同,我刚开始没有配置,结果2个引脚采集的值一样,浪费了半天时间找原因…)* j8 h5 t! ?) F$ L. x5 O

# e; N9 w9 r7 x& u: [' u& l; D4 I b72fff4c88c243a2a0382b90a9a193a7.png , ]6 l1 P- p' u) t0 T, k
6c1dc734495f40d099b7646fc5c47ffd.png + D3 u1 d  g' _1 H3 P# I

- N" |' {8 p) L; T2.3.2 配置工程文件名、路径、ToolChain/IDE——>GENERATE CODE ,完成之后打开项目
4 k2 Z/ C5 n: x; m% y
2 _1 f: `! C# V3 ^main.c
0 X+ A3 y4 _% N) U2 M! Z+ Y# F- d. H  E6 f: C* p  W: V
  1. #include "main.h"
    $ J  u% n% U; V, L4 ]
  2. #include "adc.h"6 s9 V- F+ R# ]4 [& d
  3. #include "dma.h") t6 D6 n! E. A4 J2 G
  4. #include "usart.h"
    / I* e" U" g& q7 {' @, U1 R4 l& |
  5. #include "gpio.h"
    " v7 M  H* }+ g# s0 c2 {
  6. #include "stdio.h"
    1 d$ o+ j3 `! a; r

  7. ' D8 V+ b0 M  B: v; c
  8. uint32_t ADC_1 = 0, ADC_2 = 0;) b# ]3 z* L& k2 J
  9. uint32_t ADC_Value[100];5 d) u, ~! E1 b; r5 A" d5 U
  10. uint8_t i;
    % O5 ]# D  j0 X
  11. ( Z; s. t, V! T5 b
  12. int main(void)8 e  y" r! [5 K! w: i+ e
  13. {3 i; Y* {/ i" V8 R1 k
  14.   HAL_Init();
    5 ]4 s6 D; ~; E- i9 I" [9 w
  15. + u$ n- {. I0 s
  16.   SystemClock_Config();
    & A& V" w0 [' \, _

  17. - y' x$ ?$ _4 {# W
  18.   MX_GPIO_Init();2 b- ]3 H% n* A; }8 v0 H
  19.   MX_DMA_Init();* {  D; |) d: u. n4 U
  20.   MX_ADC1_Init();" p7 M, |7 o5 i% I. y
  21.   MX_USART2_UART_Init();
      z  _+ ?5 C& l+ G3 B

  22. * i: P* W  L& q, B% t, C( e7 a5 w( t+ M) m4 `
  23.   HAL_ADC_Start_DMA(&hadc1, (uint32_t*)&ADC_Value, 100);//100数据量
    5 x3 w  v9 I9 o
  24.   printf("ADC Sampling start\r\n");# P3 k" K1 i# E( u0 e
  25. 8 \/ m% i: o4 a( u$ G, W
  26.   while (1)
    . }' r/ q* A3 p7 L1 I1 B: E) G- U( n
  27.   {
    ' J) _% e! D7 O  ^# L
  28. , }2 v: {' l; n4 ?* v. F) Q! ~
  29.       HAL_Delay(500);//这里不加延时,采集输出值第一次为0 * `$ K5 u; s+ X/ C) ^( m7 Y
  30.       for(i=0; i<100;)% y# @5 f; x9 V. e. G
  31.      {
    ! N4 i( ?$ K' U
  32.       ADC_1 = ADC_Value[i++];   
      E8 a1 Q1 x. R" {' E& O
  33.       ADC_2 = ADC_Value[i++];
    7 q& n8 r3 m1 |: d  X& L
  34.      }
    % V7 t2 B; L; u& z
  35.       printf("double channel ADC test\r\n");
    ! c# J5 R6 B6 K
  36.       printf("ADC_1 = %1.4f\r\n", ADC_1*3.3f/4096);- i. i) z1 E+ \- ~" t
  37.       printf("ADC_2 = %1.4f\r\n", ADC_2*3.3f/4096);* ?/ q) @- f" k

  38. 2 n) [+ K3 N1 r/ B
  39.   }
    7 p& Q9 q# l) M) ]! z, b

  40. 8 F# o& ^) r3 u# u; h" C- J

  41. 5 F! O2 D2 J! W1 k% F9 c  o7 h
  42. ) Y$ ~4 Z& y) `% I
  43. }2 Y) o5 ?' Z# D. O6 G! V
复制代码

# e' N6 U7 g! I6 I函数HAL_StatusTypeDef HAL_ADC_Start_DMA(ADC_HandleTypeDef* hadc, uint32_t* pData, uint32_t Length);//第三个参数我还是不明白,但是支持数据量,库函数这样解释:
5 j6 C! _; s5 z$ H/ ~, K+ K  E1 ]9 ^% L/ _! D# M( @' D$ w# K
很多人说是数据量,不是长度,我很纳闷(数据量分2种情况:
. B) s' q8 ~- b0 U# G- F+ u8 o; T
* W" J9 C8 N! I# J# H6 i( }- P/ |1.单通道 1次将采集的length个数据存放到存储区,然后执行下一次采集存放,
% x" H3 V/ H7 V( L% s! M, {2.多通道 1次将采集的length个数据存放到存储区,然后执行下一次采集存放,length应为通道数的倍数 保证每个通道的数据量持平% X3 }8 U0 L  |6 c! X. o
————————————————
' o7 e# k2 S5 b' Z版权声明:gfanbei, h; ?; h* m/ j  ?, W+ h+ m

4 |  ]$ c$ N4 d  v
5 r( w+ \. W2 C# B4 C% J* r! Y; |* r( t
f38a2a0d7066494a9a6e62bbd4d9d7be.png
赞 收藏 评论0 发布时间:2022-11-1 17:10

举报

0个回答

所属标签

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版