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

【经验分享】STM32 DAC详解

[复制链接]
STMCU小助手 发布时间:2022-4-17 21:24
既然有模拟转数字的ADC模块,那么就必然有数字转模拟的DAC模块。顾名思义,该模块仅具有ADC的补充功能。它将数字二进制值转换为模拟电压输出。DAC模块具有多种用途,包括音频生成,波形生成等。通常在大多数8位微控制器中,此模块不可用,并且通过脉宽调制(PWM)可以稍微满足其需求。部分原因是由于它们的硬件资源和运行速度相对较低。所有STM32单片机都具有PWM模块,但大容量STM32也具有DAC模块。STM32DAC模块不是很复杂,并且在工作原理方面与ADC模块相似。$ R5 W- W9 `  d- J9 o6 ?# l

$ w) `4 V. {" p6 ?4 ?9 U: F+ f01、DAC简介4 K& {# F9 q, c- F1 M, P+ w$ U9 G" K; }
从STM32F207数据手册看到,STM32F207具有两个DAC模块。
& g% R" Q+ i: F! k  D8 R: G' i& g- Y" V( s# C5 k% y" [
2801c6e10b7bc11769e781b0947a1a17.png
$ ^: p3 b8 H# b9 f: s: e4 V& F. K5 r5 m, p1 Q
每个DAC具有独立的通道,对应的GPIO分别为:PA4和PA5。对于GPIO的复用功能(Alternatefunctions)和附加功能(Additionalfunctions)。+ D" t, l& p2 s7 j! Y7 r
+ a. v8 K2 o! z, B' {0 g' \2 Y3 V1 }
除了DAC输出的管脚,还有其他相关引脚
2 p; n, @7 X* @6 n8 g
2 K6 L8 y& i" ~  T, H 128672eab617bb2f7c2901b13234d101.png 3 `9 ]+ v( r* q
: V& ]$ g. H1 @' U- s
注意:使能DAC 通道x 后,相应GPIO 引脚(PA4 或PA5)将自动连接到模拟转换器输出(DAC_OUTx)。为了避免寄生电流消耗,应首先将PA4 或PA5 引脚配置为模拟模式(AIN)。* g9 R6 E" n7 a  q( e( I! x

. u& W+ E9 t( N- R+ @* L$ \下面的简化框图显示了STM32DAC模块的主要组件。
) y& k, V% Q) W/ G3 @
3 A1 x) O$ a) k( d 947dae678a261d0fecef952dbec2b5f1.png
, @0 P$ u9 e- Y6 C1 g4 Y8 s, T; ~/ @
# g5 x/ n9 z) M9 d) L02、DAC转换
8 e6 U5 y! d3 J! C: f% ~. {由框图可以看出,DAC受DORx寄存器直接控制的,但是不能直接往DORx寄存器写入数据,而是通过DHRx间接地传给DORx寄存器,实现对DAC的输出控制。: P8 K5 ~" J7 `# l
/ Q5 z- }. F! ]1 Q9 Z# _, i
不能直接对寄存器DAC_DORx写入数据,任何输出到DAC通道x的数据都必须写入DAC_DHRx寄存器(数据实际写入DAC_DHR8Rx、DAC_DHR12Lx、DAC_DHR12Rx、DAC_DHR8RD、DAC_DHR12LD、或者DAC_DHR12RD寄存器)。
" O% z5 q* k7 J- |- P: b, {! @
9 R+ `3 o7 m5 S! d+ w( i: ]1.如果没有选中硬件触发(寄存器DAC_CR1的TENx位置0),存入寄存器DAC_DHRx的数据会在一个APB1时钟周期后自动传至寄存器DAC_DORx;# ^6 ]3 ^" p# @8 b

' U6 [. S8 h2 t3 K! q0 U1 f3 x, o4 z2.如果选中硬件触发(寄存器DAC_CR1的TENx位置1),数据传输在触发发生以后3个APB1时钟周期后完成。$ N& B' x, C. ~' R

9 l* A# D5 A8 e一旦数据从DAC_DHRx寄存器装入DAC_DORx寄存器,在经过时间tSETTLING之后,输出即有效,这段时间的长短依电源电压和模拟输出负载的不同会有所变化。
3 Q' K6 ^0 F1 G* c% J$ D
; Y6 M5 e9 j- |' k, I/ T e042f894972742c7683797281a85733f.png
4 m& f# D3 p2 P+ F; I& B/ Y" R
- n; i1 S2 }+ F/ J% S5 R5 RDAC控制寄存器(DAC_CR)$ ?+ K" f6 l* N7 }; d/ ?
/ J- V( ~* f( v+ a6 \; P2 }
     DMAEN1:DAC通道1DMA使能(DAC channel1 DMA enable),我们不使用DMA,故设置为05 q, b0 ~1 T+ t) Y; X+ ]4 L
9 j; i5 z$ l+ e3 C* }. `1 F6 f: V9 F
     MAMP1[3:0]:DAC通道1屏蔽/幅值选择器(DAC channel1 mask/amplitude selector)我们没有用到故这几位也设置为0: Y; ^' ]1 r* u

