【stm32f407】DAC实验

发布者:chaxue1987最新更新时间:2019-02-12 来源: eefocus关键字:stm32f407  DAC实验 手机看文章 扫描二维码
随时随地手机看文章

描述


STM32F4的DAC模块(数字/模拟转换模块)是12位数字输入,电压输出型的DAC。DAC可以配置为8位或12位模式,也可以与DMA控制器配合使用。DAC工作在12位模式时,数据可以设置成左对齐或右对齐。DAC模块有2个输出通道,每个通道都有单独的转换器。在双DAC模式下,2个通道可以独立地进行转换,也可以同时进行转换并同步地更新2个通道的输出。DAC可以通过引脚输入参考电压Vref+(通ADC共用)以获得更精确的转换结果。


STM32F4的DAC模块主要特点有:


① 2个DAC转换器:每个转换器对应1个输出通道


② 8位或者12位单调输出


③ 12位模式下数据左对齐或者右对齐


④ 同步更新功能


⑤ 噪声波形生成


⑥ 三角波形生成


⑦ 双DAC通道同时或者分别转换


⑧ 每个通道都有DMA功能


单个DAC通道的框图如图所示:



图中VDDA和VSSA为DAC模块模拟部分的供电,而Vref+则是DAC模块的参考电压。DAC_OUTx就是DAC的输出通道了(对应PA4或者PA5引脚)。


从图可以看出,DAC输出是受DORx寄存器直接控制的,但是我们不能直接往DORx寄存器写入数据,而是通过DHRx间接的传给DORx寄存器,实现对DAC输出的控制。前面我们提到,STM32F4的DAC支持8/12位模式,8位模式的时候是固定的右对齐的,而12位模式又可以设置左对齐/右对齐。单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]


位 )。


我们本章使用的就是单DAC通道1,采用12位右对齐格式,所以采用第③种情况。


如果没有选中硬件触发(寄存器DAC_CR1的TENx位置’0’),存入寄存器DAC_DHRx的数据会在一个APB1时钟周期后自动传至寄存器DAC_DORx。如果选中硬件触发(寄存器DAC_CR1的TENx位置’1’),数据传输在触发发生以后3个APB1时钟周期后完成。 一旦数据从DAC_DHRx寄存器装入DAC_DORx寄存器,在经过时间 tsetting之后,输出即有效,这段时间的长短依电源电压和模拟输出负载的不同会有所变化。我们可以从STM32F407ZGT6的数据手册查到 的典型值为3us,最大是6us。所以DAC的转换速度最快是333K左右。本章我们将不使用硬件触发(TEN=0),其转换的时间框图如图所示



当DAC的参考电压为Vref+的时候,DAC的输出电压是线性的从0~Vref+,12位模式下DAC输出电压与Vref+以及DORx的计算公式如下:


DACx输出电压=Vref*(DORx/4095)


接下来,我们介绍一下要实现DAC的通道1输出,需要用到的一些寄存器。首先是DAC控制寄存器DAC_CR,该寄存器的各位描述如图所示:



DAC_CR的低16位用于控制通道1,而高16位用于控制通道2,我们这里仅列出比较重要的最低8位的详细描述,如图所示:


首先,我们来看DAC通道1使能位(EN1),该位用来控制DAC通道1使能的,本章我们就是用的DAC通道1,所以该位设置为1。


再看关闭DAC通道1输出缓存控制位(BOFF1),这里STM32F4的DAC输出缓存做的有些不好,如果使能的话,虽然输出能力强一点,但是输出没法到0,这是个很严重的问题。所以本章我们不使用输出缓存。即设置该位为1。


DAC通道1触发使能位(TEN1),该位用来控制是否使用触发,里我们不使用触发,所以设置该位为0。


DAC通道1触发选择位(TSEL1[2:0]),这里我们没用到外部触发,所以设置这几个位为0就行了。


DAC通道1噪声/三角波生成使能位(WAVE1[1:0]),这里我们同样没用到波形发生器,故也设置为0即可。


DAC通道1屏蔽/复制选择器(MAMP[3:0]),这些位仅在使用了波形发生器的时候有用,本章没有用到波形发生器,故设置为0就可以了。


