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

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

[复制链接]
攻城狮Melo 发布时间:2024-5-25 13:31
之前有陆续介绍STM32的ADC采样与板载运算放大器,本期我们将二者结合,顺带再完善一下ADC采样与DMA。2 E2 y) K% Z% T# K. j( [

8 u' D- K) o! f' z5 N5 m
板载运算放大器
0 X) X. q4 w6 Q2 L, A4 [板子使用的ST公司的STM32G474RE部分板子上没有板载OPAMP的话可以忽略运算放大器的部分。2 }1 n0 w0 A; [5 M* L
. }% O# T7 D4 k9 g* s9 a" r
微信图片_20240525133129.png / S8 Z; d1 y4 P/ P. i
' }5 d- B3 d5 P. g7 t7 ~, `, b* c2 E
' X1 B1 `; J, n. c( W4 i/ S
微信图片_20240525133126.png 5 j  ]6 |! w) P! ?% A

, _  d1 T( G2 O6 P. O* g我们打开运算放大器的跟随器功能,将跟随器的输出和STM32的ADC绑定,使得我们的信号接入PA1即可通过跟随器被采样。
. r8 ?$ y- j$ a2 L  O" k' h/ n/ u/ T$ e) v) d6 t! N3 f
ADC配置
' N$ v  c) B8 j/ B3 q) W) L# ^
, `/ U% [2 Z: @, Z' ? 微信图片_20240525133123.png
7 N  r, U& w8 }0 F- @+ V
; V' o' X( l3 D5 J, E0 |
开启ADC1_12,这里通道12只能配置为单端输入,其他的通道可以配置为差分输入。
& h7 t/ m" Y/ j- t+ y) e7 p4 m6 n! X" H( D' G
微信图片_20240525133120.png $ }: Z* @) l0 S! i: n( J1 X
* ?2 R, A5 g: y
添加DMA传输,模式选择正常模式,这样子我们只采集一组ADC数据,这里如果开启了Circle模式的话,环形存储区会导致DMA后面采集的数据覆盖前面采集的数据,导致数据乱飞。2 b0 a3 U3 |" j

2 h: ~# P: x5 ?# \% I' g4 u
微信图片_20240525133117.png " Y7 C0 A" a: H/ }! n' N- h0 j* v
- K! W* F% o8 j+ y! N
触发方式(启动ADC转化)我们选择定时器8,这边可以是任意定时器推荐使用的是低级定时器,这样子就可以控制我们的采样率。
, M0 v& P6 x) Z! o5 O% j8 D; U& @% x1 }8 B" N2 S1 |, \9 [
定时器配置
. y) `" a/ H- r& D! [& z% P这里解释一下Timer 8 Trigger Out event.
, t- k" V6 P  N& r' H
, I) ]! c8 I. v, T
定时器(Timer)的触发输出事件(Trigger Output Event)可以用于生成特定的触发信号,以触发其他外设或事件。: Z0 E+ s3 P, N7 k

) ]+ T0 ~" A1 o
在STM32定时器中,可以配置不同的事件作为TRGO信号的源。常见的触发源包括:* ]4 u! l1 N3 s+ M2 L# q  a8 ]3 B
更新事件(Update Event)8 ^4 b/ ~  T  ]& w( a4 M+ M/ b
当定时器的计数器溢出或达到设定的周期值时产生的事件。/ @5 `7 ]7 R) S' ]/ h5 X2 Q- Y7 X
捕获/比较事件(Capture/Compare Event)
6 O8 V+ D  n+ y* Z) J- h0 `当定时器捕获输入信号或计数器值与比较值匹配时产生的事件。
( T; W: A2 [6 E3 f输出比较事件(Output Compare Event); J  ?7 p' d& {: X; E
当定时器的输出比较单元产生一个输出信号时的事件。
- W( s6 c1 n. m' r/ d$ S) {  }) n! I( z* @# j' t

: b: s7 b2 T3 l4 l 微信图片_20240525133114.png , M" G* E; C# `. o6 Z

. T% Z' h! _- t) \3 g这里设置好我们的分频系数,计数值,设置一个Update Event更新事件来触发定时器采样。这里我的主频是170MHZ,分配系数是169,溢出值是100,这样子过100us触发采样,采样率固定下就是10KHZ。/ @5 U$ h5 [8 L, B2 f3 W

7 D+ h  @1 M2 l
我们强调过好几次,根据奈奎斯特采样定律,采样率必须高于信号频谱最高的两倍,当然我们在性能充裕的情况下最好是在最高频率的倍数高一点。( k+ D( c( \- v# t8 F4 y$ C

6 A3 W( v) G! I$ c- z" c 微信图片_20240525133110.png , {: l: v, C! H/ s2 X& A: D

2 c; A0 m2 a  ~  n# J最后别忘记开启相对应中断源的中断。, m# @2 B8 |" f. f8 }
+ x; G( d7 `5 V5 N# f5 }0 E
接着就是创建工程。) w. M" b( _' F/ x( d  H7 X

& S% }1 R4 g, n( x4 {
  1. #define ADC_Lenth 1024* x) G9 U4 q1 c  d9 u
  2. int32_t ADC_Value[ADC_Lenth];
复制代码

" }6 j* A4 c+ E
. G- W: N& |5 E( Y
定义一个数组用以充当DMA的缓存区。: }1 @/ l- ~# Y8 a3 b; a) k; ]+ D) J
  1.   while (1)
    2 k: }% k8 ]# H$ g. C6 ~! u& N; K5 z
  2.   {! m3 ~! X: b' i$ o/ F
  3.     /* USER CODE END WHILE */
    ! R2 E- Q5 L7 Q7 V; m. y+ O& V' q

  4. 2 s) ]7 b+ x0 F5 s* c# n4 s
  5.     /* USER CODE BEGIN 3 */
    1 l1 `2 _7 X3 B3 P- s$ z
  6.     // 检查DMA传输是否完成
    1 h0 [9 |, y# b5 P7 x
  7.     if (HAL_DMA_GetState(&hdma_adc3) == HAL_DMA_STATE_READY)
    6 Q  j) l7 u2 B+ A% f* \
  8.     {
    0 k4 h& ~. p+ o( [/ D  C/ k
  9.         // 处理 ADC 数据
    9 n; j: A. e$ H. Y7 i
  10.         for (int i = 0; i < ADC_Lenth; i++)3 U0 P6 z7 i: n' U
  11.         {3 f2 H0 V( G  {2 e% h2 L, V
  12.            printf("A:%d\r\n", (uint16_t)ADC_Value[i]);
    9 @! v5 @6 }' b
  13.         }: ~/ w, D, x6 J- C; S, x
  14.         
    ( u& ?1 H$ ~  \" h& A9 J
  15.         % V( f1 F" Z( h% u2 W4 R9 g: F
  16.         HAL_ADC_Start_DMA(&hadc3,ADC_Value,ADC_Lenth);) T, U( m& a: `" p/ E% r
  17.         % `- F% G: z7 b# X4 v
  18.     }" T3 p5 D& `; h) F8 p; V( c4 A3 O9 K
  19.   }
复制代码
& f" m8 G  O2 K# o1 [4 G
在主函数中使用轮询的方式等待ADC传输完成,传输完成后我们利用串口打印。' r9 c! w( e+ G' v/ r

* Q& I2 ~  ?+ X5 a7 A9 L3 a我们使用HAL_DMA_GetState函数来获取状态。
  1. - HAL_DMA_STATE_RESET:复位状态
    ! `7 }' l: U9 I7 @2 z
  2. - HAL_DMA_STATE_READY:就绪状态4 [1 L/ _( s; P# x- }/ O2 T
  3. - HAL_DMA_STATE_BUSY:忙碌状态
    * _% g" }+ b' j/ L4 u- n$ v
  4. - HAL_DMA_STATE_TIMEOUT:超时状态
    5 \  _: M) x2 A" y  Y9 w
  5. - HAL_DMA_STATE_ERROR:错误状态
复制代码
当DMA属于就绪状态就说明传输结束。这里有一个坑点,关于/ q2 {9 G! J! w( X! I( U

2 {+ L5 v+ k. p. R
HAL_DMA_PollForTransfer这个函数按理来说是用来查询传输结束的,但是不知道为什么使用起来很奇怪。
, v, g* v/ m9 c- b% d, e2 b2 W( e( y8 T; T: ?
微信图片_20240525133107.png
$ @0 K5 [" D3 Y2 O3 Y1 [
$ e  s& y$ A5 M$ c这是我们采集的方波信号
5 b3 p3 I9 V* k4 \
& C6 z* n1 R3 ]. v% N/ B* q

9 P) \# Z5 h7 J2 Y- U0 x转载自:电路小白
' D" ?% X2 s8 b; ?0 {' ~如有侵权请联系删除
. F1 n1 O3 f+ j" q
- l& X( L" D' n
+ W& ^& x! \* m+ r  V' c

6 ]2 w' [6 F) h- T0 b' `8 H+ H" F
收藏 评论0 发布时间:2024-5-25 13:31

举报

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