DAC

DAC是数字模拟转换器(Digital-to-Analog Converter)的缩写。它是一种电子设备或电路,用于将数字信号转换为模拟信号。DAC在各种应用中都有重要作用,例如音频处理、通信系统、仪器仪表和控制系统等。

总的来说,DAC是一种关键的电子器件,用于将数字信息转换为模拟信号,使数字系统能够与模拟世界进行交互。不同应用领域需要不同类型和性能的DAC,以满足其特定的需求。

DAC模块作为CKS32F4xx系列的一个常用外设,可以将数字信号转换成模拟信号,最高分辨率可达12位,且两个独立DAC输出通道转换互不影响,各个通道均能使用DMA功能,可由软硬件触发。因此,为了实现DAC输出正弦波,拟采用一定的时间向DAC的数据寄存器写入数据,随后进行数模转换输出不同的电压,最后在时间轴上显示出波形。同时为了不占用CPU资源,配置DMA建立传输通道,以便数据快速的从内存搬移到外设。且在DAC初始化时,可以设置成定时器触发,待定时器溢出就会触发DAC工作,所以只要修改定时器的定时时间,就可改变正弦波周期。

DAC简述

1.png

①:DAC将VREF+引脚作为参考电压,在实际使用时将VSSA接地,同时把VREF+和VDDA接3.3V,DAC即可获得0~3.3V的输出电压。

②:数模转换器以VREF+作为参考电源,将DAC的数据寄存器“DORx”的数字编码转换成模拟信号并由右侧的“DAC_OUTx”通道输出。在CKS32有2个这样的DAC部件,其中PA4对应通道1,PA5对应通道2。

③:控制逻辑可以控制数据寄存器“DORx”加入一些伪噪声信号或配置产生三角波信号。

④:使用DAC时,数据会被先写入到DHRx寄存器,随后DAC会根据触发配置进行处理,最后将数据传输至DORx。DAC的触发源有三种,分别为:外部中断源触发、定时器触发和软件控制触发。

对于单DAC通道x的三种数据格式

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被线性地转换为模拟电压输出,任一DAC通道引脚上的输出电压满足下面的关系:

本案例中选择DAC的通道1,并采用12位的右对齐方式,通过查阅《CKS32F4xx参考手册》DAC和DMA章节可知,DAC1对应DMA1控制器通道7数据流5。

总的来说,DAC的输出是由DORx寄存器直接控制的,而用户写的数据是要写入DHRx寄存器,然后通过DHRx间接操作DORx,最终实现DAC的输出。

DAC输出正弦波配置

本文采用DAC1+TIM2+DMA1的方式,通过TIM2触发DAC1转换,转换完成后通过DMA1输出,主要步骤如下:

①由Matlab计算一个周期的正弦波数组;

②根据一个正弦波周期内点数和所需正弦波频率确定定时器触发间隔;

③初始化DAC1输出管脚和工作模式;

④配置触发DAC1用的定时器2;

⑤配置DMA1自主搬运正弦波数组。

待上述配置完成后,将PA4引脚接到示波器上,即可显示正弦波。以下是DAC的详细配置。

(1)正弦波数组生成

以下代码用于生成正弦波波形表:

for(i=0;i<100;i++)
{
    Sine12bit[i]=2048*sin(1.0*i/(100- 1)*2*PI)+2048;
}

从上述函数可以看出,正弦波的幅度被控制在0~4096之间,一个周期被平均分成100份,即100个点代表一个周期的波形,数组Sine12bit里面是100个采样点。

const uint16_t Sine12bit[100] = {

0x0800,0x0881,0x0901,0x0980,0x09FD,0x0A79,0x0AF2,0x0B68,0x0BDA,0x0C49,0x0CB3,0x0D19,0x0D79,0x0DD4,0x0E29,0x0E78,0x0EC0,0x0F02,0x0F3C,0x0F6F,0x0F9B,0x0FBF,0x0FDB,0x0FEF,0x0FFB,0x0FFF,0x0FFB,0x0FEF,0x0FDB,0x0FBF,0x0F9B,0x0F6F,0x0F3C,0x0F02,0x0EC0,0x0E78,0x0E29,0x0DD4,0x0D79,0x0D19,0x0CB3,0x0C49,0x0BDA,0x0B68,0x0AF2,0x0A79,0x09FD,0x0980,0x0901,0x0881,0x0800,0x077F,0x06FF,0x0680,0x0603,0x0587,0x050E,0x0498,0x0426,0x03B7,0x034D,0x02E7,0x0287,0x022C,0x01D7,0x0188,0x0140,0x00FE,0x00C4,0x0091,0x0065,0x0041,0x0025,0x0011,0x0005,0x0001,0x0005,0x0011,0x0025,0x0041,0x0065,0x0091,0x00C4,0x00FE,0x0140,0x0188,0x01D7,0x022C,0x0287,0x02E7,0x034D,0x03B7,0x0426,0x0498,0x050E,0x0587,0x0603,0x0680,0x06FF,0x077F};

(2)GPIO和DAC模式配置

该部分为输出引脚配置和DAC通道1配置,代码如下:

void DAC1_GPIO_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    DAC_InitTypeDef DAC_InitStructure;
    /*  Enable GPIOA clock  */
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);/*  Enable DAC clock  */RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE);/*  Configure the DAC Pin to Analog mode: DAC_OUT1 -- PA4  */GPIO_InitStructure.GPIO_Pin=GPIO_Pin_4;GPIO_InitStructure.GPIO_Mode= GPIO_Mode_AIN;
    GPIO_InitStructure.GPIO_PuPd= GPIO_PuPd_NOPULL;
    GPIO_InitStructure.GPIO_Speed= GPIO_Speed_100MHz;  
    GPIO_InitStructure.GPIO_OType= GPIO_OType_PP;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
    /*  Configure DAC Channel_1  */
    DAC_InitStructure.DAC_Trigger= DAC_Trigger_T2_TRGO;
    DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_None;DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Disable;DAC_InitStructure.DAC_LFSRUnmask_TriangleAmplitude = DAC_LFSRUnmask_Bit0;DAC_Init(DAC_Channel_1, &DAC_InitStructure);
    DAC_Cmd(DAC_Channel_1, ENABLE);//Enable DAC Channel_1.
    DAC_DMACmd(DAC_Channel_1, ENABLE);//Enable DAC channel_1 DMA request.
}

在DAC1_GPIO_Init函数中,实现了相应GPIO引脚(PA4)的初始化和DAC工作模式配置。其中为了避免寄生的干扰和额外的功耗,应将PA4引脚设置成模拟输入模式(AIN),如此方可正常工作。

而对DAC工作模式进行配置时,可查看CKS官方提供的DAC_InitTypeDef结构体,该结构体中主要包含了DAC_CR寄存器的各寄存器配置。如下是DAC_InitTypeDef结构体成员简述:

(a)DAC_Trigger

该成员用于DAC的触发模式配置,由上文DAC通道框图可知,共有三种触发模式,分别是定时器触发(DAC_Trigger_T2/4/5/6/7/8_TRGO)、软件触发(DAC_Trigger_Software)和EXTI_9触发方式(DAC_Trigger_Ext_IT9)。

(b)DAC_WaveGeneration