最后是DAC通道1 DMA使能位(DMAEN1),本章我们没有用到DMA功能,故还是设置为0。


通道2的情况和通道1一模一样,这里就不不细说了。在DAC_CR设置好之后,DAC就可以正常工作了,我们仅需要再设置DAC的数据保持寄存器的值,就可以在DAC输出通道得到你想要的电压了(对应IO口设置为模拟输入)。本章,我们用的是DAC通道1的12位右对齐数据保持寄存器:DAC_DHR12R1,该寄存器各位描述如图所示:



该寄存器用来设置DAC输出,通过写入12位数据到该寄存器,就可以在DAC输出通道1(PA4)得到我们所要的结果。


二.编程步骤


这里我们用到的库函数以及相关定义分布在文件stm32f4xx_dac.c以及头文件stm32f4xx_dac.h中


1)开启PA口时钟,设置PA4为模拟输入。


STM32F407ZGT6的DAC通道1是接在PA4上的,所以,我们先要使能GPIOA的时钟,然后设置PA4为模拟输入。


这里需要特别说明一下,虽然DAC引脚设置为输入,但是STM32F4内部会连接在DAC模拟输出上,这在我们引脚复用映射章节有讲解。


RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);//使能GPIOA时钟


GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;


GPIO_InitStructure.GPIO_Mode =GPIO_Mode_AN;//模拟输入


GPIO_InitStructure.GPIO_PuPd =GPIO_PuPd_DOWN;//下拉


GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化


对于DAC通道与引脚对应关系,这在STM32F4的数据手册引脚表上有列出,如下图:



2)使能DAC1时钟。同其他外设一样,要想使用,必须先开启相应的时钟。STM32F4的DAC模块时钟是由APB1提供的,所以我们先要在通过调用函数RCC_APB1PeriphClockCmd来使能DAC1时钟。


RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC,ENABLE);//使能DAC时钟


3)初始化DAC,设置DAC的工作模式。


该部分设置全部通过DAC_CR设置实现,包括:DAC通道1使能、DAC通道1输出缓存关闭、不使用触发、不使用波形发生器等设置。这里DAC初始化是通过函数DAC_Init完成的:


void DAC_Init(uint32_t DAC_Channel,DAC_InitTypeDef* DAC_InitStruct);


跟前面一样,首先我们来看看参数设置结构体类型DAC_InitTypeDef的定义:


typedef struct


{


uint32_t DAC_Trigger;


uint32_t DAC_WaveGeneration;


uint32_t DAC_LFSRUnmask_TriangleAmplitude;


uint32_t DAC_OutputBuffer; 


}DAC_InitTypeDef;


这个结构体的定义还是比较简单的,只有四个成员变量,下面我们一一讲解。


第一个参数DAC_Trigger用来设置是否使用触发功能,前面已经讲解过这个的含义,这里

我们不是用触发功能,所以值为DAC_Trigger_None。


第二个参数DAC_WaveGeneratio用来设置是否使用波形发生,这里我们前面同样讲解过不

使用。所以值为DAC_WaveGeneration_None。


第三个参数DAC_LFSRUnmask_TriangleAmplitude用来设置屏蔽/幅值选择器,这个变量只

在使用波形发生器的时候才有用,这里我们设置为0即可,值为DAC_LFSRUnmask_Bit0。


第四个参数DAC_OutputBuffer是用来设置输出缓存控制位,前面讲解过,我们不使用输出

缓存,所以值为DAC_OutputBuffer_Disable。到此四个参数设置完毕。看看我们的实例代码:


DAC_InitTypeDef DAC_InitType;


DAC_InitType.DAC_Trigger=DAC_Trigger_None;  //不使用触发功能 TEN1=0


DAC_InitType.DAC_WaveGeneration=DAC_WaveGeneration_None;//不使用波形发生


DAC_InitType.DAC_LFSRUnmask_TriangleAmplitude=DAC_LFSRUnmask_Bit0;


DAC_InitType.DAC_OutputBuffer=DAC_OutputBuffer_Disable;  //DAC1输出缓存关闭


DAC_Init(DAC_Channel_1,&DAC_InitType);   //初始化DAC通道1


4)使能DAC转换通道


初始化DAC之后,理所当然要使能DAC转换通道,库函数方法是:DAC_Cmd(DAC_Channel_1, ENABLE); //使能DAC通道1


