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

【经验分享】STM32 DAC详解

[复制链接]
STMCU小助手 发布时间:2022-2-9 21:23
既然有模拟转数字的ADC模块,那么就必然有数字转模拟的DAC模块。顾名思义,该模块仅具有ADC的补充功能。它将数字二进制值转换为模拟电压输出。DAC模块具有多种用途,包括音频生成,波形生成等。通常在大多数8位微控制器中,此模块不可用,并且通过脉宽调制(PWM)可以稍微满足其需求。部分原因是由于它们的硬件资源和运行速度相对较低。所有STM32单片机都具有PWM模块,但大容量STM32也具有DAC模块。STM32DAC模块不是很复杂,并且在工作原理方面与ADC模块相似。
2 a, P9 F+ t- [' ?4 Z1 p
01、DAC简介
从STM32F207数据手册看到,STM32F207具有两个DAC模块。
2 j# T+ ]! z6 h9 R) d* R$ [

" k6 X( j, q& W' M/ P7 |
每个DAC具有独立的通道,对应的GPIO分别为:PA4和PA5。对于GPIO的复用功能(Alternatefunctions)和附加功能(Additionalfunctions),在《STM32ADC详解》有详细讲解。
除了DAC输出的管脚,还有其他相关引脚
, Q& ]+ O. _/ [7 `. x& v

- F0 |4 }- x3 E3 V( Y
注意:使能DAC 通道x 后,相应GPIO 引脚(PA4 或PA5)将自动连接到模拟转换器输出(DAC_OUTx)。为了避免寄生电流消耗,应首先将PA4 或PA5 引脚配置为模拟模式(AIN)。
下面的简化框图显示了STM32DAC模块的主要组件。

% u! m5 W! Y/ L
+ D: ~: v& E, j& D
02、DAC转换
由框图可以看出,DAC受DORx寄存器直接控制的,但是不能直接往DORx寄存器写入数据,而是通过DHRx间接地传给DORx寄存器,实现对DAC的输出控制。
不能直接对寄存器DAC_DORx写入数据,任何输出到DAC通道x的数据都必须写入DAC_DHRx寄存器(数据实际写入DAC_DHR8Rx、DAC_DHR12Lx、DAC_DHR12Rx、DAC_DHR8RD、DAC_DHR12LD、或者DAC_DHR12RD寄存器)。
  • 如果没有选中硬件触发(寄存器DAC_CR1的TENx位置0),存入寄存器DAC_DHRx的数据会在一个APB1时钟周期后自动传至寄存器DAC_DORx;
  • 如果选中硬件触发(寄存器DAC_CR1的TENx位置1),数据传输在触发发生以后3个APB1时钟周期后完成。
    8 \* N- c/ I3 q* t
一旦数据从DAC_DHRx寄存器装入DAC_DORx寄存器,在经过时间tSETTLING之后,输出即有效,这段时间的长短依电源电压和模拟输出负载的不同会有所变化。
DAC控制寄存器(DAC_CR)
     DMAEN1:DAC通道1DMA使能(DAC channel1 DMA enable),我们不使用DMA,故设置为0
     MAMP1[3:0]:DAC通道1屏蔽/幅值选择器(DAC channel1 mask/amplitude selector)我们没有用到故这几位也设置为0
     WAVE1[1:0]:DAC通道1噪声/三角波生成使能(DAC channel1 noise/triangle wave generationenable)我们也没用到故也设置为0
     TEN1:DAC通道1触发使能(DAC channel1 trigger enable)我们不用触发,所以设置为0
     TSEL1[2:0]:DAC通道1触发选择(DAC channel1 trigger selection)注意:该位只能在TEN1=1(DAC通道1触发使能)时设置。我们TEN1设为0,所以这几位就不用设置,默认为0
     BOFF1:关闭DAC通道1输出缓存(DAC channel1 output buffer disable)我们关闭输出缓冲故设置为1
     EN1:DAC通道1使能(DAC channel1 enable)我们要使能DAC通道、故设置为1。
1 Y3 }# c, t3 `2 I, g6 i3 L
03、功能说明
STM32的DAC等效电路如下
. _& Z& E: ~& i
该电路中显示的输出缓冲器在内部3.3V电源上运行。与大多数运放在单电源(而不是+/-双电源)上运行一样,输出摆幅永远不会真正达到目标。但是,如电路所示,有两个内部开关(S1和S2)可通过寄存器控制。将它们都打开将通过两个串联的电阻(Ra和Rb)将“DACINT”信号直接连接到“DACOUT”引脚。作为参考,Ra+ Rb约为15k。
$ `2 O6 o' u7 q0 ?! I6 `
根据选择的配置模式,数据按照下文所述写入指定的寄存器:
单DAC通道x,有3种情况:
  • 8位数据右对齐:用户须将数据写入寄存器DAC_DHR8Rx[7:0]位(实际是存入寄存器DHRx[11:4]位);
  • 12位数据左对齐:用户须将数据写入寄存器DAC_DHR12Lx[15:4]位(实际是存入寄存器DHRx[11:0]位);
  • 12位数据右对齐:用户须将数据写入寄存器DAC_DHR12Rx[11:0]位(实际是存入寄存器DHRx[11:0]位)。

    ) A$ i4 o7 N3 M+ O
一般采用第三种方式:12位数据右对齐比较多。
根据对DAC_DHRyyyx寄存器的操作,经过相应的移位后,写入的数据被转存到DHRx寄存器中(DHRx是内部的数据保存寄存器x)。随后,DHRx寄存器的内容或被自动地传送到DORx寄存器,或通过软件触发或外部事件触发被传送到DORx寄存器。
双DAC通道,有3种情况:
  • 8位数据右对齐:用户须将DAC通道1数据写入寄存器DAC_DHR8RD[7:0]位(实际是存入寄存器DHR1[11:4]位),将DAC通道2数据写入寄存器DAC_DHR8RD[15:8]位(实际是存入寄存器DHR2[11:4]位);
  • 12位数据左对齐:用户须将DAC通道1数据写入寄存器DAC_DHR12LD[15:4]位(实际是存入寄存器DHR1[11:0]位),将DAC通道2数据写入寄存器DAC_DHR12LD[31:20]位(实际是存入寄存器DHR2[11:0]位);
  • 12位数据右对齐:用户须将DAC通道1数据写入寄存器DAC_DHR12RD[11:0]位(实际是存入寄存器DHR1[11:0]位),将DAC通道2数据写入寄存器DAC_DHR12RD[27:16]位(实际是存入寄存器DHR2[11:0]位)。

      d. u! l( `, c5 ~

1 @3 i7 H8 x: c' O  }/ A04、DAC输出电压
当DAC的参考电压位VREF+的时候,数字输入经过DAC被线性地转换为模拟电压输出,其范围为0到VREF+。
任一DAC通道引脚上的输出电压满足下面的关系:
DAC输出= VREF x (DOR / 4095)。
注意:此时数据格式:应该选择12位数据右对齐。
05、代码配置
DAC配置
  1. void DAC1_Config(void)1 c, @, L; D; F4 N
  2. {
    7 C8 |' `- ?: |; `3 m/ {* L
  3.   DAC_InitTypeDef  DAC_InitStructure;
    6 x, a% U7 M" z6 Q/ k
  4.   GPIO_InitTypeDef GPIO_InitStructure;- I3 Q' N+ a7 G
  5.   
    ' I1 L2 H* i8 S0 J
  6.   /* DMA1 clock and GPIOA clock enable (to be used with DAC) */
    , E  q$ s4 D! D" o# f
  7.   RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);# C* b" S8 F; C3 d. m; a! u% k
  8.   
    5 q$ \" @# A0 p5 i7 x* C
  9.   /* DAC Periph clock enable */
    : L" y: t) P# C
  10.   RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE);
    6 E  K7 ?1 Q9 |4 i7 Q) {  I
  11.   
    ; H& I% C5 d* y# W9 F4 y& U1 s1 Q
  12.   /* DAC channel 1 & 2 (DAC_OUT1 = PA.4)(DAC_OUT2 = PA.5) configuration */
    / [! |1 p, ]) k: Q0 }  p- `5 S7 Q
  13.   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
    ) V% k# ]: Z9 I4 k- }# z! l
  14.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;2 U/ u" F* t8 x# j. k
  15.   GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;4 W" D$ R; ~9 a* G: e7 D% x
  16.   GPIO_Init(GPIOA, &GPIO_InitStructure);
    ! Z" r  [; ], x' g9 q2 O7 i' {
  17.   1 x1 g% ^5 Z; s/ d
  18.    /* DAC channel2 Configuration */. {- U  @" p. Z
  19.   DAC_InitStructure.DAC_Trigger = DAC_Trigger_None;
    / i5 c0 [9 C0 Y4 }
  20.   DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_None;( y2 Y1 I0 N1 j
  21.   DAC_InitStructure.DAC_LFSRUnmask_TriangleAmplitude = DAC_LFSRUnmask_Bit0;& {- O! E: R! `  |! w& [
  22.   DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Disable;
    $ M" g5 c! U- B. i1 O
  23.   DAC_Init(DAC_Channel_1, &DAC_InitStructure);9 |+ ~3 P+ M$ `) u2 V0 J0 R5 W+ v8 I
  24. 0 y% y& I& x2 S8 E. D% s' a9 x- H
  25.   /* Enable DAC Channel2 */
    # n& ]5 b3 S% p/ W0 w( M
  26.   DAC_Cmd(DAC_Channel_1, ENABLE);
    ( k0 s# l* N  G# x$ |6 K
  27. }
复制代码
9 U' w, Y; j6 Q* g& {* C
设置输出电压
  1. //设置通道1输出电压
    , ]$ N/ H6 U) _* ]: X
  2. //vol:0~3300,代表0~3.3V
    8 w  E8 ^% y& h0 y7 ^" A# i" X
  3. void Dac1_Set_Vol(uint16_t vol)
    7 ?8 r0 E( b% T. Y6 r. ?$ _
  4. {, n. u9 T5 h# M3 M1 b8 c8 J
  5.   double temp=vol;
    ; ?) C; B& _/ D6 q# y; I
  6.   temp/=1000;
    0 o# ~1 j) U' ]" h4 x" O3 @
  7.   temp=temp*4096/3.3;
    ! Z; i4 ]' G8 @: X! F
  8.   DAC_SetChannel1Data(DAC_Align_12b_R,temp);//12位右对齐数据格式设置DAC值! C; a3 ?# a0 u  J$ e% i( j
  9. }