该成员可配置输出伪噪声和三角波输出(DAC_WaveGeneration_Noise/Triangle),若使用自定义输出,应配置为DAC_WaveGeneration_None。

(c)DAC_OutputBuffer

该成员用于控制是否使能DAC的输出缓冲(DAC_OutputBuffer_Enable/Disable)。若需要直接驱动外部负载,可以使能该成员以减小输出阻抗。

(d)DAC_LFSRUnmask_TriangleAmplitude

该成员通过控制DAC_CR的MAMP2位设置LFSR寄存器位的数据,即当使用伪噪声或三角波输出时要叠加到DHRx的值。若使用伪噪声输出时LFSR=0xAAA,这时该结构体成员可赋值为DAC_LFSRUnmask_Bit0~DAC_LFSRUnmask_Bit11_0;若使用三角波输出时,这时该结构体成员可赋值为DAC_TriangleAmplitude_1~DAC_TriangleAmplitude_4096,可用于设置三角波的最大幅值。

本例中,将DAC通道1配置成定时器TIM2触发,不使用波形发生器和不使用输出缓存,不使用输出缓存是因为CKS32的DAC无需外部运放就可以直接驱动负载,三角波振幅一项虽然本案例没有用到,可以配置成任意,但此项不可缺,最后调用DAC_Cmd、DAC_DMACmd函数使能DAC通道1和DMA的请求。

(3)定时器配置

该部分是配置触发DAC的定时器TIM2,通过设定触发的间隔,从而间接控制正弦波周期,TIM2的工作决定DMA与DAC的工作频率,代码如下:

void TIM2_Init(void)
{
    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
    /*  Enable Timer2 clock.  */
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);/*  Configure Timer2 --Clock Frequency is 84MHz  */
    TIM_TimeBaseStructure.TIM_Period=83; TIM_TimeBaseStructure.TIM_Prescaler= 0x0;       
    TIM_TimeBaseStructure.TIM_ClockDivision = 0x0;    
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);  /*  Configure the trigger source for Timer2.  */TIM_SelectOutputTrigger(TIM2, TIM_TRGOSource_Update);
    TIM_Cmd(TIM2, ENABLE);//Enable Timer2.
}

前文的DAC已选用TIM2当触发源,此处TIM2的定时周期被配置为83,向上计数,不分频。CKS32F4xx系列的主频是168MHz,TIM2的时钟是84MHz,所以TIM2的更新频率是84M/(TIM_Period+1)/(TIM_Prescaler+1),即TIM2每隔1us触发一次DAC事件,不需要设置中断,当定时器向上计数至指定值时,产生Update事件,同时触发DAC把DHRx寄存器的数据转移到DORx,开始进行转换。由于正弦波数组是100个采样点,可得正弦波的输出频率为:

(4)DMA配置

该部分主要完成数据的传输,代码如下:

void DMA_InitForDAC(void)
{
    DMA_InitTypeDef  DMA_InitStructure;
    /*  Enable DMA1 clock.  */RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE);/*  Configure DMA1 Stream5 Channel_7 For DAC1  */
    DMA_InitStructure.DMA_Channel = DMA_Channel_7;  DMA_InitStructure.DMA_PeripheralBaseAdDMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)Sine12bit ;DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
    DMA_InitStructure.DMA_BufferSize = 100;
    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_FIFOMode = DMA_FIFOMode_Disable;      DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;DMA_Init(DMA1_Stream5, &DMA_InitStructure);DMA_Cmd(DMA1_Stream5, ENABLE); //Enable DMA1 Stream5.
}

需要注意的是,DAC->DHR12R1对应数据寄存器的地址,正弦波数组Sine12bit对应数据输入地址,DMA缓存的个数是单个正弦波周期对应的点数,DMA需工作在循环模式,由于正弦波数组Sine12bit定义为16位,那么涉及数据传输的变量都要配置成半字16位。经过上述的配置后,定时器TIM2每隔1us就会触发DMA搬运正弦波数组的一个数据到DAC通道1寄存器进行转换,每搬运100个数据即一个完整周期后,DMA开始循环,最终循环输出正弦波。

(5)主函数配置

本例程主函数主要对前文所述函数依次调用,程序编译下载至开发板,使用示波器测量PA4引脚即可查看输出10kHz的正弦波形,代码如下:

int main(void)   
{
    DAC1_GPIO_Init();
    TIM2_Init();
    DMA_InitForDAC();
    while (1);
}

来源:中科芯MCU

免责声明:本文为转载文章,转载此文目的在于传递更多信息,版权归原作者所有。本文所用视频、图片、文字如涉及作品版权问题,请联系小编进行处理(联系邮箱:cathy@eetrend.com)。

围观 30

任何实际的电子应用都会受到多个误差源的影响,这些误差源可以使得最精密的元器件偏离其数据手册所述的行为。当应用信号链没有内置机制来自我调整这些误差时,最大程度降低误差影响的唯一方法是测量误差并系统地予以校准。

开环系统为了实现所需的性能,不使用输出来调整输入端的控制操作,而在闭环系统中,输出依赖于系统的控制操作,系统可以自动实施校正以提高性能。大多数数模转换器(DAC)信号链是"设置后不管"类型的系统,其输出的精度依赖于信号链中每个模块的精度。"设置后不管"型系统是一种开环系统。对于需要高精度的开环系统,校准是推荐的并且极有可能需要。

我们将介绍两种类型的DAC信号链校准:一种是TempCal(工作温度校准),它能提供最佳水平的误差校正;另一种是SpecCal(使用规格进行校准),当无法使用TempCal时,它是有效的备选方案,但不如前者全面。

“如何成功校准开环DAC信号链?"

DAC类型

单极性电压DAC只能提供正输出或负输出。本文将以 AD5676R 为单极性DAC的例子,说明如何进行精确校准。相同的方法可用于对其他类型的DAC进行必要的调整。

双极性电压DAC(如 AD5766 )可以同时实现正输出和负输出。

电流输出DAC通常用于乘法配置(MDAC)以提供可变增益,它们通常需要外部放大器来缓冲固定电阻上产生的电压。

精密电流源DAC (IDAC),例如 AD5770R 和 LTC2662,是一种新类别的DAC,可以在预定义范围内精确设置输出电流,而无需任何额外的外部元器件。

DAC转换函数理论和内部误差

理想数模转换器产生的模拟输出电压或电流与输入数字码严格成比例,而与电源和基准电压变化等干扰性外部影响无关。

对于一个理想电压输出DAC,输入数字码单步增加

对应的输出增加称为LSB,定义如下:

“如何成功校准开环DAC信号链?"

其中:

(VREF+)和(VREF-)分别为正负基准电压。在某些情况下,(VREF-)等于地电压(0 V)。

n为DAC的分辨率,单位为位。

LSBSIZE (V) 是DAC输出的最小增量,单位为伏特。

这意味着,对于任何给定的输入码,一旦知道LSB,就应该能准确地预测DAC的电压输出。

“如何成功校准开环DAC信号链?"

在实践中,DAC输出的精度受到DAC增益和失调误差(内部误差)以及信号链中其他元器件件(系统级误差)的影响。例如,有些DAC集成了输出放大器,而有些DAC则需要外部放大器,这便可能成为额外的误差源。

在数据手册中,最相关的技术规格是在术语部分中定义。对于DAC,该部分列出了失调误差和增益误差等参数。