5)设置DAC的输出值。


通过前面4个步骤的设置,DAC就可以开始工作了,我们使用12位右对齐数据格式,所以我们通过设置DHR12R1,就可以在DAC输出引脚(PA4)得到不同的电压值了。设置DHR12R1的库函数是:


DAC_SetChannel1Data(DAC_Align_12b_R, 0);//12位右对齐数据格式设置DAC值


第一个参数设置对齐方式,可以为12位右对齐DAC_Align_12b_R,12位左对齐DAC_Align_12b_L以及8位右对齐DAC_Align_8b_R方式。


第二个参数就是DAC的输入值了,这个很好理解,初始化设置为0。


这里,还可以读出DAC对应通道最后一次转换的数值,函数是:


DAC_GetDataOutputValue(DAC_Channel_1);


三.源码实验


此为设置好PA4,一点点增加值,输出到PA4,然后量PA4的波形


Dac.h



#ifndef_DAC_H_H_H

#define_DAC_H_H_H

#include"stm32f4xx_gpio.h"

#include"stm32f4xx_rcc.h"

#include"stm32f4xx_dac.h"

 

voidDac1_Init(void);                 //DAC通道1初始化              

voidDac1_Set_Vol(u16 vol);    //设置通道1输出电压

#endif

Dac.c


#include"dac.h"

//DAC通道1输出初始化

voidDac1_Init(void)

{  

  GPIO_InitTypeDef  GPIO_InitStructure;

  DAC_InitTypeDef DAC_InitType;

         

  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);//使能GPIOA时钟

  RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC,ENABLE);//使能DAC时钟

           

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;

  GPIO_InitStructure.GPIO_Mode =GPIO_Mode_AN;//模拟输入

  GPIO_InitStructure.GPIO_PuPd =GPIO_PuPd_DOWN;//下拉

  GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化

 

  DAC_InitType.DAC_Trigger=DAC_Trigger_None;       //不使用触发功能 TEN1=0

 DAC_InitType.DAC_WaveGeneration=DAC_WaveGeneration_None;//不使用波形发生

 DAC_InitType.DAC_LFSRUnmask_TriangleAmplitude=DAC_LFSRUnmask_Bit0;//屏蔽、幅值设置

  DAC_InitType.DAC_OutputBuffer=DAC_OutputBuffer_Disable;       //DAC1输出缓存关闭BOFF1=1

  DAC_Init(DAC_Channel_1,&DAC_InitType);       //初始化DAC通道1

 

  DAC_Cmd(DAC_Channel_1, ENABLE);  //使能DAC通道1

  DAC_SetChannel1Data(DAC_Align_12b_R, 0);  //12位右对齐数据格式设置DAC值

}

//设置通道1输出电压

//vol:0~3300,代表0~3.3V

voidDac1_Set_Vol(u16 vol)

{

  double temp=vol;

  temp/=1000;

  temp=temp*4096/3.3;

 DAC_SetChannel1Data(DAC_Align_12b_R,temp);//12位右对齐数据格式设置DAC值

}

Main.c



#include"led.h"

#include"key.h"

#include"delay.h"

#include"uart.h"

#include"exit.h"

#include"iwdog.h"

#include"pwm.h"

voidUser_Delay(__IO uint32_t nCount)

{

  while(nCount--)

  {

  }

}

staticint count = 0;

intmain(void)

{

 

  u16 adcx;

  u16 dacval1 = 0;

  float temp;

 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);

   My_USART2_Init();

   delay_init(168);

   printf("main test start\n");

   Adc_Init();

   Dac1_Init();

   EXTIX_Init();

   

   

   while(1)

   {

     dacval1 += 100;

      if(dacval1 >= 4000)

      {

        dacval1 = 0;

      }

      DAC_SetChannel1Data(DAC_Align_12b_R,dacval1);

     adcx=Get_Adc_Average(ADC_Channel_5,20);

     temp=(float)adcx*(3.3/4096);

     printf("adc value:(%d)\n",adcx);

     delay_ms(1);

     

   }

}


执行结果如下图:

关键字:stm32f407  DAC实验 引用地址:【stm32f407】DAC实验

