DAC --- 数模转换器

<一>.DAC简介

<1>.DAC简介

DAC,全称:Digital-to-Analog Converter,指数字/模拟转换器。

ADC和DAC是模拟电路与数字电路之间的桥梁。

<2>.DAC的特性参数

1.分辨率

表示模拟电压的最小增量,常用二进制位数表示,比如:8、12位等。

2.建立时间

表示将一个数字量转换为稳定模拟信号所需的时间。

3.精度

转换器实际特性曲线与理想特性曲线之间的最大误差,误差源:比例系统误差、失调误差、非线性误差。

原因:元件参数误差、基准电压不稳定。运算放大器零漂等。

<3>.STM32各系列DAC的主要特性

<二>.DAC工作原理

1.DAC框图简介(F1/F4/F7)

实际操作DHRyyy:自动、软件、外部事件

DORx:不能直接写入数据

2.参考电压/模拟部分电压

3.DAC数据格式

4.触发源

三种触发转换方式:自动触发、软件触发、外部事件触发;

DHRx数据加载到DORx后,模拟输出电压将经过时间V(SETTLING)-建立时间 后可用。

关闭触发时(TEN=0)的转换时序图

5.DMA请求

6.DAC输出电压

<三>.DAC输出实验

<1>.实验简要

1.功能描述

通过DAC1通道1(PA4)输出预设电压,然后由ADC1通道1(PA1)采集,最后显示ADC转换的数字量及换算后的电压值;

2.关闭通道1触发(即自动)

TEN1位置0;

3.关闭输出缓冲

BUFF1位置1;

4.使用12位右对齐模式

将数字量写入DAC_DHR12R1寄存器。

<2>.DAC寄存器介绍(F1)

输出缓存(BOFF1):可减少阻抗,使输出能力会强一些,但无法输出0

 

<3>.DAC输出实验配置步骤

  1. 初始化DAC:HAL_DAC_Init();
  2. DAC MSP初始化:HAL_DAC_MspInit() --- 配置NVIC、CLOCK、GPIO等;
  3. 配置DAC相应通道相关参数:HAL_DAC_ConfigChannel();
  4. 启动D/A转换:HAL_DAC_Start();
  5. 设置输出数字量:HAL_DAC_SetValue();
  6. 读取通道输出数字量(可选):HAL_DAC_GetValue()

 

函数

主要寄存器

主要功能
HAL_DAC_Init()配置DAC工作状态(HAL库内部使用)
HAL_DAC_MspInit()存放NVIC、CLOCK、GPIO初始化代码
HAL_DAC_ConfigChannel()CR配置DAC相应通道的相关参数
HAL_DAC_Start()CR、SWTRIGR启动D/A转换
HAL_DAC_SetValue()DHR12Rx设置输出数字量
HAL_DAC_Getvalue()DORx读取通道输出数字量

关键结构体 (F1)

<4>.代码

dac.c

#include "./BSP/DAC/dac.h"
#include "./SYSTEM/delay/delay.h"


DAC_HandleTypeDef g_dac_handle;         /* DAC句柄 */

/**
 * @brief       DAC初始化函数
 *   @note      本函数支持DAC1_OUT1/2通道初始化
 *              DAC的输入时钟来自APB1, 时钟频率=36Mhz=27.8ns
 *              DAC在输出buffer关闭的时候, 输出建立时间: tSETTLING = 4us (F103数据手册有写)
 *              因此DAC输出的最高速度约为:250Khz, 以10个点为一个周期, 最大能输出25Khz左右的波形
 *
 * @param       outx: 要初始化的通道. 1,通道1; 2,通道2
 * @retval      无
 */
void dac_init(uint8_t outx)
{
    GPIO_InitTypeDef gpio_init_struct;
    DAC_ChannelConfTypeDef dac_ch_conf;
    
    __HAL_RCC_DAC_CLK_ENABLE();                                 /* 使能DAC1的时钟 */
    __HAL_RCC_GPIOA_CLK_ENABLE();                               /* 使能DAC OUT1/2的IO口时钟(都在PA口,PA4/PA5) */
    
    gpio_init_struct.Pin = (outx==1)? GPIO_PIN_4 : GPIO_PIN_5;  /* STM32单片机, 总是PA4=DAC1_OUT1, PA5=DAC1_OUT2 */
    gpio_init_struct.Mode = GPIO_MODE_ANALOG;
    HAL_GPIO_Init(GPIOA, &gpio_init_struct);

    g_dac_handle.Instance = DAC;
    HAL_DAC_Init(&g_dac_handle);                                /* 初始化DAC */


    dac_ch_conf.DAC_Trigger = DAC_TRIGGER_NONE;                 /* 不使用触发功能 */
    dac_ch_conf.DAC_OutputBuffer = DAC_OUTPUTBUFFER_DISABLE;    /* DAC1输出缓冲关闭 */
    
    switch(outx)
    {
        case 1:
            HAL_DAC_ConfigChannel(&g_dac_handle, &dac_ch_conf, DAC_CHANNEL_1);  /* 配置DAC通道1 */
            HAL_DAC_Start(&g_dac_handle,DAC_CHANNEL_1);                         /* 开启DAC通道1 */
            break;
        case 2:
            HAL_DAC_ConfigChannel(&g_dac_handle, &dac_ch_conf, DAC_CHANNEL_2);  /* 配置DAC通道2 */
            HAL_DAC_Start(&g_dac_handle,DAC_CHANNEL_2);                         /* 开启DAC通道2 */
            break;
        default:break;
    }

}

