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

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

[复制链接]
攻城狮Melo 发布时间:2024-5-25 13:31
之前有陆续介绍STM32的ADC采样与板载运算放大器,本期我们将二者结合,顺带再完善一下ADC采样与DMA。5 ~. d3 {+ r# V4 S9 n  O
/ `2 q% W7 [' O7 q0 j
板载运算放大器# A; u/ d8 T$ z' `( H  S
板子使用的ST公司的STM32G474RE部分板子上没有板载OPAMP的话可以忽略运算放大器的部分。2 A3 z8 i( g  |, l% `

" r. Y3 G/ c, a# I  b7 B; g1 T 微信图片_20240525133129.png
6 ]+ u9 M8 q% ~2 G1 p  M( Q
: C3 A7 N  ]" @7 M6 z5 e9 i7 A. n9 _( @, ?% i
微信图片_20240525133126.png . b+ L) K2 ^1 i- Y

5 |( N1 _+ l6 [8 r3 \2 u我们打开运算放大器的跟随器功能,将跟随器的输出和STM32的ADC绑定,使得我们的信号接入PA1即可通过跟随器被采样。
2 Z' e& L7 |9 [' i# f4 O6 b* d  }7 U4 {
ADC配置' ~' h; ?" o0 g% [
6 \7 Z# X* r. x5 j) p9 [& y' r$ c
微信图片_20240525133123.png 1 A5 t$ }. n5 \
) F$ R+ R  \5 p" a: D  x: j- k
开启ADC1_12,这里通道12只能配置为单端输入,其他的通道可以配置为差分输入。' f9 A& B! `' Q9 s
+ e& e; B6 c2 A
微信图片_20240525133120.png
# m. X2 V6 j- n* @0 _+ e

2 c- x" h: d5 k' b& V& `6 e5 b4 \添加DMA传输,模式选择正常模式,这样子我们只采集一组ADC数据,这里如果开启了Circle模式的话,环形存储区会导致DMA后面采集的数据覆盖前面采集的数据,导致数据乱飞。
6 ^# R9 I/ ?5 z$ d8 m  Q- ]! L2 ^+ G5 S# {2 P- \- Q' s" _' s
微信图片_20240525133117.png # @4 f# T/ t5 T/ ?

8 a" B+ e# V; L; V: s2 j/ X4 z触发方式(启动ADC转化)我们选择定时器8,这边可以是任意定时器推荐使用的是低级定时器,这样子就可以控制我们的采样率。
! Q% w+ b8 U  ~' O5 _
$ S( v2 t6 ^' [9 x0 S
定时器配置
2 B+ J  q$ y0 a5 I这里解释一下Timer 8 Trigger Out event.  }' k; j4 s. ?' @* C+ a" j+ i
0 A$ l! b5 D/ m' c" E/ z0 v  N; m% j
定时器(Timer)的触发输出事件(Trigger Output Event)可以用于生成特定的触发信号,以触发其他外设或事件。
* d' K7 M  a; {5 ^$ L; ^2 h" F# V/ s& k" {' s2 L. O$ H( \1 F
在STM32定时器中,可以配置不同的事件作为TRGO信号的源。常见的触发源包括:2 @6 `. T8 A4 l
更新事件(Update Event): Q& S$ A- I4 v, v. N' R0 w4 X
当定时器的计数器溢出或达到设定的周期值时产生的事件。5 s( c: F2 k9 ?$ S
捕获/比较事件(Capture/Compare Event)
. U% r, _" ^" s2 ?当定时器捕获输入信号或计数器值与比较值匹配时产生的事件。
; ^" H2 L6 [; B5 P+ y, }$ i输出比较事件(Output Compare Event)* p$ R8 l9 g" b0 C* |2 b
当定时器的输出比较单元产生一个输出信号时的事件。
, K0 y; Q+ i+ y5 f3 b
1 j/ i" t; W; g6 @8 W" s1 z

2 l/ @# J4 i4 I9 k1 j 微信图片_20240525133114.png   c- Z/ t5 Z' A( i0 w

$ b' M, E* i+ H! X. [8 a! ?这里设置好我们的分频系数,计数值,设置一个Update Event更新事件来触发定时器采样。这里我的主频是170MHZ,分配系数是169,溢出值是100,这样子过100us触发采样,采样率固定下就是10KHZ。% W" U- I: ~0 g& O) `
8 i5 {8 H: ~+ a+ \7 c! X
我们强调过好几次,根据奈奎斯特采样定律,采样率必须高于信号频谱最高的两倍,当然我们在性能充裕的情况下最好是在最高频率的倍数高一点。. T3 q9 X3 l! C7 N& J

" c$ u9 ^8 s9 C! | 微信图片_20240525133110.png
4 o7 Y3 a9 b0 Y9 h! V) q$ p
* R! L: B1 U1 L最后别忘记开启相对应中断源的中断。6 `4 X1 |/ z. H2 j8 b: o2 B
6 n5 t2 v' d7 ^* _
接着就是创建工程。3 O9 i. _3 e  ^; D, X

) u# e7 M. B0 k1 K" _- x2 Z
  1. #define ADC_Lenth 1024
    , l6 `/ H8 T: `' n' t, k0 w
  2. int32_t ADC_Value[ADC_Lenth];
复制代码
$ s4 ]4 }4 ?' ^- C1 h
; r8 [6 J& a* _  \7 k0 N
定义一个数组用以充当DMA的缓存区。& [" s  R4 f, H; j" f
  1.   while (1)0 N8 d% p2 ~" _8 T" O$ a
  2.   {
    2 B, |5 _; {$ t8 X! a" i
  3.     /* USER CODE END WHILE */
    5 p& R5 I* H% v1 Z1 l" w0 S

  4. 4 B! c1 @! ~1 ~, L2 I
  5.     /* USER CODE BEGIN 3 */7 ?: C$ U8 a, k4 q. \
  6.     // 检查DMA传输是否完成
    : b! L* [) x$ v
  7.     if (HAL_DMA_GetState(&hdma_adc3) == HAL_DMA_STATE_READY)
    0 O1 T2 ~1 K( _# V& `
  8.     {# r1 }" }& T- R( d4 }% A
  9.         // 处理 ADC 数据
    / r0 O8 c3 C# T+ w3 d: r
  10.         for (int i = 0; i < ADC_Lenth; i++)
    7 j8 T; T" Z/ ?+ n
  11.         {0 I1 F: c6 `8 u/ T. _6 j
  12.            printf("A:%d\r\n", (uint16_t)ADC_Value[i]);
    ! G: \" }4 z3 j! B, }' g
  13.         }# e; q: A0 l5 ~$ s- L2 b
  14.         
    5 q; B6 q9 Y+ c' J, [1 @& Y# \7 N) ^
  15.           s# U- B+ ~3 O2 |
  16.         HAL_ADC_Start_DMA(&hadc3,ADC_Value,ADC_Lenth);
    0 h, i7 R  Y5 a! B
  17.         
    - f, {8 P3 t' D$ M) r% G, C/ r
  18.     }4 ~! V% E- u% t  O
  19.   }
复制代码

3 b) }0 g2 ?9 }$ a2 v# P1 l8 @在主函数中使用轮询的方式等待ADC传输完成,传输完成后我们利用串口打印。
$ ?; z8 t9 H9 O! O% x% r! R) P& N8 E$ y# q
我们使用HAL_DMA_GetState函数来获取状态。
  1. - HAL_DMA_STATE_RESET:复位状态5 ?4 u9 z( U2 L2 G* g5 r
  2. - HAL_DMA_STATE_READY:就绪状态
    0 O3 y+ O% P/ C: k+ r
  3. - HAL_DMA_STATE_BUSY:忙碌状态
    0 C2 x% s! G3 I. P/ i5 p% Q
  4. - HAL_DMA_STATE_TIMEOUT:超时状态
    8 M. _3 n/ a0 p) _& K2 @6 F
  5. - HAL_DMA_STATE_ERROR:错误状态
复制代码
当DMA属于就绪状态就说明传输结束。这里有一个坑点,关于( d1 Q8 l" q3 Y. [: H# X6 T, n2 p: x

9 r, n2 ~0 ^) F% P1 `0 y1 y  Y
HAL_DMA_PollForTransfer这个函数按理来说是用来查询传输结束的,但是不知道为什么使用起来很奇怪。" ^! b1 s6 E2 l9 n

0 x' z' ]# B/ e& O
微信图片_20240525133107.png 5 ]! X! V) W) `/ i/ M( V. ]+ N/ p+ f
+ H( D* K9 N+ l4 ^( [4 B
这是我们采集的方波信号
1 I1 F9 I+ o6 V- O1 {7 ~! ^7 |" |# a$ G; B+ i; ]+ H

- c: r3 Y% N1 o" X转载自:电路小白
' L" e2 a- K7 q0 Z1 d  j如有侵权请联系删除
: Z9 n! z6 p' w3 ]

0 E% g4 ~1 O, d  k; X: W. F) e- d' R7 j3 L+ M" e4 w
1 x3 i) x0 a$ `/ n/ _0 o/ p
& K9 V" ?% D- E
收藏 评论0 发布时间:2024-5-25 13:31

举报

0个回答

所属标签

相似技术帖

官网相关资源

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