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

基于STM32的TIM、DMA、DAC实例

[复制链接]
yumeii 发布时间:2019-12-26 14:17
有人想使用STM32的TIMER及DMA,通过DAC实现指定的模拟输出,实现起来似乎不太顺畅。我这里借助于STM32F334Nucleo开发板,通过TIM6触发DMA传输,让DAC输出一路正弦波【半波】,做个简单示例,仅供参考。
$ h: K' x/ L( _" j$ ^/ N7 Y) L
- g2 u4 A7 T, S* G1、基本原理:TIM6的更新事件周期性的触发DMA;DMA将预备好的内存数据写入到DAC的输出数据寄存器;以实现DAC通道1输出一路半波正弦波信号。
9 f0 `( e7 B% _, Z2 @. r* E
. w) y* g- T  l% b* f: ?. J0 Q
! [: [( R5 k0 J2 @  T* s
2、初始配置:【使用STM32CubeMx图形化工具进行配置】9 b( L- X% K1 w2 W1 U# s
9 ]8 U+ J. ^, }. R2 i

+ Q& n) B3 R' g: w- M2.1 TIM6的配置,做基本时基参数配置即可,同时开启基于TIM6更新事件的DMA传输配置【circula 模式】
0 T, r3 C6 i8 e5 L( i9 |
3 h1 ?1 g9 ^. z6 W9 l. x  R, w

! q; y) ~) F9 B8 r. g 1.png
6 |0 `2 S# a' ~/ x8 o" q& s. t" P
8 u( |+ O. R' U; n) v 2.png
* }) Q; P( `3 h6 f" w$ E- i  W+ S* y* g4 _( G
3、完成上述配置后,生成含有初始化代码的工程。
# ], b0 A1 u4 q5 ^$ y  J) ?
) H% f( U4 s* r! g* f! {4、添加用户代码。
$ D5 X/ J: L/ @& _! J4 w+ D- {/ t
, {* A. C) P( t4.1 准备用于DAC输出的数据。. `) ~; R) T$ }3 n/ b2 h* x
7 h9 F3 z3 P6 p) L

4 v. l2 T4 F$ f6 @7 v) r$ A2 c( }5 x我这里准备的数据基于如下正弦函数来做。准备好的数据放在数组 TodisplayData【】里,供DMA取用。, }+ L, d# ]- |: u
$ z  x7 g3 v; o/ t5 |/ Z; h

: I+ @& ]' H, K; i5 I4 E+ w# p 3.png " f" `5 {7 j# q) C. S  ^' ]) t

. v. Y* Y4 {4 U1 G! m* A) ]5 U

  P* n& v5 `  a" V! y& m' N#define Step      (200)
" {8 P2 @$ {& d! n  c* Z( _9 w
: t6 z" K9 B( U/ |
* X% _1 l& P" p
#define half_pai (3.141592/2)
2 N9 s0 T4 W: a- P: X" Z0 x7 ?9 ^
0 N8 Z1 Y. g! M! l' {

5 F1 p- {, W. h- c& I) O) d0 U; P#define StepAngel (half_pai/Step)
3 z0 I8 R0 u8 k0 q% H4 e/ \$ C: H: i# t  ^
+ a" F' c$ T$ G3 X1 V- t& O
#define Size_Array  (Step* 2)
0 u" A; |. Z7 F" U3 _0 o
7 |( x1 t3 A. J8 z
' S& c* T& Y5 B7 ?  S0 `" J8 b' ~7 v; X
uint16_t TodisplayData[Size_Array] = {0};7 r8 z- G0 f% v/ A

/ Z0 @9 C/ \& v8 Efor (i=0;i<Step;i++)& ]# _$ _1 a$ H% U) ^  o# M
. z* A# H3 a0 T! d/ a