6 m7 t4 R& p  i) D3 G0 A2 W" w     WAVE1[1:0]:DAC通道1噪声/三角波生成使能(DAC channel1 noise/triangle wave generationenable)我们也没用到故也设置为01 u/ Y0 q- y! Y+ a1 o1 v5 _2 k; k

* \1 ^8 K8 H6 e8 D, i     TEN1:DAC通道1触发使能(DAC channel1 trigger enable)我们不用触发,所以设置为0
9 h1 ^( S/ @% d, f3 q0 r+ f8 r1 s5 e
     TSEL1[2:0]:DAC通道1触发选择(DAC channel1 trigger selection)注意:该位只能在TEN1=1(DAC通道1触发使能)时设置。我们TEN1设为0,所以这几位就不用设置,默认为0+ m0 l/ i4 Z& Z5 b# n9 F
, R6 x9 a5 d8 E, T+ O
     BOFF1:关闭DAC通道1输出缓存(DAC channel1 output buffer disable)我们关闭输出缓冲故设置为1
% m6 u  M3 b; X8 o4 Z$ N
: c! `9 P2 G/ b+ Y" P     EN1:DAC通道1使能(DAC channel1 enable)我们要使能DAC通道、故设置为1。% o2 K1 g- N+ c9 z! y, n7 E1 |; i

; W+ L+ j& T3 ?& j1 Q5 |03、功能说明- c4 U$ i  D: R% ^3 H: w# s) r
STM32的DAC等效电路如下
! }; _) H- A  W- ?) w. G& o  ~8 u. a+ d7 L# i8 B
30e013997f8b2c15012d9ffd7c519c8c.png
& w+ s- R  ?) [; V3 B
/ k/ M# `. Z. ^7 N. y& h, F, w该电路中显示的输出缓冲器在内部3.3V电源上运行。与大多数运放在单电源(而不是+/-双电源)上运行一样,输出摆幅永远不会真正达到目标。但是,如电路所示,有两个内部开关(S1和S2)可通过寄存器控制。将它们都打开将通过两个串联的电阻(Ra和Rb)将“DACINT”信号直接连接到“DACOUT”引脚。作为参考,Ra+ Rb约为15k。
, b5 m* Z* V; ?$ s; a3 L' Z0 r9 M: Q
% ]# g" O8 X8 }% g/ I根据选择的配置模式,数据按照下文所述写入指定的寄存器:
  i0 Z. S5 ]; {" @; ^% G1 |, `; F& C! B
单DAC通道x,有3种情况:. n/ K8 E# d2 Q6 q/ S+ D% M/ b% X
0 ~1 Z$ ~0 ^* [2 _
1.8位数据右对齐:用户须将数据写入寄存器DAC_DHR8Rx[7:0]位(实际是存入寄存器DHRx[11:4]位);1 n/ Z3 o# x* }8 \' H
# a) ?% V+ m2 c+ ]$ a
2.12位数据左对齐:用户须将数据写入寄存器DAC_DHR12Lx[15:4]位(实际是存入寄存器DHRx[11:0]位);' Y0 A7 P! G8 E3 J6 p7 X

2 p( r& T6 |8 o8 I3.12位数据右对齐:用户须将数据写入寄存器DAC_DHR12Rx[11:0]位(实际是存入寄存器DHRx[11:0]位)。  b% h% l% h" h: v& c$ h) b- O6 M

" Y$ u9 |) O8 D一般采用第三种方式:12位数据右对齐比较多。) C2 l* H6 \* v5 `$ A" [  V& U

+ [5 C' Y# h/ K' O: N% d! `根据对DAC_DHRyyyx寄存器的操作,经过相应的移位后,写入的数据被转存到DHRx寄存器中(DHRx是内部的数据保存寄存器x)。随后,DHRx寄存器的内容或被自动地传送到DORx寄存器,或通过软件触发或外部事件触发被传送到DORx寄存器。& n+ Q, O0 s8 g8 S- U0 J
# b" T! ]1 _" T; Y  O6 t' h1 I
b6fca6bf1d6da39d4be750e643e30949.png
, m* z% g* u% ]
8 f! K2 [0 Y: @; p; |: s3 u+ W双DAC通道,有3种情况:" {$ H" s0 Z4 r' J; \; C2 t% x/ e# {

* G$ H# }/ q9 p$ H& j1.8位数据右对齐:用户须将DAC通道1数据写入寄存器DAC_DHR8RD[7:0]位(实际是存入寄存器DHR1[11:4]位),将DAC通道2数据写入寄存器DAC_DHR8RD[15:8]位(实际是存入寄存器DHR2[11:4]位);
, ?+ G5 e5 D+ B8 u0 w8 X
/ n- x$ `# q. v6 U9 D  d. L2.12位数据左对齐:用户须将DAC通道1数据写入寄存器DAC_DHR12LD[15:4]位(实际是存入寄存器DHR1[11:0]位),将DAC通道2数据写入寄存器DAC_DHR12LD[31:20]位(实际是存入寄存器DHR2[11:0]位);' l. }8 V0 N' o7 a/ W: ^# l

* e# o! S. i' w0 ]3.12位数据右对齐:用户须将DAC通道1数据写入寄存器DAC_DHR12RD[11:0]位(实际是存入寄存器DHR1[11:0]位),将DAC通道2数据写入寄存器DAC_DHR12RD[27:16]位(实际是存入寄存器DHR2[11:0]位)。+ h. s4 h1 M' r9 t( n; B0 d
; U6 F/ }6 O* q- K6 u
a6794a43af583632c12727bc28837227.png : u  A6 k* `# j2 Z. v( G2 M! J6 s

/ n% b* A7 T/ B% U; B, O2 v* y  S04、DAC输出电压
5 {0 Y; |: F* U; m" I" @! m' }当DAC的参考电压位VREF+的时候,数字输入经过DAC被线性地转换为模拟电压输出,其范围为0到VREF+。
$ s+ I5 X+ M) e& ?' C
1 Q& S2 j8 {3 N2 Z2 \3 J任一DAC通道引脚上的输出电压满足下面的关系:
. U6 ?/ O  n2 N5 F$ o% ~4 J; ]4 {9 H; ]$ c- H7 v
DAC输出= VREF x (DOR / 4095)。
3 G6 l; v! c% I# x% z5 N/ D  L
2 K0 P6 R9 U  y8 B* A注意:此时数据格式:应该选择12位数据右对齐。; p3 w7 z. _5 {0 {

/ J4 m" @4 t7 M  b! I7 [0 d05、代码配置
9 `: X2 w7 i2 G. x; ?$ L9 vDAC配置
! _) g! C) H% `0 p- r' ^/ n5 u, ~. S  B0 a9 o
  1. void DAC1_Config(void)% U) M5 i% d7 ?, L0 F" |
  2. {' d, A0 G! t+ D) I1 v1 [* l9 b0 H
  3.   DAC_InitTypeDef  DAC_InitStructure;
    1 S' F/ T/ T+ |2 ?9 `( _) ]
  4.   GPIO_InitTypeDef GPIO_InitStructure;: m1 Q* F9 s7 n

  5. ) P6 C3 V, k" i
  6.   /* DMA1 clock and GPIOA clock enable (to be used with DAC) */- ?2 n2 _4 ~* e' S  \: `
  7.   RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);! m6 p; _' k" K% X
  8. ! A4 a4 p$ p3 f. }/ D
  9.   /* DAC Periph clock enable */
    / B* D0 s6 Q0 {4 v9 |
  10.   RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE);5 v" U1 z; T' ?! ]  z# ?
  11. $ [! h' O% \, E# @* f$ U8 f) ^
  12.   /* DAC channel 1 & 2 (DAC_OUT1 = PA.4)(DAC_OUT2 = PA.5) configuration */% y$ p2 ^  @! {% }) x; v
  13.   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;3 K" G; m8 D* a5 |5 F
  14.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
    & U; O. P9 }$ K# d3 w) d
  15.   GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;; g+ ^% s7 I& [0 g) E' p. f+ M
  16.   GPIO_Init(GPIOA, &GPIO_InitStructure);
    * l+ [, E1 m7 }
  17. , g8 ]: j: @. K5 s7 z- e
  18.    /* DAC channel2 Configuration */
    * M3 K) u. W+ Y( Z4 S& Z) p; L
  19.   DAC_InitStructure.DAC_Trigger = DAC_Trigger_None;0 v+ Q5 K, L$ N2 _
  20.   DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_None;+ E3 I5 J; }0 W- @, y
  21.   DAC_InitStructure.DAC_LFSRUnmask_TriangleAmplitude = DAC_LFSRUnmask_Bit0;
    9 M$ ~! T! N" U2 w' l, K
  22.   DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Disable;% |+ v& K( a& B. J6 v/ Z1 z
  23.   DAC_Init(DAC_Channel_1, &DAC_InitStructure);
    . ?1 t/ W3 |/ Q7 `' Z2 a

  24. 1 M1 Z+ y6 W. ], e; n' m2 {& e
  25.   /* Enable DAC Channel2 */
    % s8 T6 i  P* Z0 U
  26.   DAC_Cmd(DAC_Channel_1, ENABLE);, \; j+ p9 U5 L' x
  27. }
复制代码
- Q! T& L! o- W, j/ i& Y! s$ }6 Q
设置输出电压0 M4 v% A% Y# \! n- x" K
1 W7 f& J3 e8 ?- r
  1. //设置通道1输出电压7 j5 V% {/ F8 k2 l& ~0 M2 \
  2. //vol:0~3300,代表0~3.3V
    6 G' Q6 X  y; K# S! }
  3. void Dac1_Set_Vol(uint16_t vol)
    2 `! i+ v) X8 ~
  4. {
    & L7 J" J) N& d& H  k
  5.   double temp=vol;
    0 V/ T) U. A/ e) F+ G9 f) r$ q
  6.   temp/=1000;
    + M# @" P/ g8 t( E9 ^1 z4 x7 m. ~! C, i  m. E
  7.   temp=temp*4096/3.3;
    9 z8 W% r% N' M+ T. H* F
  8.   DAC_SetChannel1Data(DAC_Align_12b_R,temp);//12位右对齐数据格式设置DAC值8 n+ b9 G- E  E* g) {3 [# N
  9. }
