DAC 为数字/模拟转换模块,故名思议,它的作用就是把输入的数字编码,转换成对应的模拟电压输出,它的功能与 ADC 相反。在常见的数字信号系统中,大部分传感器信号被化成电压信号,而 ADC 把电压模拟信号转换成易于计算机存储、处理的数字编码,由计算机处理完成后,再由 DAC 输出电压模拟信号,该电压模拟信号常常用来驱动某些执行器件,使人类易于感知。如音频信号的采集及还原就是这样一个过程。STM32 具有片上 DAC 外设,它的分辨率可配置为 8 位或 12 位的数字输入信号,具有两个 DAC 输出通道,这两个通道互不影响,每个通道都可以使用 DMA 功能,都具有出错检测能力,可外部触发。

    1. typedef struct {
    2. /*DAC 触发方式 */
    3. uint32_t DAC_Trigger;
    4. /*是否自动输出噪声或三角波 */
    5. uint32_t DAC_WaveGeneration;
    6. /*选择噪声生成器的低通滤波或三角波的幅值 */
    7. uint32_t DAC_LFSRUnmask_TriangleAmplitude;
    8. /*选择是否使能输出缓冲器 */
    9. uint32_t DAC_OutputBuffer;
    10. } DAC_InitTypeDef;

    各个结构体成员的介绍如下,解说中各模式后括号内的英文为该模式在标准库中使用宏:
    (1) DAC_Trigger
    本成员用于配置DAC的触发模式,当DAC产生相应的触发事件时,才会把DHRx寄存器的值转移到DORx 寄存器中进行转换。本结构体成员可以选择的触发模式如下:硬件触发模式(DAC_Trigger_None),DHRx寄存器内的数据会在3个APB1时钟周期内自动转换至 DORx进行转换;定时器触发模式(DAC_Trigger_T2/4/5/6/7_TRGO),使用定时器 2、4、5、6、7 控制 DHRx 寄存器的数据按时间转移到 DORx中进行转换,利用这种方式可以输出特定的波形;EXTI_9触发方式(DAC_Trigger_Ext_IT9),当产生EXTI_9 事件时(如 GPIO 中断事件),触 发 转 换;软件 触 发 模 式( DAC_Trigger_Software ),在本模式下,向DAC_SWTRIGR寄存器写入配置即可触发信号进行转换。

    (2)DAC_WaveGeneration
    本 成 员 用 于 设 置 是 否 使 用DAC输 出 伪 噪 声 或 三 角 波(DAC_WaveGeneration_None/Noise/Triangle),使用伪噪声和三角波输出时,DAC都会把 LFSR 寄存器的值叠加到 DHRx 数值上,产生伪噪声和三角波,若希望产生自定义的输出时,直接配置为DAC_WaveGeneration_None即可。

    (3)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在DHRx值的基础上升,幅值达到MAMPx设置的最大幅度时下降,形成三角波的输出。
    ![JE@KBE1[591L8OT3){9QG4.png
    (4) DAC_OutputBuffer
    本结构体成员用于控制是否使能DAC的输出缓冲(DAC_OutputBuffer_Enable/Disable),使能了DAC的输出缓冲后可以减小输出阻抗,适合直接驱动一些外部负载。

    DAC的配置

    1. GPIO_InitTypeDef GPIO_InitStructure;
    2. DAC_InitTypeDef DAC_InitStructure;
    3. TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
    4. RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
    5. RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE);
    6. RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
    7. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
    8. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    9. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
    10. GPIO_Init(GPIOA, &GPIO_InitStructure);
    11. TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
    12. TIM_TimeBaseStructure.TIM_Period = 0x0F;
    13. TIM_TimeBaseStructure.TIM_Prescaler = 0x01;
    14. TIM_TimeBaseStructure.TIM_ClockDivision = 0x0;
    15. TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
    16. TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
    17. TIM_SelectOutputTrigger(TIM2, TIM_TRGOSource_Update);
    18. DAC_InitStructure.DAC_Trigger = DAC_Trigger_T2_TRGO;
    19. DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_Triangle;
    20. DAC_InitStructure.DAC_LFSRUnmask_TriangleAmplitude = DAC_TriangleAmplitude_4095;
    21. DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Disable;
    22. DAC_Init(DAC_Channel_1, &DAC_InitStructure);
    23. DAC_Cmd(DAC_Channel_1, ENABLE);
    24. DAC_SetDualChannelData(DAC_Align_12b_R, 0, 0);
    25. TIM_Cmd(TIM2, ENABLE);