上一篇:【stm32f407】I2C实验
下一篇:【stm32f407】ADC实验

推荐阅读最新更新时间:2024-03-16 16:23

STM32F407 Flash操作笔记
简述 STM32F4XX的闪存擦除方式分为两种:扇区擦除(最小单元16K)和整片擦除。在实际应用中,为满足重要信息的存储,需将信息存入FLASH中,针对以上两种擦除方式,扇区擦除更符合实际的需要。 参考手册: 写FLASH操作 经过以上五个步,就可以擦除某个扇区。但是实际运用过程中,一个扇区只存储一个信息或标志,会造成资源严重浪费。现采用缓存的方式,先读取当下扇区的数据,将读取的数据和要写入的数据组合,待擦除后再次写入。 代码片 写FLASH操作 /* * WriteAddr: 起始地址 (u32)address 是 4 的整数倍, (u32)data * pBuffer: 数据指针
[单片机]
<font color='red'>STM32F407</font> Flash操作笔记
stm32F407之USART6的DMA工作方式
昨天调试了USART6的DMA工作模式,今天补发上这篇笔记。 力求简洁,stm32的DMA就不介绍了,不了解的可以搜索一下。这里重点介绍一下DMA的外设地址如何确定,这个是网上很少涉及但是很重要的一块,如果不清楚如何确定外设寄存器地址就无法进行DMA功能,这里以stm32F407的USART6为例介绍,参考手册为 RM0090 Reference manual 。 在进行DMA参数配置时有这样一项 DMA_InitStructure.DMA_PeripheralBaseAddr = ?;这句是要确定Memory与Peripheral数据传输时的外设数据地址,因为这里我们用到的是USART6从Memory的数组中取出数据并发送给上位
[单片机]
<font color='red'>stm32F407</font>之USART6的DMA工作方式
STM32F407用wk2124芯片编写SPI转四路串口驱动
引言 因为项目用到了wk2124芯片来进行串口扩展,网上找了好多资料没有现成的,根据商家提供的demo,它是基于103写的,所以根据自己板子的实际情况进行了改写,并且学习一下里面的主要函数及我对函数的理解 原理图 用到5个引脚,片选CS、时钟SCK、MOSI、MISO和中断IRQ,因为RST设置的是板子连电后电容充电,所以会自动复位,不用这个引脚。 一. SPI通信配置 1.GPIO初始化设置 GPIO_InitTypeDef GPIO_InitStructure; RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);//使能GPIOB时钟 RCC_APB
[单片机]
<font color='red'>STM32F407</font>用wk2124芯片编写SPI转四路串口驱动
STM32F407 SPI flash
STM32F407 SPI 接口: STM32F4XX时钟计算 HCLK=168M PCLK1 =HCLK/4 =42M PCLK2 =HCLK/2 =84M SPI2、SPI3在PCLK1,最大时钟为42M SPI1在PCLK2,最大时钟为84M STM32F4 支持的最大SPI时钟为37.5Mbits/s 因此需要分频。 例程选择SPI2 分频后为21M 串行Flash W25Q64BVSSIG (最高支持80MHz)。 测试: 全部写入0XAA 数据长度8192K 擦除:20.798 写入耗时42.599S 读:9.008S 百度的参照时间 擦除:8.9S 写入
[单片机]
<font color='red'>STM32F407</font> SPI flash
STM32F407的ADC之DMA多通道+温度
这里是在上一章中加上了温度 上图是温度计算公式:其中Vsense为采集到温度通道的ADC值 stm32f407温度通道是ADC1的16通道。 Avg_Slope一般取0.0025 和上一张比主要是该了下的内容: 1、增加ADC_TempSensorVrefintCmd(ENABLE);/*使能内部温度传感器*/ 2、修改ADC_InitStructure.ADC_NbrOfConversion = 3;/*只使用1通道 规则通为1*/ 由2改为3 因为之前只用到了PA2和PA3两个通道 现在增加了ADC1的16通道 3、增加ADC_RegularChannelConfig(ADC1,ADC_Channel_16,
[单片机]
STM32F407 串口编程USART1,USART2,USART3,UART4
串口设置的一般步骤可以总结为如下几个步骤: 1) 串口时钟使能,GPIO时钟使能。 2) 设置引脚复用器映射:调用GPIO_PinAFConfig函数。 3) GPIO初始化设置:要设置模式为复用功能。 4) 串口参数初始化:设置波特率,字长,奇偶校验等参数。 5) 开启中断并且初始化NVIC,使能中断(如果需要开启中断才需要这个步骤)。 6) 使能串口。 7) 编写中断处理函数:函数名格式为USARTxIRQHandler(x对应串口号)。 我们通过USART3简单介绍下这几个与串口基本配置直接相关的几个固件库函数。这些函数和定义主要分布在stm32f4xx_usart.h和stm32f4xx_usart.c文
[单片机]
<font color='red'>STM32F407</font> 串口编程USART1,USART2,USART3,UART4
国产优秀替代_APM32F407替代STM32F407记录
前言 最近一段时间在玩极海的APM32F407系列的MCU,在研究一段时间后发现其资源和意法半导体的STM32F407不相上下。通过对比两者的数据手册和参考手册,我发现APM32F407替代STM32F407绰绰有余。我拿出了我吃灰已久的一块开发板“启明欣欣 IMT407 V5.1”(淘宝搜索“启明欣欣”)。预计将开发板上的STM32F407芯片替换成APM32F407的芯片,看看会发生什么样的事情。 本文记录一下我使用APM32F407替代STM32F407制作的一个小demo(使用SPI外设读取W25Q128)。该demo使用原开发板电路,看看将主控换成APM32F407后看看能不能做到pin对pin的完美替代。 本文使用环境
[单片机]
国产优秀替代_APM32F407替代<font color='red'>STM32F407</font>记录
接触STM32F407芯片的总结
今天开始弄了一下STM32F4的板子,板子的核心芯片是STM32F407,是Contex M4的内核,和之前接触的STM32F1的相比,功能真的强大了很多,而且设计上也更加容易使用,先介绍一下今天的成果。 今天看了数据手册的RCC部分和GPIO部分,在灵格斯的帮助下,还是能够看懂的,因为它和STM32F1差不多,应该是高级芯片的寄存器结构都很类似,所以看起来不是那么的难懂,很多东西都是相通的。 GPIO部分,他的寄存器包括4个参数设置寄存器用来设置IO口的工作方式,两个数据寄存器(一个输入一个输出),一个置位复位寄存器,一个LOCK寄存器,两个功能选择寄存器。寄存器的结构是十分的清晰的,Configure寄存器
[单片机]
热门资源推荐
热门放大器推荐
  •  pdf文件控制系统设计指南 (埃利斯)
  •  pdf文件DMF407电机控制专题教程_V1.1
  •  zip文件OSEK NM网络管理开发示例
  •  none文件Altium Designer原理图与PCB设计及仿真
  • 系统发生错误

    系统发生错误

    您可以选择 [ 重试 ] [ 返回 ] 或者 [ 回到首页 ]

    [ 错误信息 ]

    页面错误!请稍后再试~