零电平误差衡量将零电平码(0x0000)载入DAC寄存器时的输出误差。

图1显示了失调和增益误差对单极性电压DAC的转换函数的影响。

增益误差衡量DAC的量程误差,如图1紫线所示。增益误差指DAC转换特性的斜率与理想值的偏差。理想DAC的转换特性以黑色显示。

失调误差是指转换函数线性区内实际输出和理想输出之间的差值,如图1蓝线所示。请注意,蓝色转换函数使用了插值方法以与y轴相交,得到负VOUT,从而确定失调误差。

“图1.单极性DAC的失调误差和增益误差的表示。"
图1.单极性DAC的失调误差和增益误差的表示

通过图4的蓝色曲线可以看到增益误差和失调误差的影响。根据其随温度变化而发生的变化,也可定义同样的参数。

  • 零点误差漂移衡量零点误差随温度的变化。

  • 增益误差温度系数衡量增益误差随温度的变化。

  • 失调误差漂移衡量失调误差随温度的变化。

温度变化对电子系统的精度有重要影响。虽然DAC的内部增益和失调误差通常相对于温度来指定,但系统中的其他元器件可能会对输出的总失调和增益产生影响。

因此,即使DAC的INL和DNL非常有竞争力,也要考虑其他误差,尤其是关于温度的误差。最新DAC指定总非调整误差(TUE)来衡量包括所有误差——即INL误差、失调误差、增量误差以及在电源电压和温度范围内的输出漂移——在内的总输出误差。TUE用%FSR表示。

当数据手册未指定DAC的TUE时,可以使用一种称为RSS或和方根的技术来计算TUE,这种技术可用来将不相关的误差源求和以进行误差分析。

“如何成功校准开环DAC信号链?"

还有其他较小的误差源,如输出漂移等,因为其相关影响较小,所以通常予以忽略。

系统中每个元器件的每个规格必须转换为相同的单位。这可以使用表2来完成。

“表2.单位转换矩阵"
表2.单位转换矩阵

TUE是一个很好的指标,可简明扼要地解释在所有内部误差的影响下,DC DAC输出的精度如何。但是,它没有考虑系统级误差,后者会根据DAC所在的信号链及其环境而不同。

值得注意的是,有些DAC的输出级内置缓冲器/放大器,在这种情况下,数据手册规格反映了二者的影响,将其作为内部误差一部分。

系统级误差

尝试分析给定应用的DAC信号链误差预算时,系统设计人员应考虑并验证不同元器件的贡献,关注系统预期的运行温度。根据最终应用,信号链可能有许多不同的构建模块,包括电源IC、缓冲器或放大器,以及不同类型的有源负载,这些都可能带来系统级误差。

基准电压源

每个DAC都需要依靠基准电压源来操作。基准电压源是影响DAC和整体信号链的精度的主要因素之一。

基准电压源的关键性能规格也是在基准电压源的单独数据手册中定义,例如 ADR45XX系列 ,或作为DAC数据手册的一部分来定义(如果器件内置基准电压源以供用户使用)。

压差有时也称为电源电压裕量,定义为能够使输出电压保持0.1%精度所需的输入电压与输出电压的最小电压差。

温度系数(TC或TCVOUT)指器件的输出电压变化与环境温度变化之间的关系,用25°C时的输出电压进行归一化处理。ADR4520/ADR4525/ADR4530/ADR4533/ADR4540/ADR4550 A级和B级的TCVOUT在下列三个温度下经过全面测试:−40°C、+25°C和+125°C。C级的TCVOUT在下列三个温度下全面测试:0°C、+25°C和+70°C。该参数使用以下两种方法指定。黑盒法是最常用的方法,会考虑整个温度范围的温度系数;而领结法可以计算+25°C时最差情况的斜率,因此对于在+25°C时进行校准的系统更加有用。

对于某些DAC,外部基准电压源的性能比集成基准电压源更好。基准电压直接影响转换函数,因此,该电压的任何变化都会导致转换函数的斜率(即增益)成比例地变化。

值得注意的是,有些DAC内置缓冲基准电压源,在这种情况下,数据手册规格反映了这些内部模块的影响,将其作为内部误差的一部分。

电压调整率

每个充当电源的独立IC都会定义电压调整率,表示输出响应输入的给定变化而发生的变化。这适用于电源、缓冲器和基准电压源IC,无论输入如何,这些器件都应当保持输出电压稳定。在数据手册中,电压调整率通常在环境温度下指定。

负载调整率

负载调整率定义为输出电压随负载电流变化而发生的增量变化。通常会缓冲电压输出,以减轻这种变化的影响。有些DAC可能不缓冲基准输入。因此,当数字码改变时,基准输入阻抗也会改变,导致基准电压改变。其对输出的影响一般很小,但在高精度应用中应当考虑。在数据手册中,负载调整率通常在环境温度下指定。

焊接热阻变化

焊接热阻(SHR)变化与基准电压源的关系最大。它指器件因进行回流焊而引起的输出电压永久变化,用输出电压百分比表示。欲了解更多信息,请参阅ADR45xx系列的数据手册。一般而言,所有IC都会在某种程度上受到SHR变化的影响,但这并不总是可量化的,能否量化在很大程度上取决于应用的具体系统装配。

长期稳定性

长期稳定性定义输出电压随时间的变化,用ppm/1000小时来表示。PCB级老化处理可以提高应用的长期稳定性。

开环校准理论

DAC信号链简图如图2所示。黑框所示的模块显示了一个简化的开环信号链,而灰框所示的模块则是实现闭环信号链所需的额外器件的例子。

“图2.DAC信号链简图"
图2.DAC信号链简图

闭环方案需要其他元器件并通过软件操纵数字数据,才能提供更精确的输出。如果因为各种原因(空间、成本等)无法添加这些额外资源,开环解决方案仍然有效——只要它能提供所需的精度。本文解释如何进行开环校准,就是为了帮助应对这种情况。

理论上,通过校准消除增益和失调误差(其在没有外部影响的情况下是恒定的)是很简单的程序。DAC转换函数的线性区域可建模为由以下方程描述的直线:

“如何成功校准开环DAC信号链?"

其中:

y为输出。

m是计入增益误差后转换函数的斜率(如图1紫线所示)。

x为DAC输入。

c为失调电压(如图1蓝线所示)。

理想情况下,m始终为1,c始终为0。实践中会考虑DAC的增益和失调误差,一旦知道,就可以在DAC输入端进行校正,实现更接近理想DAC输出的数字。将数字DAC输入乘以增益误差的倒数,便可消除增益误差。将测得的失调误差的相反数增加到数字DAC输入,便可消除失调误差。

下面的公式显示了如何计算正确的DAC输入以产生所需的电压:

“如何成功校准开环DAC信号链?"

其中:

“如何成功校准开环DAC信号链?"

“如何成功校准开环DAC信号链?"

注意,失调误差可以为正,也可以为负。

如何成功校准DAC信号链

本节以AD5676R为例说明如何实际校准DAC信号链中的失调和增益。所有测量都使用 EVAL-AD5676 评估套件,并且使能AD5676R内部基准电压源。EVAL-AD5676板和测量设置均为我们在示例中测量的信号链的一部分。该信号链的每个元器件(电路板上的电源IC、AD5676R、布局和连接器引入的寄生效应等)都会贡献系统误差。我们的意图是说明如何校准该系统,从而为任何其他系统提供范例。

