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

STM32 DAC详解

[复制链接]
STMCU小助手 发布时间:2021-1-11 11:10
STM32 DAC详解
上篇介绍了《STM32ADC详解》,既然有模拟转数字的ADC模块,那么就必然有数字转模拟的DAC模块。顾名思义,该模块仅具有ADC的补充功能。它将数字二进制值转换为模拟电压输出。DAC模块具有多种用途,包括音频生成,波形生成等。通常在大多数8位微控制器中,此模块不可用,并且通过脉宽调制(PWM)可以稍微满足其需求。部分原因是由于它们的硬件资源和运行速度相对较低。所有STM32单片机都具有PWM模块,但大容量STM32也具有DAC模块。STM32DAC模块不是很复杂,并且在工作原理方面与ADC模块相似。
01
DAC简介
从STM32F207数据手册看到,STM32F207具有两个DAC模块。
4.3.png
每个DAC具有独立的通道,对应的GPIO分别为:PA4和PA5。对于GPIO的复用功能(Alternatefunctions)和附加功能(Additionalfunctions),在《STM32ADC详解》有详细讲解。
除了DAC输出的管脚,还有其他相关引脚
4.4.png
注意:使能DAC 通道x 后,相应GPIO 引脚(PA4 或PA5)将自动连接到模拟转换器输出(DAC_OUTx)。为了避免寄生电流消耗,应首先将PA4 或PA5 引脚配置为模拟模式(AIN)。
下面的简化框图显示了STM32DAC模块的主要组件。
4.5.png
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寄存器)。
l  如果没有选中硬件触发(寄存器DAC_CR1的TENx位置0),存入寄存器DAC_DHRx的数据会在一个APB1时钟周期后自动传至寄存器DAC_DORx;
l  如果选中硬件触发(寄存器DAC_CR1的TENx位置1),数据传输在触发发生以后3个APB1时钟周期后完成。
一旦数据从DAC_DHRx寄存器装入DAC_DORx寄存器,在经过时间tSETTLING之后,输出即有效,这段时间的长短依电源电压和模拟输出负载的不同会有所变化。
4.6.png
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 wavegenerationenable)我们也没用到故也设置为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。
03
功能说明
STM32的DAC等效电路如下
4.7.png
该电路中显示的输出缓冲器在内部3.3V电源上运行。与大多数运放在单电源(而不是+/-双电源)上运行一样,输出摆幅永远不会真正达到目标。但是,如电路所示,有两个内部开关(S1和S2)可通过寄存器控制。将它们都打开将通过两个串联的电阻(Ra和Rb)将“DACINT”信号直接连接到“DACOUT”引脚。作为参考,Ra+ Rb约为15k。
根据选择的配置模式,数据按照下文所述写入指定的寄存器:
单DAC通道x,有3种情况:
l  8位数据右对齐:用户须将数据写入寄存器DAC_DHR8Rx[7:0]位(实际是存入寄存器DHRx[11:4]位);
l  12位数据左对齐:用户须将数据写入寄存器DAC_DHR12Lx[15:4]位(实际是存入寄存器DHRx[11:0]位);
l  12位数据右对齐:用户须将数据写入寄存器DAC_DHR12Rx[11:0]位(实际是存入寄存器DHRx[11:0]位)。
一般采用第三种方式:12位数据右对齐比较多。
根据对DAC_DHRyyyx寄存器的操作,经过相应的移位后,写入的数据被转存到DHRx寄存器中(DHRx是内部的数据保存寄存器x)。随后,DHRx寄存器的内容或被自动地传送到DORx寄存器,或通过软件触发或外部事件触发被传送到DORx寄存器。
4.8.png
双DAC通道,有3种情况:
1.      8位数据右对齐:用户须将DAC通道1数据写入寄存器DAC_DHR8RD[7:0]位(实际是存入寄存器DHR1[11:4]位),将DAC通道2数据写入寄存器DAC_DHR8RD[15:8]位(实际是存入寄存器DHR2[11:4]位);
2.      12位数据左对齐:用户须将DAC通道1数据写入寄存器DAC_DHR12LD[15:4]位(实际是存入寄存器DHR1[11:0]位),将DAC通道2数据写入寄存器DAC_DHR12LD[31:20]位(实际是存入寄存器DHR2[11:0]位);
3.      12位数据右对齐:用户须将DAC通道1数据写入寄存器DAC_DHR12RD[11:0]位(实际是存入寄存器DHR1[11:0]位),将DAC通道2数据写入寄存器DAC_DHR12RD[27:16]位(实际是存入寄存器DHR2[11:0]位)。
4.9.png
04
DAC输出电压
当DAC的参考电压位VREF+的时候,数字输入经过DAC被线性地转换为模拟电压输出,其范围为0到VREF+。
任一DAC通道引脚上的输出电压满足下面的关系:
DAC输出= VREF x (DOR/ 4095)。
注意:此时数据格式:应该选择12位数据右对齐。
05
代码配置
DAC配置
# w) ~' u) @: Y+ m
  1. void DAC1_Config(void)3 q% [% R+ ]' f7 d
  2. {
    # ~0 M/ t" t0 m; s. _& N- Q3 E; L, b: ^  N
  3.   DAC_InitTypeDef DAC_InitStructure;
    . s1 Z( v6 q! _) l/ N
  4.   GPIO_InitTypeDef GPIO_InitStructure;9 |, T( R6 G  l9 F1 w

  5. * [: g, m0 \9 H2 ^
  6.   /* DMA1 clock and GPIOA clock enable (to be used with DAC)*/' P! D5 N# u6 E7 g
  7.   RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
    . G' u+ Z9 u8 W1 b

  8. * o  S8 V1 b7 R* Y& w. }; V
  9.   /* DAC Periph clock enable */
    " ^; S2 v( i0 }( [
  10. RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE);* }* t! C7 f) x: r4 A
  11.   
    5 ?) O( c3 p# P
  12.   /*DAC channel 1 & 2 (DAC_OUT1 = PA.4)(DAC_OUT2 = PA.5)configuration */
    / ~" d- {% D* h2 D4 H: @( F& l/ z
  13.   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
    ; T2 f  H. b/ @# |' l$ S
  14. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;  x' X& U2 g( W; i
  15. GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;* F! r& z4 e' g& p
  16. GPIO_Init(GPIOA, &GPIO_InitStructure);. ^' y) c( U, |9 U  P: v
  17.    /* DACchannel2 Configuration */
    , x. P! U3 p' G  P# q' D
  18. DAC_InitStructure.DAC_Trigger =DAC_Trigger_None;) k1 D. U5 ~+ ]% P  q+ Z$ o, ?( v
  19. DAC_InitStructure.DAC_WaveGeneration =DAC_WaveGeneration_None;
    " u1 k5 y2 @9 n3 [2 A
  20. DAC_InitStructure.DAC_LFSRUnmask_TriangleAmplitude =DAC_LFSRUnmask_Bit0;
    ! M# I2 O( v' _2 @7 F# Z0 D, ]
  21. DAC_InitStructure.DAC_OutputBuffer =DAC_OutputBuffer_Disable;; ]* L1 F1 C% J0 Q
  22. DAC_Init(DAC_Channel_1,&DAC_InitStructure);
    9 J; H( L( W' Y: x% R5 j1 Y, C
  23. 1 Q+ O3 |2 G0 E* b% D
  24. /* Enable DAC Channel2 */( Y: u& a' Y* N2 C$ o) T
  25. DAC_Cmd(DAC_Channel_1, ENABLE);0 T9 H0 V" P/ h) V# E
  26. }
复制代码

. E; G, d4 A1 S7 F$ Q1 j
设置输出电压
  1. //设置通道1输出电压
    ' A8 ]6 C8 c, C3 r- c3 I2 R7 E
  2. //vol:0~3300,代表0~3.3V
    : W3 D% m" C% {* y7 \4 Q/ [- D. J; G
  3. voidDac1_Set_Vol(uint16_t vol)& g/ S2 e6 g, Q- L  `
  4. {
    ' s7 V) J5 g4 V: `% d* K
  5.   double temp=vol;. z. I+ H4 w3 [4 q6 K- K% R
  6. temp/=1000;
    . @9 n) F$ B0 e# \
  7.   temp=temp*4096/3.3;
    ) f  r) I7 R1 y* M. r
  8. DAC_SetChannel1Data(DAC_Align_12b_R,temp);//12位右对齐数据格式设置DAC值3 p2 ?& e7 l3 G4 v! O) `# q3 [
  9. }
复制代码
! j2 Y0 T" |0 _# r
测试用例很简单,就是反复输出1.2V和3.0V电压
  1. while (1)( q) n7 I8 c3 I. O/ G
  2.   {; A7 k, Q% d: a0 }/ c
  3.     GPIO_SetBits(GPIOE,GPIO_Pin_4);  //熄灭LED灯
    % b5 l  [! p8 k
  4.     Dac1_Set_Vol(1200);( W: @# c; _% F1 E
  5.     LCD_ShowString(0,0,"DAC OUT 1.2V");. X( |  @6 ?  |' G: ~, W; c1 a  ]
  6.     Delay(500);                      //延时500ms
    ; W( h7 Q, l4 l' @! Q- N+ o, Y- `, T
  7.     GPIO_ResetBits(GPIOE,GPIO_Pin_4);//点亮LED灯
    . i$ d4 p/ F8 ~+ q  P
  8.     Dac1_Set_Vol(3000);5 |+ \4 @* n" A5 r, e/ M
  9.     LCD_ShowString(0,0,"DAC OUT 3.0V");$ R( K" w# V& N- y3 d- b+ A* E
  10.     Delay(500);                      //延时500ms
    1 |, x# Y/ s! Y
  11. }
复制代码
下载验证
4.10.gif

8 m& y/ l% }9 i0 H# x
硬件和软件开源地址:
文章出处: 知晓编程
1 A& o1 f- q2 s) f7 M3 i# E
收藏 评论0 发布时间:2021-1-11 11:10

举报

0个回答

所属标签

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