小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
  • 学习ARM开发(16)
    ARM有很多东西要学习,那么中断,就肯定是需要学习的东西。自从CPU引入中断以来,才真正地进入多任务系统工作,并且大大提高了工作效率。采 ...
  • 学习ARM开发(17)
    因为嵌入式系统里全部要使用中断的,那么我的S3C44B0怎么样中断流程呢?那我就需要了解整个流程了。要深入了解,最好的方法,就是去写程序 ...
  • 学习ARM开发(18)
    上一次已经了解ARM的中断处理过程,并且可以设置中断函数,那么它这样就可以工作了吗?答案是否定的。因为S3C44B0还有好几个寄存器是控制中 ...
  • 嵌入式系统调试仿真工具
    嵌入式硬件系统设计出来后就要进行调试,不管是硬件调试还是软件调试或者程序固化,都需要用到调试仿真工具。 随着处理器新品种、新 ...
  • 最近困扰在心中的一个小疑问终于解惑了~~
    最近在驱动方面一直在概念上不能很好的理解 有时候结合别人写的一点usb的例子能有点感觉,但是因为arm体系里面没有像单片机那样直接讲解引脚 ...
  • 学习ARM开发(1)
  • 学习ARM开发(2)
  • 学习ARM开发(4)
  • 学习ARM开发(6)
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved