STM32之DAC

发布者:CelestialGarden最新更新时间:2022-02-16 来源: eefocus关键字:STM32  DAC  转换速度 手机看文章 扫描二维码
随时随地手机看文章

       STM32F103VCT6自带两个12位DAC,DAC的转换速度一直没有查到,网上有人说是1MHZ的频率,那就是1us了。ADC的转换时间在56MHZ工作频率下为1us,在72MHZ工作频率下为1.17us。如果AD和DA有对称关系的话,那么很可能跟ADC的时间相同。(仅作分析用!)


       DAC于我,有两个用途:输出波形和输出固定电压。先来说说前者的配置。


       第一个参数:触发方式,DAC_InitStructure.DAC_Trigger。可选的外部触发源一共有八个。六个是定时器触发:TIM2,TIM4,TIM5,TIM6,TIM7和TIM8。剩下两个分别是:EXTI线路9和软件触发。如果采用定时器触发的话,就还要再编写相应的定时器函数,这个倒不是很复杂,和定时器的编写方式类似。如:DAC_InitStructure.DAC_Trigger = DAC_Trigger_T6_TRGO;//选择定时器6作外部触发源

 

void TIM_Configuration(void)

{

       TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;

       TIM_OCInitTypeDef            TIM_OCInitStructure;

 

      

       TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);

      TIM_TimeBaseStructure.TIM_Period = 0x85;         

      TIM_TimeBaseStructure.TIM_Prescaler = 0x0;      

      TIM_TimeBaseStructure.TIM_ClockDivision = 0x0;   

      TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; 

      TIM_TimeBaseInit(TIM6, &TIM_TimeBaseStructure);     

      

    TIM_SelectOutputTrigger(TIM6, TIM_TRGOSource_Update);

}


       输出信号频率计算:假设输出一个6个点的锯齿波波形,则其频率为:(72MHZ/(0x85+1))*6=89.552KHZ.注意:如果prescaler不为0,则时钟还要再除以(prescaler+1)


       第二个参数:DAC_InitStructure.DAC_WaveGeneration。顾名思义:波形发生器。STM32内部集成了两个幅度可调的波形发生器,可以产生三角波和噪声波。如果我们使用自定义的缓冲区的话,就不需要配置这个参数或者使其为DAC_WaveGeneration_None,但为了避免别人误以为你忘了配置这个参数,所以还是多写一句吧,养成好的习惯。


       第三个参数:DAC_InitStructure.DAC_OutputBuffer,即是否使用输出缓存。输出缓存的功能主要用来减小输出阻抗,是STM32的DAC无需外部运放就可以直接驱动负载。这里一般设置成DAC_OutputBuffer_Disable,即关闭外部缓存。这是为保险起见,万一驱动能力不够强(本人也没试过@_@),那调试的时间就又多了一些。


       参数的配置就这么多了,算得上STM32中最简单的外设配置之一了!


       一般来说,用DAC输出波形,传输的数据比较多,所以采用DMA传输可以节省CPU的开支。所以在调用DAC_DMACmd(DAC_Channel_1, ENABLE);函数后别忘了配置DMA函数。详细的配置说明就不写了,这里把代码贴出来:

 

void DMA_Configuration(void)

{

       DMA_InitTypeDef            DMA_InitStructure;

      

       DMA_DeInit(DMA2_Channel3);

       DMA_InitStructure.DMA_PeripheralBaseAddr = DAC_DHR12R1_Address;

       DMA_InitStructure.DMA_MemoryBaseAddr = (u32)&FIR_OutPutValueTab;

       DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;

       DMA_InitStructure.DMA_BufferSize = 200;

       DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;

       DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;

       DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;

       DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;

       DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;

       DMA_InitStructure.DMA_Priority = DMA_Priority_High;

       DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;

       DMA_Init(DMA2_Channel3, &DMA_InitStructure);

 

      

       DMA_Cmd(DMA2_Channel3, ENABLE);

      

       DMA_ITConfig(DMA2_Channel3,DMA_IT_TC,ENABLE);

}


       注意红色字体写的那行代码,当我们传输多个数据时,需要将其设置为连续转换!其余就不赘述了。


       接下来谈谈DAC固定电压的配置。


       STM32的DAC固定电压配置和上面的波形输出配置相似,不同的地方在于它要多调用一个函数:DAC_SoftwareTriggerCmd(DAC_Channel_1,ENABLE);这样才会输出固定的电平。


       具体配置如下:

 

void DAC_VOLTAGE_Configuration(void)

{

       DAC_InitTypeDef            DAC_InitStructure;

       DAC_DeInit();

      

      DAC_InitStructure.DAC_Trigger = DAC_Trigger_None;

      DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_None;      

      DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Disable;

      DAC_Init(DAC_Channel_1, &DAC_InitStructure);

       //

      

       DAC_Cmd(DAC_Channel_1, ENABLE);

       DAC_SoftwareTriggerCmd(DAC_Channel_1,ENABLE);

}


       配置完成后,调用DAC_SetChannel1Data(DAC_Align_12b_R,4000);函数就可以发送数据了!!极其方便。比起5615,0832之流不知简便了多少!有两点要注意:1、该函数的第一个参数DAC_Align_12b_R不可依据设置ADC外设地址的方式重写这个地址,因为这个参数是不带基址的,而我们重写地址后一半会把基址算进去,这样就不对了!(笔者就曾经卡在这里!看来凡事不可先入为主,否则问题迟早会发生。)2、每次改变发送数据时,要同时调用以下两个函数:

       DAC_SetChannel1Data(DAC_Align_12b_R,4000);

       DAC_SoftwareTriggerCmd(DAC_Channel_1,ENABLE);

至于为什么,我的理解是:因为DAC改变数据后并不会立即写入寄存器,需要一次更新,由于不是通过定时器触发来更新,因此就只能通过调用函数的方法来更新。


=======================================================================================================

1、简述:

12位数字输入,电压输出,DAC可以配置为8位或12位模式。有2个输出通道。在双DAC模式下,两个通道可以独立地工作。

 

特殊功能: 噪声波形生成,三角波形生成,外部触发转换,双DAC同时或者分别转换;每个通道都有DMA功能;

 

参考电压:2.4V~ 3.3V

 

因为一旦使能DAC通道,那么相应的GPIO便自动地连接到DAC转换器,因此,模拟输出前应该设置成模拟输入,目的是避免寄生的干扰和额外的功耗;

 

2、函数介绍:

(1)缺省函数

DAC_Init();

 

(2)DAC_Init(DAC_Channel_1,&DAC_InitStructure);初始化函数

DAC_InitTypeDef            DAC_InitStructure;

初始化的设置有四个:

❶DAC_Trigger:指定所选DAC的触发源,有9个触发源可以选择:

DAC_Trigger_None

DAC_Trigger_T6_TRGO

DAC_Trigger_T8_TRGO

DAC_Trigger_T7_TRGO

DAC_Trigger_T5_TRGO

DAC_Trigger_T2_TRGO

DAC_Trigger_T4_TRGO

DAC_Trigger_Ext_IT9

DAC_Trigger_Software

 

❷DAC_WaveGeneration :指定DAC是否产生噪声波形,三角波或者不产生以上波形

DAC_WaveGeneration_None

DAC_WaveGeneration_Noise

DAC_WaveGeneration_Triangle

❸DAC_LFSRUnmask_TriangleAmplitude:如果选择了产生噪声波形或者三角波,那么这里可以选择噪声波形的LFSRUnMask屏蔽位(不晓得是什么东西) 或者三角波的最大幅度

❹DAC_OutputBuffer:指定输出是否要缓冲一下

DAC_OutputBuffer_Enable

DAC_OutputBuffer_Disable

(3)DAC_Cmd(DAC_Channel_1,EANBLE); DAC通道使能函数

 

(4)DAC_DMACmd(DAC_Channel_1,ENABLE); 如果要用到DMA到DAC那么就要使能哪个DAC通道

 

(5)DAC_SoftwareTriggerCmd(DAC_Channel_1, ENABLE);软件触发使能函数,一般单通道时候使用

 

(6)DAC_DualSoftwareTriggerCmd(ENABLE);如果要同时控制两个DAC通道,那么就要使能此函数

 

(7)DAC_Wave GenerationCmd(DAC_Channel_1, DAC_Wave_Noise, ENABLE);波形发生使能函数,可以选择哪个通道以及噪声或者三角波波形

 

(8)DAC_SetChannel1Data(DAC_Align_12b_R, 0x500);

选择通道1的数据位数和对齐方式,以及具体输出值。三种对齐数据位方式:

DAC_Align_12b_R  12位右对齐,数值小于4096

DAC_Align_12b_L 12位左对齐,数值小于0XxFFF0

DAC_Align_8b_R 8位右对齐,数值小于256

(9)DAC_SetChannel2Data(DAC_Align_12b_L, 0x8880);同理(8)

 

(10)DAC_SetDualChannelData(DAC_Align_8b_R, 0x40, 0xF1);同理(8)

 

(11)u16 DataValue;

DataValue = DAC_GetDataOutputValue(DAC_Channel_1); 得到当前DAC输出的值

3、具体应用:

3.1 产生一个直流电压:

GPIOA_04 是DAC1 , GPIOA_05 是DAC2

1、设置GPIOA_04 或05 为模拟输入;

  GPIO_InitTypeDef GPIO_InitStructure;

  GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_4 | GPIO_Pin_5;

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;

  GPIO_Init(GPIOA, &GPIO_InitStructure)

 

2、开启GPIOA和DAC的时钟。注意GPIOA的时钟是在APB2,而DAC的时钟则是在APB1

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

  RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE);

3、配置DAC输出直流电压

DAC_InitTypeDef            DAC_InitStructure;

DAC_InitStructure.DAC_Trigger = DAC_Trigger_None;//选择DAC的触发输出,当产生波形时可用定时器触发

DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_None;

DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Disable;

DAC_Init(DAC_Channel_1, &DAC_InitStructure);

DAC_Cmd(DAC_Channel_1, ENABLE);

DAC_SetChannel1Data(DAC_Align_12b_R,4095);//我的板子实际输出的是3.265v


3.2 产生三角波

在上述代码基础上加入下面代码,其中部分代码替代

  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);

     TIM_TimeBaseInitTypeDef    TIM_TimeBaseStructure;

  TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);

  TIM_TimeBaseStructure.TIM_Period = 0xF;         

  TIM_TimeBaseStructure.TIM_Prescaler = 0xF;      

  TIM_TimeBaseStructure.TIM_ClockDivision = 0x0;   

  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; 

  TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);

  TIM_SelectOutputTrigger(TIM2, TIM_TRGOSource_Update);

 /*

                  TIM_SelectOutputTrigger()函数到底是干嘛的?定时器触发输出,比如用作触发另一个定时器,触发AD转换等,触发其他外设

*/

  DAC_InitStructure.DAC_Trigger = DAC_Trigger_T2_TRGO;

  DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_Triangle;

  DAC_InitStructure.DAC_LFSRUnmask_TriangleAmplitude = DAC_TriangleAmplitude_2047;


3.3 利用DMA产生正弦波(DAC2)和直流电压值(DAC1)

uint16_t g_Wave[128];

