STM32 DAC详解

Wesley13
• 阅读 353

上一篇介绍了《STM32ADC详解》,既然有模拟转数字的ADC模块,那么就必然有数字转模拟的DAC模块。顾名思义,该模块仅具有ADC的补充功能。它将数字二进制值转换为模拟电压输出。DAC模块具有多种用途,包括音频生成,波形生成等。通常在大多数8位微控制器中,此模块不可用,并且通过脉宽调制(PWM)可以稍微满足其需求。部分原因是由于它们的硬件资源和运行速度相对较低。所有STM32单片机都具有PWM模块,但大容量STM32也具有DAC模块。STM32DAC模块不是很复杂,并且在工作原理方面与ADC模块相似。

01、DAC简介

从STM32F207数据手册看到,STM32F207具有两个DAC模块。

STM32 DAC详解

每个DAC具有独立的通道,对应的GPIO分别为:PA4和PA5。对于GPIO的复用功能(Alternatefunctions)和附加功能(Additionalfunctions),在《STM32ADC详解》有详细讲解。

除了DAC输出的管脚,还有其他相关引脚

STM32 DAC详解

注意:使能DAC 通道x 后,相应GPIO 引脚(PA4 或PA5)将自动连接到模拟转换器输出(DAC_OUTx)。为了避免寄生电流消耗,应首先将PA4 或PA5 引脚配置为模拟模式(AIN)。

下面的简化框图显示了STM32DAC模块的主要组件。

STM32 DAC详解

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寄存器)。

  1. 如果没有选中硬件触发(寄存器DAC_CR1的TENx位置0),存入寄存器DAC_DHRx的数据会在一个APB1时钟周期后自动传至寄存器DAC_DORx;

  2. 如果选中硬件触发(寄存器DAC_CR1的TENx位置1),数据传输在触发发生以后3个APB1时钟周期后完成。

一旦数据从DAC_DHRx寄存器装入DAC_DORx寄存器,在经过时间tSETTLING之后,输出即有效,这段时间的长短依电源电压和模拟输出负载的不同会有所变化。

STM32 DAC详解

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。

03、功能说明

STM32的DAC等效电路如下

STM32 DAC详解

该电路中显示的输出缓冲器在内部3.3V电源上运行。与大多数运放在单电源(而不是+/-双电源)上运行一样,输出摆幅永远不会真正达到目标。但是,如电路所示,有两个内部开关(S1和S2)可通过寄存器控制。将它们都打开将通过两个串联的电阻(Ra和Rb)将“DACINT”信号直接连接到“DACOUT”引脚。作为参考,Ra+ Rb约为15k。

根据选择的配置模式,数据按照下文所述写入指定的寄存器:

单DAC通道x,有3种情况:

  1. 8位数据右对齐:用户须将数据写入寄存器DAC_DHR8Rx[7:0]位(实际是存入寄存器DHRx[11:4]位);

  2. 12位数据左对齐:用户须将数据写入寄存器DAC_DHR12Lx[15:4]位(实际是存入寄存器DHRx[11:0]位);

  3. 12位数据右对齐:用户须将数据写入寄存器DAC_DHR12Rx[11:0]位(实际是存入寄存器DHRx[11:0]位)。

一般采用第三种方式:12位数据右对齐比较多。

根据对DAC_DHRyyyx寄存器的操作,经过相应的移位后,写入的数据被转存到DHRx寄存器中(DHRx是内部的数据保存寄存器x)。随后,DHRx寄存器的内容或被自动地传送到DORx寄存器,或通过软件触发或外部事件触发被传送到DORx寄存器。

STM32 DAC详解

双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]位)。

STM32 DAC详解

04、DAC输出电压

当DAC的参考电压位VREF+的时候,数字输入经过DAC被线性地转换为模拟电压输出,其范围为0到VREF+。

任一DAC通道引脚上的输出电压满足下面的关系:

DAC输出= VREF x (DOR / 4095)。

注意:此时数据格式:应该选择12位数据右对齐。

05、代码配置

DAC配置

void DAC1_Config(void)
{
  DAC_InitTypeDef  DAC_InitStructure;
  GPIO_InitTypeDef GPIO_InitStructure;
  
  /* DMA1 clock and GPIOA clock enable (to be used with DAC) */
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
  
  /* DAC Periph clock enable */
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE);
  
  /* DAC channel 1 & 2 (DAC_OUT1 = PA.4)(DAC_OUT2 = PA.5) configuration */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
  GPIO_Init(GPIOA, &GPIO_InitStructure);
  
   /* DAC channel2 Configuration */
  DAC_InitStructure.DAC_Trigger = DAC_Trigger_None;
  DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_None;
  DAC_InitStructure.DAC_LFSRUnmask_TriangleAmplitude = DAC_LFSRUnmask_Bit0;
  DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Disable;
  DAC_Init(DAC_Channel_1, &DAC_InitStructure);
 
  /* Enable DAC Channel2 */
  DAC_Cmd(DAC_Channel_1, ENABLE);
}

设置输出电压

//设置通道1输出电压
//vol:0~3300,代表0~3.3V
void Dac1_Set_Vol(uint16_t vol)
{
  double temp=vol;
  temp/=1000;
  temp=temp*4096/3.3;
  DAC_SetChannel1Data(DAC_Align_12b_R,temp);//12位右对齐数据格式设置DAC值
}

测试用例很简单,就是反复输出1.2V和3.0V电压

while (1)
  {
    GPIO_SetBits(GPIOE,GPIO_Pin_4);  //熄灭LED灯
    Dac1_Set_Vol(1200);
    LCD_ShowString(0,0,"DAC OUT 1.2V");
    Delay(500);                      //延时500ms
    GPIO_ResetBits(GPIOE,GPIO_Pin_4);//点亮LED灯
    Dac1_Set_Vol(3000);
    LCD_ShowString(0,0,"DAC OUT 3.0V");
    Delay(500);                      //延时500ms
  }

下载验证 

STM32 DAC详解

硬件和软件开源地址:

https://github.com/strongercjd/STM32F207VCT6

点击查看本文所在的专辑,STM32F207教程

点赞
收藏
评论区
推荐文章
blmius blmius
2年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Easter79 Easter79
2年前
swap空间的增减方法
(1)增大swap空间去激活swap交换区:swapoff v /dev/vg00/lvswap扩展交换lv:lvextend L 10G /dev/vg00/lvswap重新生成swap交换区:mkswap /dev/vg00/lvswap激活新生成的交换区:swapon v /dev/vg00/lvswap
Jacquelyn38 Jacquelyn38
2年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Wesley13 Wesley13
2年前
Java获得今日零时零分零秒的时间(Date型)
publicDatezeroTime()throwsParseException{    DatetimenewDate();    SimpleDateFormatsimpnewSimpleDateFormat("yyyyMMdd00:00:00");    SimpleDateFormatsimp2newS
Stella981 Stella981
2年前
KVM调整cpu和内存
一.修改kvm虚拟机的配置1、virsheditcentos7找到“memory”和“vcpu”标签,将<namecentos7</name<uuid2220a6d1a36a4fbb8523e078b3dfe795</uuid
Wesley13 Wesley13
2年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
2年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
2年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Wesley13 Wesley13
2年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
3个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这