使用 EVAL-SDP-CB1Z Blackfin® SDP控制板(SDP-B) 来与EVAL-AD5676评估套件上的AD5676R通信,并且使用8位DMM来测量VOUT0的输出电压。使用一个气候箱来控制整个系统(由EVAL-SDP-CB1Z、EVAL-AD5676和内置基准电压源的AD5676R组成)的温度。

EVAL-AD5676按照用户指南所述上电,链路配置如表3所示。

“表3.用于所述测量的EVAL-AD5676评估板跳线配置"
表3.用于所述测量的EVAL-AD5676评估板跳线配置

首先评估不同温度下无校准(NoCal)的信号链误差。考虑特定输入码的理想值和测量值的LSB差异,计算输出误差。此误差包括DAC和EVAL-AD5676板上整体信号链的内部误差和外部误差。无校准的输出误差如图3所示。

“图3.EVAL-AD5676输出误差(LSB),无校准"
图3.EVAL-AD5676输出误差(LSB),无校准

计算失调和增益误差所需的信息以及相应的校正码,位于转换函数中。为此需要两个点:一个数据点接近零点(ZSLIN),另一个接近满量程(FSLIN)。背后的道理是要在DAC的线性区域中工作。此信息通常与INL和DNL规格一起提供,最有可能在规格表的尾注中。例如,对于AD5676R,线性区域是从数字码256到数字码65280。

图4解释了DAC的线性区域。

“图4.单极性电压DAC的转换函数和误差"
图4.单极性电压DAC的转换函数和误差

一旦确定ZSLIN和FSLIN码,我们便可收集校准所需的测量结果,即在这两个数字码的DAC电压输出(ZSLIN处的VOUT和FSLIN处的VOUT),加上这之间的其他几个数字码(¼量程、中间量程和¾量程)。

应在应用的工作温度下收集测量结果。如果这不可能,一旦在环境温度时收集到这两个主要数据点,便可使用信号链中器件的数据手册来推导所需的信息。

信号链中的每个器件都会贡献误差,每片板都不相同,因此应该单独校准。

TempCal:工作温度校准

通过测量应用环境在工作温度时的误差,并在写入DAC以更新输出时进行系统校正,可以实现最佳水平的校准。

为了使用这种方法校准DAC,在系统的预期工作温度下,测量数字码ZSLIN和FSLIN对应的DAC输出。构建转换函数如下:

“如何成功校准开环DAC信号链?"

“如何成功校准开环DAC信号链?"

“如何成功校准开环DAC信号链?"

“如何成功校准开环DAC信号链?"

“如何成功校准开环DAC信号链?"

“如何成功校准开环DAC信号链?"

其中:

VOE失调误差(V)

VFS,LIN,ACT = FSLIN的实际输出

VZS,LIN,ACT = ZSLIN的实际输出

VFS,LIN,IDEAL 的理想输出

VZS,LIN,IDEAL = ZSLIN的理想输出

注意,失调误差可以为正,也可以为负。

图5显示了EVAL-AD5676评估套件采用TempCal方法所实现的输出误差。

“如何成功校准开环DAC信号链?"

图5.不同温度下使用TempCal的系统输出误差(LSB)。

SpecCal:使用规格进行校准

如果无法测量应用环境在工作温度时的误差,使用AD5676R数据手册和环境温度时校准的DAC转换函数仍可实现高水平的校准。

为了使用这种方法校准DAC,应在环境温度下测量数字码ZSLIN和FSLIN对应的DAC输出。通过计算环境温度下的增益和失调误差并应用公式14,按照TempCal部分所述构建转换函数。

“如何成功校准开环DAC信号链?"

其中:

GEamb = 环境温度下的增益误差

VOE,amb = 环境温度下的失调误差(V)

在环境温度下校准DAC信号链可解决系统级误差。但是,温度变化导致的外部误差变化未予考虑;因此,这种校准方法不如TempCal方法精确。

工作温度变化导致的DAC内部误差(即失调和增益误差)漂移,可以使用数据手册规格来解决。这就是我们所说的SpecCal。失调误差漂移的典型值列在AD5676R数据手册的技术规格表中,失调误差与温度关系的典型性能参数(TPC)表示误差漂移的方向,这取决于环境温度是提高还是降低。

“如何成功校准开环DAC信号链?"

温度导致的增益误差变化由增益误差与温度关系的TPC表示。从图中确定增益误差的% FSR,然后应用公式16。

“如何成功校准开环DAC信号链?"

估算出工作温度下的失调误差和增益误差后,我们便可使用公式17来确定SpecCal输出对应的输入码。

“如何成功校准开环DAC信号链?"

其中:

“如何成功校准开环DAC信号链?"

图6显示了EVAL-AD5676评估套件采用SpecCal方法所实现的输出误差。

“图6.不同温度下使用SpecCal的系统输出误差(LSB)。"
图6.不同温度下使用SpecCal的系统输出误差(LSB)。

此例中使用了内部基准电压源。外部基准电压源可能会增加整体误差。基准电压源引起的误差可利用基准电压源数据手册并考虑目标温度时的基准电压漂移来解决。基准电压的变化会改变实际输出范围,从而改变LSB大小。使用外部基准电压源应能解决此问题。温度与输出电压关系的TPC可用来确定基准电压漂移引起的输出范围变化。

“如何成功校准开环DAC信号链?"

其中:

“如何成功校准开环DAC信号链?"

结论

本文概述了DAC信号链误差的一些主要原因,包括数据手册中定义的DAC内部误差,以及随系统而变化且开环应用必须予以考虑的系统级误差。

本文讨论了两种校准方法:一种用于DAC可以在系统工作温度下进行校准的情况,另一种用于无法在工作温度下进行校准,但可以在环境温度下进行测量的情况。第二种方法使用信号链中DAC和其他IC的数据手册中提供的TPC和技术规格来解决增益和失调误差漂移。

TempCal方法可以实现比SpecCal好得多的精度。例如,对于50°C时的EVAL-AD5676板,图7显示TempCal方法实现的精度非常接近理想精度,而SpecCal方法相对于NoCal数据仍然有一定的改进。

“图7.NoCal、SpecCal和50°C
图7.NoCal、SpecCal和50°C TempCal的系统输出误差(LSB)

温度变化对电子系统的精度有重要影响。在系统工作温度进行校准可以消除大部分误差。如果这不可能,可以使用DAC和其他IC的数据手册中提供的信息来解决温度变化问题,实现可接受的精度。

来源:亚德诺半导体
免责声明:本文为转载文章,转载此文目的在于传递更多信息,版权归原作者所有。本文所用视频、图片、文字如涉及作品版权问题,请联系小编进行处理(联系邮箱:cathy@eetrend.com)。

围观 81

采集时间

采集时间是从释放保持状态(由采样-保持输入电路执行)到采样电容电压稳定至新输入值的1 LSB范围之内所需要的时间。采集时间(Tacq)的公式如下:

“ADC和DAC常用的56个技术术语"

混叠

根据采样定理,超过奈奎斯特频率的输入信号频率为“混叠”频率。也就是说,这些频率被“折叠”或复制到奈奎斯特频率附近的其它频谱位置。为防止混叠,必须对所有有害信号进行足够的衰减,使得ADC不对其进行数字化。欠采样时,混叠可作为一种有利条件。

