(本文基于SYM32F4,部分参数说明参考标准库)
DAC简介
作用就是把输入的数字编码,转换成对应的模拟电压输出。DAC 可以按 8 位或 12 位模式进行配置,并且可与 DMA 控制器配合使用。在 12 位模式下,数据可以采用左对齐或右对齐。DAC 有两个输出 通道,每个通道各有一个转换器。在 DAC 双通道模式下,每个通道可以单独进行转换;当 两个通道组合在一起同步执行更新操作时,也可以同时进行转换。可通过一个输入参考电压引脚 Vref+ (与 ADC 共享)来提高分辨率。
DAC功能框图
-
参考电压 DAC使用Vref+作为参考电压,STM32规定了DAC的Vref+的输入范围为2.4-3.3V设计原理图时一般把Vssa接地,Vref+和Vdda接3.3V,可以得到DAC的电压输出范围是0~3.3V。 如果需要输出的电压范围变宽,需要外加电压转换电路将DAC的输出按比例抬升。 -
数模转换及输出通道 这是DAC的核心部件,它以Vref+为参考电源,以数据寄存器DORx的数字编码作为输入,经过其转换得的模拟信号通过右侧DAC_OUTx通道输出。 STM32中有两个DAC,每个DAC有一个对应的输出通道连接到特定引脚(需要配置为模拟输入功能) -
触发源及DHRx寄存器 使用DAC时不能直接对DORx寄存器写数据,任何输出到DAC通道x的数据都必须写入到DHRx寄存器中 数据写入到DHRx寄存器后,DAC会根据触发配置进行处理: 若使用硬件触发,则DHRx中的数据会在3个APB1时钟周期后传输至DORx,DORx随之输出相应的模拟电压到输出通道 若使用外部事件触发,可以使用定时器(TIMx_TRGO)、EXTI_9信号或软件触发(SWTRIGx)这几种方式
配置参数
-
DAC_Trigger: 用于配置DAC的触发模式,当DAC产生相应的触发事件时才会把DHRx寄存器的值转移到DORx寄存器中进行转换。可以选取的模式: ·硬件触发模式(DAC_Trigger_None):DHRx寄存器内的数据会在3个APB1时钟周期内自动转换至DORx进行转换 · 定时器触发模式(DAC_Trigger_T2/4/5/6/7/8_TRGO):使用定时器2、4、5、6、7、8控制DHRx寄存器的数据按时间转移到DORx中进行转换,利用这种方式可以输出特定的波形 · EXTI_9触发模式(DAC_Trigger_Ext_IT9):当产生EXTI_9事件时触发转换(如IO中断) · 软件触发模式(DAC_Trigger_Software):本模式下向DAC_SWTRIGR寄存器写入配置即可触发信号转换 -
DACWaveGeneration: 用于设置是否使用DAC输出伪噪声或三角波 使用伪噪声或三角波时,DAC都会把LFSR寄存器的值叠加在DHRx数值上,产生伪噪声或三角波。 -
DAC_LFSRUnmask_TriangleAmplitude: 通过控制DAC_CR的MAMP2位设置LFSR寄存器位的数据,即当使用伪噪声或三角波输出时要叠加到DHRx的值,非噪声或三角波输出模式下本参数无效。 使用伪噪声输出时LFSR=0xAAA,MAMP2寄存器位可以屏蔽LFSR的某些位,这时把本结构体成员赋值为DAC_LFSRUnmask_Bit0~DAC_LFSRUnmask_Bit11_0等宏即可; 使用三角波输出时,本结构体设置三角波的最大幅值,可选择DAC_TriangleAmplitude_1~ DAC_TriangleAmplitude_4096等。 -
DAC_OutputBuffer: 用于控制是否使能DAC的输出缓冲,使能了DAC输出缓冲可以减小输出阻抗,适合直接驱动一些外部负载
实验验证
我们可以通过DAC通道产生正弦波来验证实验。 要输出正弦波,实质是控制DAC以正弦函数关系来输出电压。由于模拟信号是连续的而数字信号是离散的,所以使用DAC输出正弦波时只能按一定时间间隔输出正弦曲线上的点,在该时段内输出相同的电压值,若缩短时间间隔,提高单个周期内输出点数,可以逐渐逼近连续正弦波的图形。
因为正弦波是周期函数,所以我们只需要得到单个周期内的数据即可。为了增加响应速度,减少单片机运算量,我们一般提前算好数据存入表中查表使用。
数据准备 可写入寄存器的最大值是12位所以就是2^12=4096 sin范围是[0,1],可以经过处理:v=3.3*(sin+1)/2,此时的范围就是[0,3.3]
把电压值以DAC寄存器的形式表示:Reg=(4096/3.3)v=2^11(sin+1) 此时存储到寄存器的值的范围就是[0,4096]
我们在单个周期内取32个点进行电压输出,所以就在[0,2Π]内等距取32个点按上面的公式算出来形成数组表格。 控制DAC输出时,每隔固定的时间就取出数组中的一个值进行输出即可模拟正弦波,改变时间间隔长度可以改变模拟正弦的周期
最后我们可以得到一组值: 下面我们进行配置:
uint16_t Sine12bit[32] = {
2048 , 2460 , 2856 , 3218 , 3532 , 3786 , 3969 , 4072 ,
4093 , 4031 , 3887 , 3668 , 3382 , 3042 , 2661 , 2255 ,
1841 , 1435 , 1054 , 714 , 428 , 209 , 65 , 3 ,
24 , 127 , 310 , 564 , 878 , 1240 , 1636 , 2048
};
void DAC_Config(void)
{
DAC_InitTypeDef DAC_Structer;
DAC_Structer.DAC_Trigger = DAC_Trigger_Software;
DAC_Structer.DAC_WaveGeneration = DAC_WaveGeneration_None;
DAC_Structer.DAC_OutputBuffer = DAC_OutputBuffer_Enable;
DAC_Structer.DAC_LFSRUnmask_TriangleAmplitude = DAC_TriangleAmplitude_4095;
DAC_Init(DAC_Channel_1,&DAC_Structer);
DAC_Cmd(DAC_Channel_1,ENABLE);
}
void TIM2_IRQHandler(void)
{
static u8 i=0;
TIM_ClearITPendingBit (TIM2,TIM_IT_Update);
DAC->DHR12R1 = Sine12bit[i];
DAC_SoftwareTriggerCmd(DAC_Channel_1,ENABLE);
i++;
if(i>31)
{
i=0;
}
}
最够得到结果可以用示波器看到是一个正弦波(这个正弦波还是会有噪声的)
|