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

基于STM32的ADC+DMA采样与板载运放跟随经验分享

[复制链接]
攻城狮Melo 发布时间:2024-5-25 13:31
之前有陆续介绍STM32的ADC采样与板载运算放大器,本期我们将二者结合,顺带再完善一下ADC采样与DMA。
+ q# g# x; e7 q2 B6 t: L" J' j
" }) y- N; {9 e) l' P5 b
板载运算放大器
, A8 h2 g5 O- }1 E5 T; Y6 e板子使用的ST公司的STM32G474RE部分板子上没有板载OPAMP的话可以忽略运算放大器的部分。
' z9 m# ~% N) O% G3 r+ r8 d
* e3 A( V1 c# P( r) P3 Q' B% p- ^ 微信图片_20240525133129.png 3 s$ ~( ^2 R. H% G* _8 X0 N/ h
7 |2 w, S/ x6 s& F
: @5 F9 t% p+ K1 ^  M0 I/ f9 ^
微信图片_20240525133126.png
# `  e- Z5 {% t& C# ^  ^9 B/ t5 A! J4 W6 `3 E* N3 ^0 b
我们打开运算放大器的跟随器功能,将跟随器的输出和STM32的ADC绑定,使得我们的信号接入PA1即可通过跟随器被采样。
" V) o% `5 ?, ?+ _( r1 H% `0 ^) P
ADC配置
$ V, i* Z! |8 n7 [
; Y4 U) j& Z8 {, {8 v6 S 微信图片_20240525133123.png ! [- y" l( ^+ t" j

3 z# B5 q1 D5 y0 `开启ADC1_12,这里通道12只能配置为单端输入,其他的通道可以配置为差分输入。
  t! a5 h$ I! Y2 y" R7 r
1 ]. N8 X: N: K0 c 微信图片_20240525133120.png
  o9 s4 A& _! z% w2 C$ i' H% Q
8 Z& P3 g/ J/ R( H0 `
添加DMA传输,模式选择正常模式,这样子我们只采集一组ADC数据,这里如果开启了Circle模式的话,环形存储区会导致DMA后面采集的数据覆盖前面采集的数据,导致数据乱飞。7 c. l! Y: f- p& k

& S8 S* `7 A2 [; m5 q
微信图片_20240525133117.png
, R( l9 v0 }4 ^6 y  E; w, V) c2 C/ e! w; D' a& H+ P0 _6 u4 `
触发方式(启动ADC转化)我们选择定时器8,这边可以是任意定时器推荐使用的是低级定时器,这样子就可以控制我们的采样率。, \! t) B3 a3 t
- r/ O! v6 g4 m; _# t& a
定时器配置
. q$ Z7 \; A# z( h这里解释一下Timer 8 Trigger Out event.
3 J7 u' y& [5 ~$ K& d8 N$ j8 e. N0 v+ w6 C- ?& R3 [3 T" L
定时器(Timer)的触发输出事件(Trigger Output Event)可以用于生成特定的触发信号,以触发其他外设或事件。
/ c* p' x5 }5 h4 P3 n# L! n8 A) d6 f" |9 n' q
在STM32定时器中,可以配置不同的事件作为TRGO信号的源。常见的触发源包括:
; ]  q, P3 U6 u9 i0 E1 _更新事件(Update Event)" f" B& o  p7 X2 ?  @2 Z
当定时器的计数器溢出或达到设定的周期值时产生的事件。6 A$ m5 Y9 J' ~1 ]
捕获/比较事件(Capture/Compare Event)
9 Y/ ^% P% E2 I+ ~' D! p3 g当定时器捕获输入信号或计数器值与比较值匹配时产生的事件。
8 W/ V% }* U# K7 A输出比较事件(Output Compare Event)
0 ^# t% z5 ?% k当定时器的输出比较单元产生一个输出信号时的事件。* ?/ u/ w0 Q1 i7 q6 e
& A1 \# D  q8 }- S) R: s  a
& b( B8 m  I8 u% J8 b
微信图片_20240525133114.png
) |- A- p' C$ Q- r: Z. w
5 G5 Q* y& D( l
这里设置好我们的分频系数,计数值,设置一个Update Event更新事件来触发定时器采样。这里我的主频是170MHZ,分配系数是169,溢出值是100,这样子过100us触发采样,采样率固定下就是10KHZ。7 W/ w" f4 f. ^' m- x2 R

: I/ x: G9 w  {( N8 @- g1 {7 S
我们强调过好几次,根据奈奎斯特采样定律,采样率必须高于信号频谱最高的两倍,当然我们在性能充裕的情况下最好是在最高频率的倍数高一点。* H4 w4 o" g0 X: T. A, n5 b

1 t) v: w! t$ b$ t: I 微信图片_20240525133110.png
/ g- K$ ?; J2 j) w! q3 k5 G$ `
' P) e0 e/ x; ~; l/ a4 t6 ^最后别忘记开启相对应中断源的中断。- j+ ^& k1 l. ?

4 w8 g( S3 L; F9 c
接着就是创建工程。' \6 \3 O4 W" M) l) K6 R" l
1 s2 }9 [3 y: V
  1. #define ADC_Lenth 1024
      B. y  |+ {( A- l& l* C- P- [1 O7 N
  2. int32_t ADC_Value[ADC_Lenth];
复制代码

4 i+ Y* {$ `1 n3 }+ U: R; D, A. i- @; _; ^! j6 k6 z4 K$ w
定义一个数组用以充当DMA的缓存区。
% K% B. _/ d- b/ Z; Y
  1.   while (1)
    ! T. |! z4 [5 N: X, M
  2.   {0 {8 ]' q& y5 _5 V% l
  3.     /* USER CODE END WHILE */6 J  u7 n6 \' y. A$ X, z

  4. ' `% ?4 `5 ]) A# \8 K9 ^
  5.     /* USER CODE BEGIN 3 */+ u, ?" \4 @( l% M# s+ r) o
  6.     // 检查DMA传输是否完成
    & a, M0 J; X2 y" W7 c* x
  7.     if (HAL_DMA_GetState(&hdma_adc3) == HAL_DMA_STATE_READY)
    5 J6 p& P# `* p) ^) i* Z- f$ c. t3 \
  8.     {
    3 t$ ^9 }' p: v: E6 R0 T: [
  9.         // 处理 ADC 数据1 i0 s' G9 R% m! M( G
  10.         for (int i = 0; i < ADC_Lenth; i++)- N; p) Z/ P1 U8 ~
  11.         {
    2 r- A2 H* x. V9 v- y4 _1 |
  12.            printf("A:%d\r\n", (uint16_t)ADC_Value[i]);' ?9 p: j1 f! n/ g7 g6 q
  13.         }! c6 h1 V% T8 V% w( g! C
  14.         
    5 n% G+ E0 z* Y0 X
  15.         
    ' _  ]1 b  j, H. l) K
  16.         HAL_ADC_Start_DMA(&hadc3,ADC_Value,ADC_Lenth);$ s7 `" j( U0 }' Y) `& [( S9 j
  17.         8 \# t2 ^- n! X- x4 J
  18.     }; i/ e& ^+ I) E5 K( f+ K
  19.   }
复制代码

$ `& N, S: @& P# X7 {. n7 ]: W在主函数中使用轮询的方式等待ADC传输完成,传输完成后我们利用串口打印。  N; }2 [0 O6 I/ t$ R4 A

3 M5 ]9 L! M0 i; M6 e0 u1 Q. E3 w我们使用HAL_DMA_GetState函数来获取状态。
  1. - HAL_DMA_STATE_RESET:复位状态
    7 p9 }4 x. S" T$ p7 |# m# A
  2. - HAL_DMA_STATE_READY:就绪状态& v0 Z- r* ~+ ?) g, m5 W4 y
  3. - HAL_DMA_STATE_BUSY:忙碌状态
    ! {$ s. [; Y" v- g) t4 B
  4. - HAL_DMA_STATE_TIMEOUT:超时状态
    $ }' R& o6 A9 W3 |3 i% F0 e. G# g- m
  5. - HAL_DMA_STATE_ERROR:错误状态
复制代码
当DMA属于就绪状态就说明传输结束。这里有一个坑点,关于
+ N; \9 U* R/ F1 @5 e9 q, g
/ W% i8 V1 S+ a
HAL_DMA_PollForTransfer这个函数按理来说是用来查询传输结束的,但是不知道为什么使用起来很奇怪。" i" e; d6 C  S4 k( V: h
9 T" T7 s: E, `
微信图片_20240525133107.png * }  W  ?5 M8 N6 e( }% P5 C" n
! x0 z  |7 u* P
这是我们采集的方波信号7 g+ N. A, X& u' V! A$ s  }* y
& |; y: J8 G; ]& J. Q9 R. x5 b
7 h2 k5 N' I; o# U5 x
转载自:电路小白+ K( v. k, X( {- w. s9 ~
如有侵权请联系删除$ t# y5 m$ A3 L! _

5 N) e$ V" W" O4 A. l6 M& D; V; R) S3 y4 s8 z

; K5 n8 M' R) u4 K* F) q8 U% M9 z, k
; Z8 @0 k# B& z/ Z5 ^
收藏 评论0 发布时间:2024-5-25 13:31

举报

0个回答

所属标签

相似分享

官网相关资源

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