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

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

[复制链接]
攻城狮Melo 发布时间:2024-5-25 13:31
之前有陆续介绍STM32的ADC采样与板载运算放大器,本期我们将二者结合,顺带再完善一下ADC采样与DMA。. g& r) x5 U, F) m8 q  t

) [3 S1 K; i" a+ ?* l) S: {; D
板载运算放大器0 ?- x& ?( j8 A
板子使用的ST公司的STM32G474RE部分板子上没有板载OPAMP的话可以忽略运算放大器的部分。# t  Q) N) G9 K

- W  h2 g# s7 i1 u8 _ 微信图片_20240525133129.png
0 L2 c" d: [) q. O: m1 c9 T1 {8 {' j# t% K3 A6 i$ \

( r3 F  |# ]8 _* G 微信图片_20240525133126.png $ M! \  H: r; K2 t' D- M. N* Y

6 f7 D1 M- Z( L8 a* }4 i+ W1 s我们打开运算放大器的跟随器功能,将跟随器的输出和STM32的ADC绑定,使得我们的信号接入PA1即可通过跟随器被采样。
2 E# E' h$ h; ?) t
( C7 o/ B" I7 ~0 @" [4 @+ a
ADC配置6 B. h2 Q; O  ?2 Z# E6 J( C* v
0 ^- z) b4 }  W! M1 ~
微信图片_20240525133123.png " `- b6 ?  F$ J3 U  J# j: ^

  E! D) }! ?3 t  ~开启ADC1_12,这里通道12只能配置为单端输入,其他的通道可以配置为差分输入。
1 F- B$ t/ N5 A% q" [( K9 c, d4 G8 u# B) z+ Z- }+ n
微信图片_20240525133120.png # P( c4 w0 t- s8 M8 b3 Z. b- }
0 `1 i/ _( z. e* I& C' k) W
添加DMA传输,模式选择正常模式,这样子我们只采集一组ADC数据,这里如果开启了Circle模式的话,环形存储区会导致DMA后面采集的数据覆盖前面采集的数据,导致数据乱飞。
; L( e. F) f6 S4 M3 @$ W- W/ C5 x& S
微信图片_20240525133117.png ( `3 e2 _1 W6 p8 P. Z, |
# P4 K/ X$ y& ?1 K6 T7 v
触发方式(启动ADC转化)我们选择定时器8,这边可以是任意定时器推荐使用的是低级定时器,这样子就可以控制我们的采样率。7 U0 G* L" {+ h- o" l- Z

# }( e' `, H" `7 Y6 i( f! k
定时器配置
5 b1 X; k; J, G/ ~5 m9 a* J7 T! M" W这里解释一下Timer 8 Trigger Out event.' X! \; R( R8 g( H3 m8 ]- o7 Q/ H
; z: r7 m5 S6 ?7 f8 @
定时器(Timer)的触发输出事件(Trigger Output Event)可以用于生成特定的触发信号,以触发其他外设或事件。$ g3 d+ d2 I0 F) i9 K' F2 C) m

) H0 H5 d0 B; m7 Z1 z2 z6 v: ^
在STM32定时器中,可以配置不同的事件作为TRGO信号的源。常见的触发源包括:
5 v6 b' R- y8 l$ x: x更新事件(Update Event)7 |2 s0 F9 d+ K& b
当定时器的计数器溢出或达到设定的周期值时产生的事件。0 G1 ^3 _# C/ {; _- j
捕获/比较事件(Capture/Compare Event), g1 g$ K/ e4 a; u# i" ^; q; r
当定时器捕获输入信号或计数器值与比较值匹配时产生的事件。
3 |9 ]0 Z9 T( ~; U+ n- m2 Q* C输出比较事件(Output Compare Event)
: W# G6 J5 r! |2 p) u, W, m, c当定时器的输出比较单元产生一个输出信号时的事件。
9 l: d5 A" ?8 M. |# {) B
* ^2 {% g/ j$ W/ i2 P( j5 Q% S3 G
" |8 p: ~5 k; g/ i1 Y8 l2 z
微信图片_20240525133114.png
9 g/ z6 e+ `% n: Q

, [. s% W* S# S0 j8 g这里设置好我们的分频系数,计数值,设置一个Update Event更新事件来触发定时器采样。这里我的主频是170MHZ,分配系数是169,溢出值是100,这样子过100us触发采样,采样率固定下就是10KHZ。0 Y% X' l1 t! y( {0 }2 J+ f6 M
) v6 b" m% u% H$ @1 t: _+ |6 q0 Y) M
我们强调过好几次,根据奈奎斯特采样定律,采样率必须高于信号频谱最高的两倍,当然我们在性能充裕的情况下最好是在最高频率的倍数高一点。
3 J: p% _0 a/ u
* e( @0 e/ r* F7 S" g: X 微信图片_20240525133110.png
7 k: A5 g3 Q1 ]# F" x
" @7 H$ ?9 ^: ^6 p7 {3 V最后别忘记开启相对应中断源的中断。  q' S# r) E6 a. v- W! g
$ A3 m* f0 c1 l2 C: U
接着就是创建工程。
$ J6 a" g- }( o, I' p- z( X; Y0 [% }( L5 G
  1. #define ADC_Lenth 1024- o5 M! U5 ]8 ?. R, V: Z6 ~. s4 ]
  2. int32_t ADC_Value[ADC_Lenth];
复制代码
1 X8 J+ E" T2 D4 S

: c4 n; V5 a% F' |( V
定义一个数组用以充当DMA的缓存区。7 S. U9 m5 O$ ~
  1.   while (1)! y- ?9 U! v# G) H8 l0 a
  2.   {& i& w, Q# K. e8 i& U: S
  3.     /* USER CODE END WHILE */
    % Y. C! Y7 r+ G: ]' @' @, ~

  4. & O  D- v3 v8 n' M0 N( b" i. f
  5.     /* USER CODE BEGIN 3 */1 R7 z+ G) q% ^& c1 _
  6.     // 检查DMA传输是否完成" t% @5 R# i/ u) D0 g8 U
  7.     if (HAL_DMA_GetState(&hdma_adc3) == HAL_DMA_STATE_READY)
    , g6 U' t6 [7 Q& X
  8.     {
    8 U3 O" W7 f3 J4 z( c
  9.         // 处理 ADC 数据
    7 d) F( a# ^' d4 Q" |  R7 |
  10.         for (int i = 0; i < ADC_Lenth; i++)
    3 q! i& A- v" Y: Y' b4 j2 Z
  11.         {
    1 D% ?; x2 f6 O; p* r, D- ^
  12.            printf("A:%d\r\n", (uint16_t)ADC_Value[i]);
    % g) T1 K- ?; p) C  ]+ o2 t) {
  13.         }0 I: O+ n( N( J  h9 |/ l) |% O9 @
  14.         $ B9 w+ a  }  l" r* ?  {- u
  15.         ' |- ~/ K0 ^5 |, A
  16.         HAL_ADC_Start_DMA(&hadc3,ADC_Value,ADC_Lenth);# ^1 M9 z9 |8 n( G& }
  17.         % L( U! ~$ {! q- \! V  N! ~! ?9 F& n
  18.     }0 ]' T; b/ ]& b; J* c9 x' [
  19.   }
复制代码
2 {: O/ ]: F  B  p! o& n
在主函数中使用轮询的方式等待ADC传输完成,传输完成后我们利用串口打印。
' n* H: M$ A( P8 K, u/ H! \
! }/ f3 y6 k3 g# N2 f7 {: B我们使用HAL_DMA_GetState函数来获取状态。
  1. - HAL_DMA_STATE_RESET:复位状态
    ( o. ]" d7 C& u9 D. R
  2. - HAL_DMA_STATE_READY:就绪状态* Y5 C* D% X4 m8 M$ X* Z
  3. - HAL_DMA_STATE_BUSY:忙碌状态( F( h# j; B  H' E! g1 x7 S
  4. - HAL_DMA_STATE_TIMEOUT:超时状态
    * @: W, {' c' \, F  ?+ \1 Z& `) F. W
  5. - HAL_DMA_STATE_ERROR:错误状态
复制代码
当DMA属于就绪状态就说明传输结束。这里有一个坑点,关于
% o$ ~: W/ R# @. q/ w$ z- e' ?  u7 ]/ E; i
HAL_DMA_PollForTransfer这个函数按理来说是用来查询传输结束的,但是不知道为什么使用起来很奇怪。
. m) e+ l: u) L7 n- U: _" H3 E6 h; {4 ]
微信图片_20240525133107.png   B/ H) T4 s( h' z# o. t

7 `, g" s. F# Q! S" t这是我们采集的方波信号
0 n  A8 T) R6 H. D% {8 z
0 V% l  W; _, X! z+ s) n( n# n1 T  W! }
( a& H. c& \! X: ]% ?6 F( j
转载自:电路小白
: g! U$ q: k! U. v% d- b如有侵权请联系删除
6 z: e: r% Y2 f  r  }1 {
/ V; L- H; C0 D' x" Z

9 x7 `) e9 ~$ d9 `
: a; j3 X& g9 `, b! O7 a* w* {

8 l6 j1 u' }( U/ U1 X5 h
赞 收藏 评论0 发布时间:2024-5-25 13:31

举报

0个回答

所属标签

相似技术帖

官网相关资源

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