复制代码
& ]$ ~5 B2 v7 A
测试用例很简单,就是反复输出1.2V和3.0V电压
* Y( J1 w8 t& T1 M- i
0 i3 \" W1 B: u6 N3 K) P( }, v
  1. while (1)
      y( r) ~3 c( |& \
  2.   {
    $ F1 F* k& d4 E  O
  3.     GPIO_SetBits(GPIOE,GPIO_Pin_4);  //熄灭LED灯
    & N2 i# A7 T% E" ]8 O6 O
  4.     Dac1_Set_Vol(1200);0 H# t1 g. P8 a1 |0 Z/ f
  5.     LCD_ShowString(0,0,"DAC OUT 1.2V");
    " R! Z9 h7 T/ a0 V0 P4 q+ ]
  6.     Delay(500);                      //延时500ms: u- L: j# E- L, y/ W7 c' g
  7.     GPIO_ResetBits(GPIOE,GPIO_Pin_4);//点亮LED灯
    - o# @2 O. ^# R5 G. t, u. i. D
  8.     Dac1_Set_Vol(3000);7 D% _6 x1 L9 X5 X4 Q# t4 y
  9.     LCD_ShowString(0,0,"DAC OUT 3.0V");& Z& x! ^, p4 W( J- M6 C0 T
  10.     Delay(500);                      //延时500ms* J7 ~/ |0 r; N, E2 L
  11.   }
复制代码

/ v6 Y; v0 _8 l  R. s6 S7 O下载验证/ I$ h* [0 g8 J- V8 J# ?9 {

1 V8 |3 |' ~  N& \2 P f1dd10238818b89eab06440a5d2aa4c2.gif & h: z  O3 z3 e1 @& z

6 E2 a4 Q1 ~) }4 [! _/ u. T$ C6 r/ `" d; Y9 Q
, J4 h, G: F0 J7 n! q
, `4 J" Q3 y% v9 I
收藏 评论0 发布时间:2022-4-17 21:24

举报

0个回答

所属标签

相似分享

官网相关资源

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