孔径延迟

ADC中的孔径延迟(tAD)是从时钟信号的采样沿(下图中为时钟信号的上升沿)到发生采样时之间的时间间隔。当ADC的跟踪-保持切换到保持状态时,进行采样。

“ADC和DAC常用的56个技术术语”

孔径抖动

孔径抖动 (tAJ) 是指采样与采样之间孔径延迟的变化,如图所示。典型的ADC孔径抖动值远远小于孔径延迟值。

二进制编码(单极性)

准二进制是一种常用于单极性信号的编码方法。二进制码(零至满幅)的范围为从全0 (00...000)到全1的正向满幅值(11...111)。中间值由一个1 (MSB)后边跟全0 (10...000)表示。该编码类似于偏移二进制编码,后者支持正和负双极性传递函数。

双极性输入

术语“双极性”表示信号在某个基准电平上、下摆动。单端系统中,输入通常以模拟地为基准,所以双极性信号为在地电平上、下摆动的信号。差分系统中,信号不以地为基准,而是正输入以负输入为参考,双极性信号则指正输入信号能够高于和低于负输入信号。

共模抑制(CMRR)

共模抑制是指器件抑制两路输入的共模信号的能力。共模信号可以是交流或直流信号,或者两者的组合。共模抑制比(CMRR)是指差分信号增益与共模信号增益之比。CMRR通常以分贝(dB)为单位表示。

串扰(Crosstalk)

串扰表示每路模拟输入与其它模拟输入的隔离程度。对于具有多路输入通道的ADC,串扰指从一路模拟输入信号耦合到另一路模拟输入的信号总量,该值通常以分贝(dB)为单位表示;对于具有多路输出通道的DAC,串扰是指一路DAC输出更新时在另一路DAC输出端产生的噪声总量。

微分非线性(DNL)误差

对于ADC,触发任意两个连续输出编码的模拟输入电平之差应为1 LSB (DNL = 0),实际电平差相对于1 LSB的偏差被定义为DNL。对于DAC,DNL误差为连续DAC编码的理想与实测输出响应之差。理想DAC响应的模拟输出值应严格相差一个编码(LSB)(DNL = 0)。(DNL指标大于或等于1LSB保证单调性。)(见“单调”。)

“ADC和DAC常用的56个技术术语”

数字馈通

数字馈通是指DAC数字控制信号变化时,在DAC输出端产生的噪声。在下图中,DAC输出端的馈通是串行时钟信号噪声的结果。

“ADC和DAC常用的56个技术术语”

动态范围

动态范围定义为器件本底噪声至其规定最大输出电平之间的范围,通常以dB表示。ADC的动态范围为ADC能够分辨的信号幅值范围;如果ADC的动态范围为60dB,则其可分辨的信号幅值为x至1000x。对于通信应用,信号强度变化范围非常大,动态范围非常重要。如果信号太大,则会造成ADC输入过量程;如果信号太小,则会被淹没在转换器的量化噪声中。

有效位数(ENOB)

ENOB表示一个ADC在特定输入频率和采样率下的动态性能。理想ADC的误差仅包含量化噪声。当输入频率升高时,总体噪声(尤其是失真分量)也增大,因此降低ENOB和SINAD(参见“信号与噪声+失真比(SINAD)”)。满幅、正弦输入波形的ENOB由下式计算:

“ADC和DAC常用的56个技术术语"

加载-感应输出

一种测量技术,在电路的远端点加载电压(或电流),然后测量(检测)产生的电流(或电压)。例如,带有集成输出放大器的DAC有时就包含加载-感应输出。输出放大器可提供反相输入用于外部连接,反馈通路必须通过外部形成闭环。

全功率带宽(FPBW)

ADC工作时施加的模拟输入信号等于或接近转换器的规定满幅电压。然后将输入频率提高到某个频率,使数字转换结果的幅值降低3dB。该输入频率即为全功率带宽。

满幅(FS)误差

满幅误差为触发跳变至满幅编码的实际值与理想模拟满幅跳变值之差。满幅误差等于“失调误差+增益误差”,如下图所示。

“ADC和DAC常用的56个技术术语”

FS增益误差(DAC)

数/模转换器(DAC)的满幅增益误差为实际与理想输出跨距之差。实际跨距为输入设置为全1时与输入设置为全0时的输出之差。所有数据转换器的满幅增益误差都与选择用于测量增益误差的基准有关。

增益误差

ADC或DAC的增益误差表示实际传递函数的斜率与理想传递函数的斜率的匹配程度。增益误差通常表示为LSB或满幅范围的百分比(%FSR),可通过硬件或软件校准进行消除。增益误差等于满幅误差减去失调误差。

“ADC和DAC常用的56个技术术语”

增益误差漂移

增益误差漂移指环境温度引起的增益误差变化,通常表示为ppm/°C。

增益一致性

增益一致性表示多通道ADC中所有通道增益的匹配程度。为计算增益的一致性,向所有通道施加相同的输入信号,然后记录最大的增益偏差,通常用dB表示。

尖峰脉冲

尖峰脉冲指MSB跳变时在DAC输出端产生的电压瞬态振荡,通常表示为nV?s,等于电压-时间曲线下方的面积。

谐波

周期信号的谐波为信号基频整数倍的正弦分量。

积分非线性(INL)误差

对于数据转换器,积分非线性(INL)是实际传递函数与传递函数直线的偏差。消除失调误差和增益误差后,该直线为最佳拟合直线或传递函数端点之间的直线。INL往往被称为“相对精度”。

“ADC和DAC常用的56个技术术语”

互调失真(IMD)

IMD是指由于电路或器件的非线性产生的原始信号中并不存在的新频率分量的现象。IMD包括谐波失真和双音失真。测量时,将其作为将所选交调产物(即IM2至IM5)的总功率与两个输入信号(f1和f2)的总功率之比。2阶至5阶交调产物如下:

·2阶交调产物(IM2):f1 + f2、f2 - f1

·3阶交调产物(IM3):2 x f1 - f2、2 x f2 - f1、2 x f1 + f2、2 x f2 + f1

·4阶交调产物(IM4):3 x f1 - f2、3 x f2 - f1、3 x f1 + f2、3 x f2 + f1

·5阶交调产物(IM5):3 x f1 - 2 x f2、3 x f2 - 2 x f1、3 x f1 + 2 x f2、3 x f2 + 2 x f1

最低有效位(LSB)

在二进制数中,LSB为最低加权位。通常,LSB为最右侧的位。对于ADC或DAC,LSB的权重等于转换器的满幅电压范围除以2N,其中N为转换器的分辨率。对于12位ADC,如果满幅电压为2.5V,则1LSB = (2.5V/2^12) = 610μV

MSB跳变

MSB跳变(中间刻度点)时,MSB由低电平变为高电平,其它所有数据位则由高电平变为低电平;或者MSB由高电平变为低电平,而其它数据位由低电平变为高电平。例如,01111111变为10000000即为MSB跳变。MSB跳变往往产生最严重的开关噪声(见尖峰脉冲)。

单调

