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

【经验分享】基于STM32G4芯片的DAC应用示例

[复制链接]
STMCU小助手 发布时间:2021-12-8 22:00
有人使用STM32G431芯片做DAC应用,具体来说就是通过DMA将数据从指定内存传送给DAC数据寄存器,并由定时器触发DAC转换。他发现总是没法实现该功能。这里简单介绍下相关实现过程,并做些提醒。这里要演示的基本功能就是让DAM将内存数据周期性传输给DAC数据寄存器,最后输出一路正弦波。  q" b! Z% A# |

( Z+ M: I" S) }# B  s
8c8aec0947a9e081baa317138ac945de.png

' W: u8 p9 g7 E/ e/ d; B
$ `( F3 z/ V4 O. _* O: V6 Q: o! j2 o: _) C0 N6 Z& V0 e$ _
结合STM32G4芯片的特性,这里可以有两种实现方式。
5 Z; }9 A9 T  p, @) X# l( n" }* p8 Q$ a- [0 l! ^, l7 i
第一种,DMA的请求来自于DAC1的转换事件。第二种,DMA的请求来自于定时器事件,下面用到的是定时器的更新事件。这里就两种实现方式的配置及相关用户代码简单介绍下,以供参考。$ C& H; y5 w6 \9 L/ i2 y

) C5 F3 N/ U8 ~我们先看第一种方式,即DMA请求来自DAC转换事件,定时器3触发DAC的转换。
7 k( w/ U9 }1 |' ~' k+ J' U. h; {! b6 c
使用CubeMx进行配置,主要配置如下:5 u$ Y5 E0 z8 Q: K
d1020b7d0f8f4894eb7b709ab4cbed6d.png
; H9 M3 ^) a! k8 ?

% J  \; R& r% l& H+ Q4 q8 ^& p2 |  ?- k. j" Q& D- _+ ]
ddd67d8a4616146cdf0ec6419da513ec.png
; A: ?  P2 w: Q1 K% ^6 }
: l. c- b! z8 T% [* r
0f1f5180cdc185196607e3ef27b9e215.png

; R' M" {& `1 L$ L# L1 ~4 Y. h- C
完成配置后生成初始代码,再添加下面代码即可验证测试:; @/ ?! g/ O$ v7 a/ E  q
- F: }- |; z7 H1 `) `0 N% ~% c1 M
  1. #define   Tpai     (2*3.14159)
    ' F3 W+ d. C% n2 t
  2. 5 U9 q; n. R5 n/ D* a
  3. uint32_t  PData[200],Dac_data;
    / _% W) y7 y& I4 ^
  4.   @. q, G' T; ^0 B' L
  5. uint16_t     i;1 v1 {- z' N* L! I9 \* z
  6. * v2 z8 ], ~$ M0 [! [9 z
  7. for (i=0;i<200;i++)
    1 m" J' u, f) y. o  c+ K) J% G

  8. . x! ^9 S' X2 g: w" Q: O
  9. {undefined/ c7 M' l: W1 G/ O8 `* l' k8 O
  10. ! A# w- h/ C% N, K
  11. PData<i>=</i>
    / ?: D* e) x* O1 A  ?0 Y

  12. % C. G6 J- f6 r2 C5 _* x# Y
  13. (uint32_t ) (2000*(sin((Tpai/200)*i))+2000);/ {2 ~: s, ?, s/ x' S4 E

  14. - d0 d1 G7 j! w" d( E
  15. } //prepare data for DAC
    8 q+ ?$ h* ~' T" I4 j) a+ w/ _7 d
  16. 5 B6 f5 w9 G% U3 A* \: J
  17. HAL_DAC_Start_DMA(&hdac1,DAC_CHANNEL_1,(uint32_t*)&PData[0],  200,DAC_ALIGN_12B_R);2 w; d5 z- f2 @' S$ ]& D9 j& o
  18. , U6 @3 a9 d( ]
  19. __HAL_TIM_ENABLE(&htim3);
复制代码
8 K6 `2 F* @$ [$ n6 H- d: f
( F+ c  J- `. p; t
( P7 ^8 @& ~- L3 |
上面配置的DMA传输方向是从内存到外设,目的和源的访问宽度都是32位WORD. 当然也可以是内存访问宽度为16位的半字,外设访问宽度为32位字。即DMA的配置像下面这样也是可以的。
" F! u0 A/ ^0 o  v
6 z/ |' `) i' D, y8 s
d1a3b9537ab66535982e8b0cb86d3bbc.png

- M* P, m( E, a, S( I  `- Y# y! U" B) }; E8 ?$ B+ c
其它配置不动,代码稍微改动和整理下即可。参见下面代码:
4 T. _" K, r1 i0 V- X
" d4 h7 H: A' a+ @. K' b2 V
  1. Uint16_t  PData[200],Dac_data;
    6 O3 j' ]6 @/ q/ k# C

  2. ; @) K" ?3 e; Z+ A5 U1 h) h( S
  3. #define   Tpai (2*3.14159)
    8 Q* w- `0 {- [% q7 A
  4. ( z& Y9 x$ m( Q' V, P; r
  5. uint16_t     i;7 g3 |+ _( M' l  e( D

  6. 7 l7 ?; v0 h, \. V9 c2 e
  7. for (i=0;i<200;i++)
    # L. M2 }- `4 i$ l
  8. 2 s- O+ n. G, n; ~8 F: Y7 \
  9. {undefined
      U6 }7 M6 [9 P5 q, [1 ^
  10.   p3 y4 \' q7 u4 [! o
  11. PData=& r8 s. [) P( C; ]9 B5 V. r0 I* p/ Y
  12. & B, J7 z2 B9 {# a" M0 }
  13. (uint16_t )(2000*(sin((Tpai/200)*i))+2000);1 o2 ~& _1 C; X6 M/ M6 m5 v5 a

  14. * n" Y  u- z7 i0 ?5 X
  15. } //prepare data for DAC2 \( f1 `/ }9 Y) c2 H

  16. " f/ A" X* I0 E2 R$ x' a
  17. SET_BIT(hdac1.Instance->CR,DAC_CR_DMAEN1);
    1 I# n+ x0 L3 G" l; K

  18. 0 G# U3 X8 ]; X& y! z% \- ]: e

  19. * M9 k0 b( Y" u0 ]; {( l

  20. . w8 k& m# i, x
  21. HAL_DAC_Start(&hdac1,DAC_CHANNEL_1 );
    * Q+ {6 G0 G+ K; K6 S  [

  22. + b2 ~. D) {: W# y' U* h! h8 R
  23. HAL_Delay(2);
    4 C  A4 O5 x. |

  24. ' L6 U2 n6 `2 w/ }& ?7 o. n

  25. 0 U. S" p0 j1 G. u

  26. ' A, w* [) O# a- m
  27. HAL_DMA_Start_IT(&hdma_dac1_ch1,(uint32_t)&PData[0],(uint32_t)&DAC1->DHR12R1, 200);
    0 \. F$ u* K+ c* b* [9 }) ?8 }
  28.   t4 E" G# o! N" u6 Y
  29. : K' s. n8 a4 L, H6 r8 J6 N4 G
  30. 9 H: }) L) W$ W& G" F
  31. __HAL_TIM_ENABLE(&htim3);
复制代码
8 T' s* T7 `# j" ~

, K6 s9 l  |! Y4 U
6 ?8 X3 J7 K3 e0 g, e" H
9 ~1 \! u; {/ C; k" q# l8 q  b+ f: J第一种方式就介绍到这里,再来看看第二种实现方式,即TIMER更新事件作为DMA请求源,同时作为DAC转换触发源。3 x3 R- ^& @$ _( p0 N. n& x  U
$ u3 X/ m. _! I' E. m
基于CubeMx配置,主要调整下DMA配置,其它配置基本不动。
0 u1 O6 m* h& O6 f3 {+ C5 s1 m
" L- K/ J6 B# D! @  {
+ J; a. I" C* k1 S" H) y( g$ T1 [# o

/ g' K  n' U/ ]1 }' p) X
' V9 j& \0 J* J9 b5 z+ U1 Y4 e0 _  w主要是DMA请求事件变了,其它配置跟第一种模式基本一样。  s2 g) b, k! ]. _2 f) o5 T8 c6 X
, l/ Z1 w3 e; t8 x  }) U6 L4 K# x% v
配置完成后生成初始化代码,再添加下面用户代码:" f5 p" R8 ]2 {) F( [) G
2 \+ `4 h* P+ m% _/ E4 T# C
  1. #define   Tpai     (2*3.14159)+ v4 r, v' B# Y

  2. + V1 K$ D8 m* N7 H3 U1 ^
  3. uint16_t PData[200], Dac_data;
    " g, I, |& E, v( m
  4. / @0 q5 Y/ p3 ]4 N" q. X6 K
  5. uint16_t     i;- o( m6 P& i0 L& H1 O
  6. ' u: k1 O  b! b2 [
  7. for (i=0;i<200;i++). x8 x" f. {; \3 x
  8. 0 R0 D! W8 z! A2 g+ Z4 f
  9. {undefined
    4 l  h' Z9 U# ]4 g

  10. ' c$ }0 s: R' p, D0 _, z
  11. PData=( ]( k2 E: v. u0 w
  12. + x# |* I" Y% H
  13. (uint16_t )(2000*(sin((Tpai/200)*i))+2000);
    1 v  Z6 Q, f) v4 k( r
  14. $ d: H% }' Y: M* E$ v
  15. }" e7 V8 _6 \8 ~( d+ X
  16. ( r" x# b+ E4 m- a& i
  17. HAL_DAC_Start(&hdac1,DAC_CHANNEL_1 );
    # r; S9 S0 }- W  N5 X
  18. , p) S% e, _1 n7 x! |
  19. HAL_Delay(3);! [# T9 b6 P# m0 f  m

  20. ( g" \" }+ h0 s2 c7 U8 c' f2 r
  21. : ?/ ?( c' `3 _* I
  22. ' ?+ D) k/ I( j; ~/ S. T% O- J; ^
  23. HAL_DMA_Start(&hdma_tim3_up,(uint32_t)&PData[0],(uint32_t)&DAC1->DHR12R1, 200);
    + j7 R4 @3 @! l4 P, v) I; X- O
  24. " b& x1 @7 y- |5 O

  25. 8 x8 j: Q/ O# e8 {6 r* H2 i$ S
  26. " x3 C! k( W; n6 h2 o6 t
  27. __HAL_TIM_ENABLE_DMA(&htim3, TIM_DMA_UPDATE);
    * @. B5 X7 _: y; q0 N7 `: w. V4 ~
  28. 2 L' N% ?4 \& z  T& A/ z
  29. __HAL_TIM_ENABLE(&htim3);
复制代码
* y; v  D7 @5 B' D- T
  C3 A% A' R( z8 w7 ~5 Y
这里要提醒一点,G4系列的DAC1的数据保持寄存器可以一次放2个通道的数据,在使用DMA传输时,即使只用到1个通道,DMA对它的访问也要遵循WORD对齐,不然你可能会遇到麻烦。& R2 F! v/ P6 I6 W* L: j/ l1 M
8 S( @) d7 o2 @/ A9 v
如果说,我们不使用DMA做数据传输,只是手动给DAC喂数据,那如何实现上述效果呢?这时我们可以使用软件触发DAC的传输,手动给DAC的数据保持寄存器赋值,参考配置及实现代码如下:
" D7 ~" _4 G0 {( S" V% x# x; W9 Q% ?' _) z5 Z' M0 z% ]
81958bbf0c7325cd86a0ecbf4dc138ef.png

8 P6 N" e  t3 x* w1 C
" c2 o! z" G/ Z8 {) W
; N4 D1 \# K2 G  c, _  T相关用户代码如下: 8 _$ U' y2 h3 o0 Q( h0 n) L

0 _. `# ]( c* s' v! `) \1 w- b
  1. #define   Tpai (2*3.14159): Y1 v6 |$ L: M0 M. N) a! X
  2. . ?2 z) m. [* N: `
  3. uint16_t PData[200],Dac_data;' J. t" @+ V4 X1 a0 f
  4. , p0 _% p# Q1 C& g# N
  5. uint16_t     i;" M+ E. ]2 B4 c5 S9 e$ i& c

  6. ) z+ O" ^1 D4 x# i! U9 D
  7. for (i=0;i<200;i++)/ x% O0 x7 g8 z& h: F

  8. / x3 K5 b! N6 K) I: [  v/ K3 i
  9. {undefined
    8 R# m& |2 U- v% F& C3 l7 v/ i

  10. * G: u  w/ _: l& R* T
  11. PData<span style="font-style: italic;"><span style="font-style: normal;">=
    , G+ V7 C5 b% ]# i1 T
  12. ( i/ X% p! h  ^& i
  13. (uint16_t)(2000*(sin((Tpai/200)*i))+2000);! r0 P$ J5 M' ~; L$ `+ H9 t& k( g1 r

  14. 6 r! r4 N! |- f! ?# S) A% H
  15. }* M' O' j0 U8 a" x' c- \. E
  16. $ x; F3 B4 t% _. ?! m( x2 o4 A+ o; [/ M
  17. HAL_DAC_Start(&hdac1,DAC_CHANNEL_1 );+ P* v3 C2 [' q# V( q

  18. 8 Q) Y0 `7 X$ l. d0 H% r9 I! }3 a( h1 X
  19.    HAL_Delay(3);
    / j; s9 v' j# [4 |9 `( d  {3 t2 O4 H

  20. ! X8 Z( c- l2 }" o. p8 b
  21. 9 k$ |7 t9 q# w& @9 v
  22. , X& J4 s! p4 {- V( E+ ^% W+ K6 p
  23. while(1)* u* V8 J4 L& m( ^9 t9 l
  24. - P8 j& [  H" U9 k1 U* o
  25. {undefined$ I. }6 ]7 R# O7 e3 y* v, K! \
  26. : M# ~5 c% k! v7 B" c* s0 o( j* b$ P, x5 m
  27. for(i=0;i<200;i++)
    # H6 A4 ^- m' |" k5 P' h
  28. ; N% I6 k  d5 L( I) t$ B
  29. {undefined
    % ^" v; P$ A' {# D. O4 ^, v

  30. 9 K. i& Z' z3 ~+ E" P" D- r* l
  31. DAC1->DHR12R1= PData</span><span style="font-style: normal;">;
    1 L; U- v- q- x! G" x
  32.   @) \% m$ Z: X
  33. SET_BIT(hdac1.Instance->SWTRIGR,DAC_SWTRIGR_SWTRIG1);- ?2 E3 f  M6 I, d

  34. & O  m% u5 p  u; T1 m
  35.       HAL_Delay(5);) c, N, h; k& T+ u# h1 u
  36. 1 \! Y- \& M9 f" k- g( j& R8 @
  37. ( k- s" T6 H9 c# \
  38. ! |; V* v  ^+ O' T# u! p' Y9 l3 U
  39. Dac_data = DAC1->DOR1;//for debug! z5 A+ x) m. \
  40. " d7 P- }  Q. z" O7 s; m

  41. : I* }$ ]6 n0 h9 D/ a7 U8 u% l
  42. 4 E/ b. V) ~8 c3 R! t9 x: F/ v
  43. }
    / M8 @$ u9 z9 d
  44. 3 _  V- L7 K' u1 A: e
  45. }
    . E# I8 y  e2 j7 S% T6 M: j
  46. </span></span>
复制代码

: Z# R% D6 g) p总之,不论使用哪种方式,都可以实现我们所期望的结果,即输出如下正弦波。' g0 i# V6 T' J# n5 U/ p0 G

& V. T9 ^* Y" b3 u: K( `2 s
692bd68b1c31d5aa2a4b73541244f56e.png
! @1 R' T" O; g* G
. b" H8 B/ P5 [, @: c' R' L5 q
好,关于STM32G4的DAC应用就简单介绍到这里,STM32G4系列的模拟外设丰富而强大,此处算是抛砖引玉。这里做些分享也是为了让其他有需要的人少走弯路,加速开发进程。【文中代码都很简短、直观,就没做注释说明了。还有个客观原因就是在微信公众号里排版也很费劲,字符不太好对齐。若有需要交流的可以后台留言。】
2 n( Q+ b4 k% k7 @; G+ F
* B, r; r5 S# G) T7 b
5 H  V& G; Z4 }* I
79bba335bff508c4f57300f0f57049de.png
收藏 评论0 发布时间:2021-12-8 22:00

举报

0个回答

所属标签

相似分享

官网相关资源

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