2 _( E7 v. X8 I& I{2 x8 K5 |- O" D) ?& ~
0 \0 d6 Y) Y) f8 J3 w
/ c( H; b* p( R8 q
TodisplayData=(uint16_t)(4000*sinf(StepAngel*i));
- G" h0 z8 r8 Y8 B5 P7 D4 a+ N, P' s# ~
5 @. s3 N/ ?& h4 P: A3 M! t; j/ V

4 U, m8 V3 `8 z, q1 O, j- Z+ [3 \}7 \" X- H! o8 Z0 _$ v! i( J

2 ?* g( c/ X: l3 {

! M; x- \2 [3 Hfor (i=Step;i<Step*2;i++)
( @7 i; d) Z) M6 C& z( c! I1 K/ M' E$ U+ M5 |- c

. L% V3 l; D! N: c, V) u{; w; E4 d4 T4 V1 K2 m

9 x# V9 T' k5 ~/ d3 A" u# [, h

. t% u! t1 n2 P6 |TodisplayData=(uint16_t)(4000*sinf(StepAngel*(Step*2-i)));    r6 o% _" F7 a: ^' }

, m" n) _8 p" c

1 O% ?+ v3 A, W$ n7 |7 ~3 [}
* v! [( h9 [7 X7 A" g, P# O8 R8 w5 u4 M- u2 I% E
! ~' C7 V, q0 C# Z/ S! ^' Z
4.2使能TIM6的基于更新事件的DMA请求。- N5 I& c) k  Z

2 I# R) H2 x- W6 R+ Y( R
/ U+ ?7 E/ W  s" D3 P# T9 R
  __HAL_TIM_ENABLE_DMA(&htim6,TIM_DMA_UPDATE);
1 \0 |/ W/ N- |6 g1 G1 i8 d. |
4 R) d* M. I* B# h) V- h4.3使能TIM6的计数器计数。
- |6 o; L& [1 m) p% ]: B$ b( k0 w) Y9 t% N7 x- C. [

7 H% V9 o) V  b2 F* w4 u  __HAL_TIM_ENABLE(&htim6);
# Y1 [9 v/ I/ U2 W/ P1 M
2 F7 S, ^; p8 P/ L! b
5 D  Q# V: ~8 T( b7 e
4.4使能DAC通道1输出启动。$ K* z  }9 {; W7 S- E$ a8 M

' f9 V% @4 X6 B
( k7 z7 k# _7 Y7 K3 a
  HAL_DAC_Start(&hdac1,DAC_CHANNEL_1 );
( d! D( o! c! e. ~5 s( ]7 I. n+ V" d' f  E1 H
4.5完成基于TIM6更新事件的DMA传输的相关配置,并开启该传输相关中断。) P- W6 f$ s, X, `. |4 N% z+ w

+ F! W: a% H  Q$ M: X

3 ?/ Y: _. _' ]9 T6 B3 j% W: [HAL_DMA_Start_IT(&hdma_tim6_up,(uint32_t)TodisplayData, (uint32_t)&DAC1->DHR12R1 , Step*2-1);# l+ s/ ?: V4 x" ^1 ]

# p$ c9 K% M/ S: ?& m' b5、验证结果。
& W' X+ B8 }' {3 C1 s; l2 ?7 |8 C5 P! j

' b9 P& {$ L- g+ v% y我们可以通过示波器看到DAC通道1输出周期性的波形。我这里是借助MDK IDE自带的逻辑分析仪看到的结果,可以参考。如下图:
: Y9 D/ l3 H  Y5 G
& Y2 v1 X8 a& `0 n" O

" x3 C& P+ O! l/ Q' y( O2 r 4.png ; Y% G7 _( l3 g1 M% N* c

0 q6 W5 R8 t; S7 n* Q4 ^
. J+ i: X7 C, ?9 y( [
OK,到此也实现了预期的结果,其实整个过程也比较简单。3 G' a7 S+ H* a; W

* U- Q8 m( Y1 y( t* d' H最后,稍微提醒两点:' N3 z- P7 L( h  M( ~% S3 U( [

, d3 j; v" t; H5 H7 E# R" b
1 y. l# y4 F# |4 a* H2 m# ]
1、对于DAC输出数据寄存器多说几句,以12位为例。
7 p: r" I+ p, R9 h+ `3 v+ I5 |. y- y

3 ?& @' W9 |$ V- i3 I我们要写入的DAC数据输出寄存器是DAC_DHR12Rx或DAC_DHR12Lx,即数据保持寄存器,具体使用哪个看你选择的是左对齐还是右对齐数据格式。而真正体现在输出端所对应的输出数据寄存器是DORx寄存器,该寄存器是只读的,即不能被写入的。DAC_DHR寄存器的内容被加载到DOR寄存器,可能是自动完成,也可能需依靠触发事件激发完成。具体跟我们的配置有关。我们读取DAC通道实际输出的数据时应以DORx寄存器为准。" [+ ~( V" i) ]) a4 s

8 T4 \. `2 Z0 O. _/ @7 `2、关于DMA配置有个地方也提醒下。用cubeMx配置时选择的内存数据宽度【BYTE/HALF WORD/WORD]注意要跟你实际定义内存数组的数据类型一致。不要DMA配置时MEMORY宽度选择WORD,而在定义内存数组数据类型时使用HALF WORD(uint16)类型。这个地方很容易出错,还很隐蔽。特作提醒。
$ ~7 v& a; b! W' z( H9 l
6 p# }* o- o8 }; r
赞 收藏 评论0 发布时间:2019-12-26 14:17

举报

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