在序列中,如果对于每个n,Pn + 1总是大于或等于Pn,则说该序列单调增大;类似地,如果对于每个n,Pn + 1总是小于或等于Pn,则说该序列单调减小。对于DAC,如果模拟输出总是随DAC编码输入的增大而增大,则说该DAC是单调的;对于ADC,如果数字输出编码总是随模拟输入的增大而增大,则说该ADC是单调的。如果转换器的DNL误差不大于±1LSB,则能够保证单调。

最高有效位(MSB)

在二进制数中,MSB为最高加权位。通常,MSB为最左侧的位。

乘法DAC (MDAC)

乘法DAC允许将交流信号施加至基准输入。通过将感兴趣的信号连接至基准输入,并利用DAC编码缩放信号,DAC可用作数字衰减器。

无丢失编码

当斜线上升信号施加至ADC的模拟输入端时,如果ADC产生所有可能的数字编码,则该ADC无丢失编码。

奈奎斯特频率

奈奎斯特定理说明:ADC的采样率必须至少为信号最大带宽的两倍才能无失真地完整恢复模拟信号。该最大带宽被称为奈奎斯特频率。

偏移二进制编码

偏移二进制是一种常用于双极性信号的编码方法。在偏移二进制编码中,负向最大值(负向满幅值)用全0 (00...000)表示,正向最大值(正向满幅值)用全1 (11...111)表示。零幅由一个1 (MSB)后边跟全0 (10...000)表示。该方法与标准二进制类似,后者常用于单极性信号(参见二进制编码,单极性)。

失调误差(双极性)

双极性转换器失调误差的测量与单极性转换器失调误差的测量类似,但在双极性传递函数的中间点测量零幅处的误差(参见失调误差单极性)

失调误差(单极性)

失调误差常称为“零幅”误差,指在某个工作点,实际传递函数与理想传递函数的差异。对于理想数据转换器,第一次跳变发生在零点以上0.5LSB处。对于ADC,向模拟输入端施加零幅电压并增加,直到发生第一次跳变;对于DAC,失调误差为输入编码为全0时的模拟输出。

“ADC和DAC常用的56个技术术语"

失调误差漂移

失调误差漂移指环境温度引起的失调误差变化,通常表示为ppm/°C。

过采样

对于ADC,如果采样模拟输入的频率远远高于奈奎斯特频率,则称为过采样。过采样有效降低了噪底,所以提高ADC的动态范围。提高动态范围又进而提高了分辨率。过采样是Σ-Δ ADC的基础。

相位匹配

相位匹配表示施加至多通道ADC所有通道的完全相同信号的相位匹配程度。相位匹配指所有通道中的最大相位偏移,通常用度表示。

电源抑制比(PSRR)

电源抑制比(PSRR)指电源电压变化与满幅误差变化之比,以dB表示。

量化误差

对于ADC,量化误差定义为实际模拟输入与表示该值的数字编码之间的差异(参见“量化”)。

比例测量

施加至ADC电压基准输入的电压不是恒定电压,而是与施加至变送器(即负载单元或电桥)的信号成比例。这种类型的测量称为比例测量,它消除了基准电压变化引起的所有误差。下图中使用电阻桥的方法就是比例测量的一个例子。

“ADC和DAC常用的56个技术术语"

分辨率

ADC分辨率为用于表示模拟输入信号的位数。为了更准确地复现模拟信号,就必须提高分辨率。使用较高分辨率的ADC也降低量化误差。对于DAC,分辨率与此类似:DAC的分辨率越高,增大编码时在模拟输出端产生的步进越小。

有效值(RMS)

交流波形的RMS值为有效直流值或该信号的等效直流信号。计算交流波形的RMS值时,先对交流波形进行平方以及时间平均,然后取其平方根。对于正弦波,RMS值为峰值的 2/2 (或0.707)倍,也就是峰-峰值的0.354倍。

采样率/频率

样率或采样频率以“采样/秒”(sps)表示,指ADC采集(采样)模拟输入的速率。对于每次转换执行一次采样的ADC(如SAR、Flash ADC或流水线型ADC),采样速率也指吞吐率。对于Σ-Δ ADC,采样率一般远远高于数据输出频率。

建立时间

对于DAC,建立时间是从更新(改变)其输出值的命令到输出达到最终值(在规定百分比之内)之间的时间间隔。建立时间受输出放大器的摆率和放大器振铃及信号过冲总量的影响。对于ADC,采样电容电压稳定至1 LSB所需的时间小于转换器的捕获时间至关重要。

信纳比(SINAD)

SINAD是正弦波(ADC的输入,或DAC恢复的输出)的RMS值与转换器噪声加失真(无正弦波)的RMS值之比。RMS噪声加失真包括奈奎斯特频率以下除基波和直流失调以外的所有频谱成分。SINAD通常表示为dB。

信噪比(SNR)

信噪比(SNR)是给定时间点有用信号幅度与噪声幅度之比,该值越大越好。对于由数字采样完美重构的波形,理论上的最大SNR为满幅模拟输入(RMS值)与RMS量化误差(剩余误差)之比。理想情况下,理论上的最小ADC噪声仅包含量化误差,并直接由ADC的分辨率(N位)确定:

(除量化噪声外,实际ADC也产生热噪声、基准噪声、时钟抖动等。)

带符号二进制编码

带符号二进制编码方法中,MSB表示二进制数的符号(正或负)。所以,-2的8位表示法为10000010,+2的表示法为00000010。

摆率

摆率是DAC输出变化的最大速率,或者不会造成ADC数字输出错误的输入变化的最大速率。对于带有输出放大器的DAC,规定摆率通常是放大器的摆率。

小信号带宽(SSBW)

为测量小信号带宽,向ADC施加一个幅值足够小的模拟输入信号,其摆率不会限制ADC的性能。然后,扫描输入频率,直到数字转换结果的幅值降低3dB。小信号带宽往往受限于相关采样-保持放大器的性能。

无杂散动态范围(SFDR)

无杂散动态范围(SFDR)是基波(信号成分最大值)RMS幅值与第二大杂散成份(不包含直流失调)的RMS值之比。SFDR以相对于载波的分贝(dBc)表示。

总谐波失真(THD)

THD测量信号的失真成分,用相对于基波的分贝(dB)表示。对于ADC,总谐波失真(THD)是所选输入信号谐波的RMS之和与基波之比。测量时,只有在奈奎斯特限值之内的谐波被包含在内。

跟踪-保持

跟踪-保持往往也被称为“采样-保持”,指ADC的输入采样电路。跟踪-保持输入的最基本表示形式是模拟开关和电容(见图)。开关闭合时,电路处于“跟踪”模式;开关开路时,采样电容保持输入的最后瞬态值,电路处于“保持”模式。

“ADC和DAC常用的56个技术术语"

转换噪声

转换噪声指引起ADC输出在相邻输出编码之间切换的输入电压变化范围。当增大模拟输入电压时,由于相关瞬态噪声的原因,触发每个编码发生跳变(编码边缘)的电压是不确定的。

二进制补码编码

二进制补码编码方法用于正数和负数编码,简化加法和减法计算。该编码方法中,-2的8位表示法为11111110,+2的表示法为00000010。

欠采样