复制代码

2 e' j  }( j; M1 `" H
测试用例很简单,就是反复输出1.2V和3.0V电压
  1. while (1)9 I, K( S; b* l; d" Y) x8 b) ]* k1 n
  2.   {3 i$ n4 x! U. k( x6 Z6 k$ Z) i
  3.     GPIO_SetBits(GPIOE,GPIO_Pin_4);  //熄灭LED灯* Y$ r7 Y" N2 I
  4.     Dac1_Set_Vol(1200);  |$ Z" o6 g- p" g! P
  5.     LCD_ShowString(0,0,"DAC OUT 1.2V");1 y: R* b9 N% S. n! ?
  6.     Delay(500);                      //延时500ms
    & B, F- o: }+ T4 I# D# O& F
  7.     GPIO_ResetBits(GPIOE,GPIO_Pin_4);//点亮LED灯
    # _2 B( O$ ^# ]/ j
  8.     Dac1_Set_Vol(3000);9 Q) T4 u% D/ N- a0 M3 z( W6 ]
  9.     LCD_ShowString(0,0,"DAC OUT 3.0V");
    9 V; k" Y9 b' S. c7 N0 O1 z* }# M
  10.     Delay(500);                      //延时500ms6 i6 `2 w% p, I3 U
  11.   }
复制代码
2 ]1 m. c  ^  G# Q/ [: C
下载验证
, o& o" u, G" [' I# Q. q+ S
: {+ z' I: x) Y3 Y: ~
a6794a43af583632c12727bc28837227.png
b6fca6bf1d6da39d4be750e643e30949.png
e042f894972742c7683797281a85733f.png
30e013997f8b2c15012d9ffd7c519c8c.png
f1dd10238818b89eab06440a5d2aa4c2.gif
128672eab617bb2f7c2901b13234d101.png
947dae678a261d0fecef952dbec2b5f1.png
2801c6e10b7bc11769e781b0947a1a17.png
赞 收藏 评论0 发布时间:2022-2-9 21:23

举报

0个回答

所属标签

相似技术帖

官网相关资源

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