uint16_t DAC1_Value[1];

 

 const uint16_t SineData[32] = {

                       2047, 2447, 2831, 3185, 3498, 3750, 3939, 4056, 4095, 4056,

                       3939, 3750, 3495, 3185, 2831, 2447, 2047, 1647, 1263, 909,

[1] [2]
关键字:STM32  DAC  转换速度 引用地址:STM32之DAC

上一篇:寄存器led灯 亮灭
下一篇:RTC(实时时钟)和BKP(备份寄存器)

推荐阅读最新更新时间:2024-11-17 08:13

STM32驱动0.96 OLED I2C显示程序
0.96 OLED的主控芯片是SSD1306,用STM32驱动OLED显示的程序如处图所示 #include system.h #include SysTick.h #include OLED_I2C.h int main() { u8 i; extern const unsigned char BMP1 ; SysTick_Init(72); I2C_Configuration(); OLED_Init(); while(1) { OLED_CLS(); for(i=0;i 5
[单片机]
<font color='red'>STM32</font>驱动0.96 OLED I2C显示程序
unity在stm32上的使用
按照本文的描述,应该可以在你所处的 硬件 上跑通代码。 先决条件:装有编译和集成的开发环境,比如: Keil uVision5。 板子硬件要求:无, 芯片 自带的串口功能即可完成。 源码获取 Unity 是一个轻量级的 C 语言单元测试框架,它的设计理念是简单易用。 Unity 支持测试套件和测试用例,同时提供了丰富的断言函数,包括比较、异常和日志等。 源码入口: GitHub - ThrowTheSwitch/Unity: Sim ple Unit Te sting f or C https://github.com/ThrowTheSwitch/Unity/ 源码里面结构,接下来准备一个stm32的基础工程,把相关代码
[单片机]
unity在<font color='red'>stm32</font>上的使用
STM32的窗口看门狗(WWDG)
一、窗口看门狗由从APB1时钟分频后得到时钟驱动。 通过可配置的时间窗口来检测应用程序非正常的过迟或过早操作。 窗口看门狗最适合那些要求看门狗在精确计时窗口起作用的程序。 二、什么是窗口看门狗? 窗口就是因为其喂狗时间是一个有上下限的范围内(窗口),你可以通过设定相关寄存器,设定其上限时间(下限固定)。喂狗的时间不能过早也不能过晚。 而独立看门狗限制喂狗时间在0-x内,x由相关寄存器决定。喂狗的时间不能过晚 三、窗口看门狗的好处 对于一般的看门狗,因为是在复位前的任意时刻刷新看门狗,但有可能程序跑乱了又跑回到正常的地方,或跑乱的程序正好执行了刷新看门狗操作,这样的情况下就检测不
[单片机]
<font color='red'>STM32</font>的窗口看门狗(WWDG)
STM32移植lwip之建立tcp客户端
本篇目标:在之前能ping通pc机的工程基础上搭建tcp客户端,并可以主动发数据给pc机,同时也能与pc机收发数据,并在网络调试工具上显示 材料准备: 基础工程:修改后能ping通pc机的工程( STM32官方移植lwip修改代码 ) 调试工具:用来调试tcp连接下的数据接收( 网络调试助手 ) 搭建工程:最终搭建好tcp客户端数据接收的工程( tcp客户端建立工程 ) 搭建TCP客户端 搭建TCP客户端的过程与上一章TCP服务器也相似,所以尽量把重点的地方加粗显示来区别 在搭建TCP客户端之前可以先理一下概念,客户端与服务器的区别: 客户端:主动建立tcp去连接目标IP 服务器:拥有静态IP,能让其他设备被动连接
[单片机]
STM32上电启动过程分析
单片机上电后执行的第一段代码 1.初始化堆栈指针 SP=_initial_sp 2.初始化 PC 指针=Reset_Handler 3.初始化中断向量表 4.配置系统时钟 5.调用 C 库函数_main 初始化用户堆栈,然后进入 main 函数。 在正式讲解之前,我们需要了解STM32的启动模式。 STM32的启动模式 手册可以在Keil中跳转查看 STM32的三种启动模式 首先要讲一下STM32的启动模式,因为启动模式决定了向量表的位置,STM32有三种启动模式: 1. 主闪存存储器(Main Flash memor
[单片机]
<font color='red'>STM32</font>上电启动过程分析
STM32与有源蜂鸣器
有源蜂鸣器的声音是固定的,工作电压恒定,改变通断电的时间获得不同时长的音响,譬如连续音、快速短音、慢速长音(类似莫尔斯电报)来区分不同的报警信息。 简单的说,有源蜂鸣器只能发出一种声音,因为它的频率是固定的。只能根据响声的不同间隔长短来区分。 例如,闹钟是:滴滴~滴滴~滴滴~。 有源只要通电就响了,我们只要控制好通电的时间就好。 #include mbed.h PwmOut PWM1(PB_13); int main() { while(1) { PWM1 = 1;//响 wait(0.1);//响0.1s PWM1 = 0;//不响 wait(0.1);//不响0.1s PWM1 = 1;//再响
[单片机]
STM32的GPIO—快速IO的使用与讲解
STM32的每个GPIO端口都有两个特别的寄存器,GPIOx_BSRR和GPIOx_BRR寄存器,通过这两个寄存器可以直接对对应的GPIOx端口置'1'或置'0'。 GPIOx_BSRR的高16位中每一位对应端口x的每个位,对高16位中的某位置'1'则端口x的对应位被清'0';寄存器中的位置'0',则对它对应的位不起作用。 GPIOx_BSRR的低16位中每一位也对应端口x的每个位,对低16位中的某位置'1'则它对应的端口位被置'1';寄存器中的位置'0',则对它对应的端口不起作用。 简单地说
[单片机]
DAC输出的多通道温度采集模块的设计
在化工产业,机械加工,工业制造等领域经常要考虑到温度对测量或加工的影响,因此对温度的测量和控制就显得尤为重要。特别在一些环境恶劣、干扰较强的使用场合,温度采集装置的稳定是实现测量与控制的首要环节。本文针对上述背景,设计了通用多通道检测模块。 1 系统结构和工作原理 模块采用单片机ATmega48为控制核心,多路恒流源测温电路通过电子开关CD4051与13位A/D转换器MCP3301相连,通过单片机控制3/8译码器74HC138进行通道选择;模块通过基于Modbus通信协议的RS 485接口与主机通信;并具有一路PWM转DAC电路。模块适用于与PLC等主机连接,各通道实时检测数据保存于各通道的保持寄存器中,当接收到主机读取命令
[测试测量]
带<font color='red'>DAC</font>输出的多通道温度采集模块的设计
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

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

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

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