欠采样技术中,ADC采样率低于模拟输入频率,该条件下将引起混叠。根据奈奎斯特定理,自然知道欠采样将丢失信号信息。然而,如果对输入信号进行正确滤波,以及正确选择模拟输入和采样频率,则可将包含信号信息的混叠成分从较高频率搬移至较低频率,然后进行转换。该方法有效地将ADC用作下变频器,将较高带宽信号搬移到ADC的有效带宽。要想该技术取得成功,ADC跟踪-保持电路的带宽必须能够处理预期的最高频率信号。

单极性

对于单端模拟输入ADC,单极性信号输入范围为零幅(通常为地)至满幅(通常为基准电压);对于差分输入ADC,信号输入范围为零幅至满幅,以正输入相当于负输入测量输入范围。

零幅误差

参见失调误差(单极性)。

来源:高速射频百花潭
免责声明:本文为转载文章,转载此文目的在于传递更多信息,版权归原作者所有。本文所用视频、图片、文字如涉及作品版权问题,请联系小编进行处理(联系邮箱:
cathy@eetrend.com)。

围观 44

STM32 的 DAC 模块(数字/模拟转换模块)是 12 位数字输入,电压输出型的DAC。

DAC 可以配置为 8 位或 12 位模式,也可以与 DMA 控制器配合使用。

DAC工作在 12 位模式时,数据可以设置成左对齐或右对齐。

DAC 模块有 2 个输出通道,每个通道都有单独的转换器。

在双DAC模式下,2个通道可以独立地进行转换,也可以同时进行转换并同步地更新 2 个通道的输出。

DAC可以通过引脚输入参考电压 VREF+以获得更精确的转换结果。

STM32 的 DAC 模块主要特点有:

① 2 个 DAC 转换器:每个转换器对应 1 个输出通道
② 8 位或者 12 位单调输出
③ 12 位模式下数据左对齐或者右对齐
④ 同步更新功能
⑤ 噪声波形生成
⑥ 三角波形生成
⑦ 双 DAC 通道同时或者分别转换
⑧ 每个通道都有 DMA 功能

使用库函数的方法来设置 DAC 模块的通道 1 来输出模拟电压,其详细设置步骤如下:

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

STM32F103ZET6 的 DAC 通道 1 在 PA4 上,所以,我们先要使能 PORTA 的时钟,然后设置 PA4 为模拟输入。DAC 本身是输出,但是为什么端口要设置为模拟输入模式呢?因为一但使能 DACx 通道之后,相应的 GPIO 引脚(PA4 或者 PA5)会自动与 DAC 的模拟输出相连,设置为输入,是为了避免额外的干扰。

使能 GPIOA 时钟:

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE ); 
//使能 PORTA 时钟

设置 PA1 为模拟输入只需要设置初始化参数即可:

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

2)使能 DAC1 时钟。

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

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

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

该部分设置全部通过 DAC_CR 设置实现,包括:DAC 通道 1 使能、DAC 通道 1 输出缓存关闭、不使用触发、不使用波形发生器等设置。这里 DMA 初始化是通过函数 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_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);
//使能 DAC1

5)设置 DAC 的输出值。

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

DAC_SetChannel1Data(DAC_Align_12b_R, 0);

第一个参数设置对齐方式,可以为 12 位右对齐 DAC_Align_12b_R,12 位左对齐DAC_Align_12b_L 以及 8 位右对齐 DAC_Align_8b_R 方式。第二个参数就是 DAC 的输入值了,这个很好理解,初始化设置为 0。

这里,还可以读出 DAC 的数值,函数是:

DAC_GetDataOutputValue(DAC_Channel_1);

以下为代码:

//DAC通道1输出初始化
void Dac1_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    DAC_InitTypeDef DAC_InitType;
    
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE );
    //使能PORTA通道时钟
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE );
    //使能DAC通道时钟
    
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
    // 端口配置
     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
     //模拟输入
     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
     GPIO_Init(GPIOA, &GPIO_InitStructure);
    GPIO_SetBits(GPIOA,GPIO_Pin_4);
    //PA.4 输出高
    
    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); 
    //使能DAC1
    DAC_SetChannel1Data(DAC_Align_12b_R, 0);
    //12位右对齐数据格式设置DAC值
}
//设置通道1输出电压
//vol:0~3300,代表0~3.3V
void Dac1_Set_Vol(u16 vol)
{
    float temp=vol;
    temp/=1000;
    temp=temp*4096/3.3;
    DAC_SetChannel1Data(DAC_Align_12b_R,temp);
    //12位右对齐数据格式设置DAC值
}

在使用的过程中,只需要调用 DAC_SetChannel1Data(DAC_Align_12b_R,temp);该函数就可以随意设定需要输出的电压值。

本文出处:http://blog.chinaunix.net/uid-24219701-id-4101802.html
免责声明:本文为转载文章,转载此文目的在于传递更多信息,版权归原作者所有。

围观 140

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

STM32 的 DAC 模块主要特点有:

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

② 8 位或者 12 位单调输出

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

④ 同步更新功能

⑤ 噪声波形生成

⑥ 三角波形生成

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

⑧ 每个通道都有 DMA 功能

使用库函数的方法来设置 DAC 模块的通道 1 来输出模拟电压,其详细设置步骤如下:

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

STM32F103ZET6 的 DAC 通道 1 在 PA4 上,所以,我们先要使能 PORTA 的时钟,然后设置 PA4 为模拟输入。DAC 本身是输出,但是为什么端口要设置为模拟输入模式呢?因为一但使能 DACx 通道之后,相应的 GPIO 引脚(PA4 或者 PA5)会自动与 DAC 的模拟输出相连,设置为输入,是为了避免额外的干扰。

使能 GPIOA 时钟:

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE ); //使能 PORTA 时钟

设置 PA1 为模拟输入只需要设置初始化参数即可:

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

2)使能 DAC1 时钟。

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

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

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

该部分设置全部通过 DAC_CR 设置实现,包括:DAC 通道 1 使能、DAC 通道 1 输出缓存关闭、不使用触发、不使用波形发生器等设置。这里 DMA 初始化是通过函数 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_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); //使能 DAC1

5)设置 DAC 的输出值。

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

DAC_SetChannel1Data(DAC_Align_12b_R, 0);

第一个参数设置对齐方式,可以为 12 位右对齐 DAC_Align_12b_R,12 位左对齐DAC_Align_12b_L 以及 8 位右对齐 DAC_Align_8b_R 方式。第二个参数就是 DAC 的输入值了,这个很好理解,初始化设置为 0。

这里,还可以读出 DAC 的数值,函数是:

DAC_GetDataOutputValue(DAC_Channel_1);

以下为代码:

//DAC通道1输出初始化
void Dac1_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
DAC_InitTypeDef DAC_InitType;

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE ); //使能PORTA通道时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE ); //使能DAC通道时钟

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4; // 端口配置
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; //模拟输入
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_SetBits(GPIOA,GPIO_Pin_4) ;//PA.4 输出高

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); //使能DAC1
DAC_SetChannel1Data(DAC_Align_12b_R, 0); //12位右对齐数据格式设置DAC值
}
//设置通道1输出电压
//vol:0~3300,代表0~3.3V
void Dac1_Set_Vol(u16 vol)
{
float temp=vol;
temp/=1000;
temp=temp*4096/3.3;
DAC_SetChannel1Data(DAC_Align_12b_R,temp);//12位右对齐数据格式设置DAC值
}
在使用的过程中,只需要调用 DAC_SetChannel1Data(DAC_Align_12b_R,temp);该函数就可以随意设定需要输出的电压值。