/**
 * @brief       设置通道1/2输出电压
 * @param       outx: 1,通道1; 2,通道2
 * @param       vol : 0~3300,代表0~3.3V
 * @retval      无
 */
void dac_set_voltage(uint8_t outx, uint16_t vol)
{
    double temp = vol;
    temp /= 1000;
    temp = temp * 4096 / 3.3;

    if (temp >= 4096)temp = 4095;   /* 如果值大于等于4096, 则取4095 */

    if (outx == 1)   /* 通道1 */
    {
        HAL_DAC_SetValue(&g_dac_handle, DAC_CHANNEL_1, DAC_ALIGN_12B_R, temp); /* 12位右对齐数据格式设置DAC值 */
    }
    else            /* 通道2 */
    {
        HAL_DAC_SetValue(&g_dac_handle, DAC_CHANNEL_2, DAC_ALIGN_12B_R, temp); /* 12位右对齐数据格式设置DAC值 */
    }
}

dac.h

#ifndef __DAC_H
#define __DAC_H

#include "./SYSTEM/sys/sys.h"



void dac_init(uint8_t outx);                        /* DAC通道1初始化 */ 
void dac_set_voltage(uint8_t outx, uint16_t vol);   /* 设置通道1/2输出电压 */ 

#endif

 main.c

#include "./SYSTEM/sys/sys.h"
#include "./SYSTEM/usart/usart.h"
#include "./SYSTEM/delay/delay.h"
#include "./USMART/usmart.h"
#include "./BSP/LED/led.h"
#include "./BSP/LCD/lcd.h"
#include "./BSP/KEY/key.h"
#include "./BSP/DAC/dac.h"
#include "./BSP/ADC/adc3.h"

extern DAC_HandleTypeDef g_dac_handle;

int main(void)
{
    uint16_t adcx;
    float temp;
    uint8_t t = 0;
    uint16_t dacval = 0;
    uint8_t key;

    HAL_Init();                                 /* 初始化HAL库 */
    sys_stm32_clock_init(RCC_PLL_MUL9);         /* 设置时钟, 72Mhz */
    delay_init(72);                             /* 延时初始化 */
    usart_init(115200);                         /* 串口初始化为115200 */
    usmart_dev.init(72);                        /* 初始化USMART */
    led_init();                                 /* 初始化LED */
    lcd_init();                                 /* 初始化LCD */
    key_init();                                 /* 初始化按键 */
    adc3_init();                                /* 初始化ADC3 */
    dac_init(1);                                /* 初始化DAC1_OUT1通道 */

    lcd_show_string(30,  50, 200, 16, 16, "STM32F103", RED);
    lcd_show_string(30,  70, 200, 16, 16, "DAC TEST", RED);
    lcd_show_string(30,  90, 200, 16, 16, "ATOM@ALIENTEK", RED);
    lcd_show_string(30, 110, 200, 16, 16, "WK_UP:+  KEY1:-", RED);
    
    lcd_show_string(30, 130, 200, 16, 16, "DAC VAL:", BLUE);
    lcd_show_string(30, 150, 200, 16, 16, "DAC VOL:0.000V", BLUE);
    lcd_show_string(30, 170, 200, 16, 16, "ADC VOL:0.000V", BLUE);

    while (1)
    {
        t++;
        key = key_scan(0);          /* 按键扫描 */

        if (key == WKUP_PRES)
        {
            if (dacval < 4000)dacval += 200;

            HAL_DAC_SetValue(&g_dac_handle, DAC_CHANNEL_1, DAC_ALIGN_12B_R, dacval);/* 输出增大200 */
        }
        else if (key == KEY1_PRES)
        {
            if (dacval > 200)dacval -= 200;
            else dacval = 0;

            HAL_DAC_SetValue(&g_dac_handle, DAC_CHANNEL_1, DAC_ALIGN_12B_R, dacval); /* 输出减少200 */
        }

        if (t == 10 || key == KEY1_PRES || key == WKUP_PRES)        /* WKUP/KEY1按下了,或者定时时间到了 */
        {
            adcx = HAL_DAC_GetValue(&g_dac_handle, DAC_CHANNEL_1);  /* 读取前面设置DAC1_OUT1的值 */
            lcd_show_xnum(94, 130, adcx, 4, 16, 0, BLUE);           /* 显示DAC寄存器值 */
            
            temp = (float)adcx * (3.3 / 4096);                      /* 得到DAC电压值 */
            adcx = temp;
            lcd_show_xnum(94, 150, temp, 1, 16, 0, BLUE);           /* 显示电压值整数部分 */
            
            temp -= adcx;
            temp *= 1000;
            lcd_show_xnum(110, 150, temp, 3, 16, 0X80, BLUE);       /* 显示电压值的小数部分 */
            
            adcx = adc3_get_result_average(ADC3_CHY, 20);           /* 得到ADC3通道1的转换结果 */
            temp = (float)adcx * (3.3 / 4096);                      /* 得到ADC电压值(adc是16bit的) */
            adcx = temp;
            lcd_show_xnum(94, 170, temp, 1, 16, 0, BLUE);           /* 显示电压值整数部分 */
                
            temp -= adcx;
            temp *= 1000;
            lcd_show_xnum(110, 170, temp, 3, 16, 0X80, BLUE);       /* 显示电压值的小数部分 */
            
            LED0_TOGGLE();  /* LED0闪烁 */
            t = 0;
        }

        delay_ms(10);
    }
}

<四>.DAC输出三角波实验

<五>.DAC输出正弦波实验

<六>.PWM DAC实验

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值