打印
[应用相关]

关于DAC转换

[复制链接]
1949|4
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
米尔豪斯|  楼主 | 2015-12-24 19:45 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
DAC, DMA, TI, mx, DM
本帖最后由 米尔豪斯 于 2015-12-24 20:50 编辑

STM32DAC例程都用TIMx更新启动DMA2,有没有不用TIMx启动DMA2自动把数据传送DACDHRxx寄存器里面?该如何设置呢?
沙发
mintspring| | 2015-12-24 20:05 | 只看该作者
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);
}


使用特权

评论回复
板凳
mintspring| | 2015-12-24 20:05 | 只看该作者
配置完成后,调用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改变数据后并不会立即写入寄存器,需要一次更新,由于不是通过定时器触发来更新,因此就只能通过调用函数的方法来更新。

使用特权

评论回复
地板
mintspring| | 2015-12-24 20:06 | 只看该作者
STM32F4的DAC是一个12位,电压输出的DAC。可被配置为12位或者8位,也能和DMA联合使用。DAC具有两个独立转换通道。在双DAC模式下,DA抓换可被配置成独立模式或者同步工作模式。两路DAC参考电压以及ADC都是VREF。

【主要特性】

1、两路  2、12bit时数据可被配置成左对齐或右对齐  3、具有同步更新能力  4、噪声产生  5、三角波产生  6、两个通道独立转换或同步转换  7、每个通道都有DMA能力  8、DMA出错检测 9、可外部触发

输出电压计算公式:

Vout = VREF×DOR/4095 = 参考电压×DAC数据寄存器值/4095

【实验内容】

利用DAC输出指定的电压,软件触发DAC转换。

【初始化要点】

1、GPIO配置成AIN/AN即模拟功能。记着开时钟

void DAC_GPIO_Config(void)
{
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
  GPIO_Init(GPIOA,&GPIO_InitStructure);
  
}

2、DAC触发方式设置为软件触发(DAC_Trigger_Software)

void DAC_Config(void)
{
  DAC_GPIO_Config();
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC,ENABLE);
  DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_None;
  DAC_InitStructure.DAC_Trigger = DAC_Trigger_Software;
  DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Enable;
  DAC_Init(DAC_Channel_1,&DAC_InitStructure);
  
  DAC_Cmd(DAC_Channel_1,ENABLE);
  DAC_SetChannel1Data(DAC_Align_12b_R,0x0000);
  
  DAC_SoftwareTriggerCmd(DAC_Channel_1,ENABLE);
}

3、主函数中使用:

向输出寄存器写数据,数据可根据上边公式得到

DAC_SetChannel1Data(DAC_Align_12b_R,0xF0F0);

然后,然间触发

DAC_SoftwareTriggerCmd(DAC_Channel_1,ENABLE);

这时,在引脚上GPIOA-4上将会有电压输出。



当然也可以设置成定时器触发,TIM6和TIM7 是专公DAC转换用的定时器。初始化也很方便。

使用特权

评论回复
5
lefeng| | 2015-12-24 20:36 | 只看该作者
固定值输出是DAC最简单的使用,在STM32的DAC中我们需要设置的东西并不多

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

150

主题

731

帖子

1

粉丝