本文转自:http://blog.chinaunix.net/uid-24219701-id-4101802.html

围观 852

有客户需要用到高精度的DAC模块,MM32L0系列产品内部没有集成DAC模块,考虑到外接DAC芯片会增加成本,所以在本实验中将为大家介绍使用PWM输出,经过简单的变换电路即可实现DAC,这将大量降低电子设备的成本、减少体积,并提高精度。本实验在PWM到DAC转换关系的理论分析基础上,设计出输出为0~5V电压的DAC。

MM32L0系列产品包含1个高级控制定时器、5个通用定时器(1个32 位定时器和5个16 位定时器),以及 2个看门狗定时器和1个系统嘀嗒定时器。

每个定时器都有 PWM 输出或单脉冲模式输出,所以MM32L0系列产品任意一款型号都可以用PWM做DAC输出功能。

PWM波形的分段函数:

MM32 基于PWM做DAC输出设计

其中:k为谐波次数,N是PWM波一个周期的计数脉冲个数,T是单片机中计数脉冲的基本周期,即MCU每隔T时间记一次数(计数器的值增加或者减少1),t为时间, n是PWM波一个周期中高电平的计数脉冲个数,VH和VL分别是PWM波中高低电平的电压值。

PWM的高低电平分别为VH和VL,理想的情况VL等于0,但是实际中一般不等于0,所以用户在处理PWM的VL时需注意,出现较大误差一般都是因为这个地方。

将上述函数展开成傅里叶级数得到:

MM32 基于PWM做DAC输出设计

从上式可以看出,上式中第1个方括弧为直流分量,第2项为1次谐波分量,第3项为大于1次的高次谐波分量。上式中的直流分量与n成线性关系,并随着n从0到N,直流分量从VL到VL+VH之间变化,这正是电压输出的DAC所需要的。因此,如果能把式中除直流分量的谐波过滤掉,则可以得到从PWM波到电压输出DAC的转换,即:PWM波可以通过一个低通滤波器进行解调。式中的第2项的幅度和相角与n有关,频率为1/(NT),该频率是设计低通滤波器的依据。如果能把1次谐波很好过滤掉,则高次谐波就应该基本不存在了。

在DAC的应用中,分辨率是一个很重要的参数,傅里叶级数公式中的分辨率计算直接与N和n的可能变化有关:

MM32 基于PWM做DAC输出设计

从上式中可看出:
N越大DAC的分辨率越高,但是NT也越大,即 PWM的周期或者傅里叶级数公式中的1次谐波周期也越大,相当于1次谐波的频率也越低,需要截止频率很低的低通滤波器,DAC输出的滞后也将增加。为了使T减少,即减少单片机的计数脉冲宽度(这往往需要提高单片机的工作频率),达到不降低1次谐波频率的前提下提高精度。

MM32L0系列产品最高工作频率可达 48MHz,TIM2是32位的定时器,PWM频率计算公式:
Fpwm = 48M / ((arr+1)*(psc+1))(单位:Hz)
公式中psc就是分频系数,arr就是计数值。预分频器可以将计数器的时钟频率按 1 到 65536 之间的任意值分频。计数值可以从1-4294967295(2的32次方减1)中任意选取。

本次实验采用两阶RC滤波,使用两个电阻和两个电容组成一个具有DAC功能的引脚,PB10是32位的定时器TIM2_CH3通道,PA3和PA4两个通道分别去采集1阶RC滤波和2阶RC滤波后的电压值。

MM32 基于PWM做DAC输出设计

R29和C10的具体参数可根据傅里叶级数公式的第2部分的一次谐波频率来选择,实际应用中一般选择阻容滤波器的截止频率为傅里叶级数公式的基波频率的1/4左右。

RC滤波器的截止频率计算公式:

f = 1/(2πRC)

滤波器是频率选择电路,只允许输入信号中的某些频率成分通过,而阻止其他频率成分到达输出端。在电路中需要考虑到芯片引脚输出端到RC滤波电路之间的存在阻值等问题,上图中的电阻和电容值需要根据实际情况计算调整。

PB10引脚能将不同占空比的PWM信号转换为不同电压值的模拟信号。为了能更准确的获取DAC转换值,电路中还使用了2个ADC通道用来检测DAC转换值。在转换过程中PWM信号频率越快DAC输出的电压值越稳定,PWM位数越高DAC输出的电压值精度越高,32位PWM比16位PWM精度高。

实验程序:

TIM2定时器配置:
u32 OutCnt;

void InitTIM2_PWM(u16 t1, u16 t2, u16 psc)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //TIM2_CH3
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11; //TIM2_CH4
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);

GPIO_PinAFConfig(GPIOB, GPIO_PinSource10,GPIO_AF_2);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource11,GPIO_AF_2);

TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_TimeBaseStructure.TIM_Prescaler =psc;
TIM_TimeBaseStructure.TIM_Period = t1;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);

TIM_OCInitTypeDef TIM_OCInitStructure;
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = 0;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;

TIM_OC3Init(TIM2, &TIM_OCInitStructure);
TIM_OC4Init(TIM2, &TIM_OCInitStructure);

TIM_OCInitStructure.TIM_Pulse = t2;
TIM_OC3Init(TIM2, &TIM_OCInitStructure);
TIM_OC3PreloadConfig(TIM2, TIM_OCPreload_Enable);

TIM_OCInitStructure.TIM_Pulse = t2;
TIM_OC4Init(TIM2, &TIM_OCInitStructure);
TIM_OC4PreloadConfig(TIM2, TIM_OCPreload_Enable);

TIM_ARRPreloadConfig(TIM2, ENABLE);
TIM_Cmd(TIM2, ENABLE);
}

获取 SysTick 计数器的值:
u32 GetSysTickCount(void)
{
return SysTick_Count;
}

设置 SysTick 重装载值:
void SysTick_Configuration(void)
{
SysTick_Config(48000);
}

SysTick中断配置:
u32 pwm = 150;
void SysTick_Handler(void)
{
if (SysTick_Count ++ > 500)
{
SysTick_Count = 0;
InitTIM2_PWM(1024, pwm, 1);
}
}

主函数:
int main(void)
{
SystemInit();
SysTick_Count = 0;
SysTick_Configuration();
while(1)
{
}
}

操作方法:按照上述硬件搭建实验环境后,上电接上调试器,进入Debug状态,在IAR的Live watch窗口修改pwm值可以实现占空比可调。

实验结果:

MM32 基于PWM做DAC输出设计MM32 基于PWM做DAC输出设计

根据实验现象:
从PWM到DAC输出的信号处理有许多电路实现方法,上述电路实现方法DAC输出的负载能力比较差,适合具有高输入阻抗的后续电路连接,对精度和负载能力要求较高的场合,建议增加基准电压、负载驱动等电路。在MCU的应用中还可以通过软件的方法进行精度调整和误差的进一步校正。

PWM 外设结合本电路所实现DAC 有非常好的差分非线性(DNL)、线性度(INL),8位分辨率的情况下,PWM 频率为50KHz,实测精度在 0.5LSB 以内,适合于输出低频、高精度的模拟信号。

转自: 灵动微电子

围观 1101
订阅 RSS - DAC