DAC 基础知识(DAC 输出实验)

DAC 简介 

DAC 输出实验 

DAC 寄存器 

⚫ DAC 控制寄存器(DAC_CR)

DAC_CR 的低 16 位用于控制通道 1,高 16 位用于控制通道 2,下面介绍本实验需要设置 的一些位:

EN1 位用于 DAC 通道 1 的使能,我们需要用到 DAC 通道 1 的输出,该位必须设置为 1。

BOFF1 位用于 DAC 输出缓存控制,这里 STM32 的 DAC 输出缓存做的有些不好,如果使 能的话,虽然输出能力强一点,但是输出没法到 0,这是个很严重的问题。所以本章的三个实验 我们都不使用输出缓存,即该位设置为 1。

TEN1 位用于 DAC 通道 1 的触发使能,我们设置该位为 0,不使用触发。写入 DHR1 的值 会在 1 个 APB1 周期后传送到 DOR1,然后输出到 PA4 口上。

TSEL1[2:0]位用于选择 DAC 通道 1 的触发方式,这里我们没有用到外部触发,所以这几位 设置为 0 即可。

WAVE1[1:0]位用于控制 DAC 通道 1 的噪声/波形输出功能,我们这里没用到波形发生器, 所以默认设置为 00,不使能噪声/波形输出。

MAMP[3:0]位是屏蔽/幅值选择器,用来在噪声生成模式下选择屏蔽位,在三角波生成模式 下选择波形的幅值。本实验没有用到波形发生器,所以设置为 0 即可。

DMAEN1 位用于 DAC 通道 1 的 DMA 使能,本实验没有用到 DMA 功能,所以设置为 0。

⚫ DAC 通道 1 12 位右对齐数据保持寄存器(DAC_DHR12R1)

 我们只需要通过杜邦线连接 ADC 和 DAC,就可以使得 ADC1 通道 1(PA1)和 DAC 通 道 1(PA4)连接起来。对应的硬件连接如图 33.2.2.2 所示:

 代码

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

DAC_HandleTypeDef g_dac_handle;

/* DAC初始化函数 */
void dac_init(void)
{
    DAC_ChannelConfTypeDef dac_ch_conf = {0};
    
    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 输出缓冲关闭 */
    HAL_DAC_ConfigChannel(&g_dac_handle, &dac_ch_conf, DAC_CHANNEL_1);
    
    HAL_DAC_Start(&g_dac_handle, DAC_CHANNEL_1);/* 开启 DAC 通道 1 */
}

/* DAC MSP底层初始化函数 */
void HAL_DAC_MspInit(DAC_HandleTypeDef *hdac)
{
    if(hdac->Instance == DAC)
    {
        GPIO_InitTypeDef gpio_init_struct = {0};
        
        __HAL_RCC_DAC_CLK_ENABLE();/* 使能 DAC1 的时钟 */
        __HAL_RCC_GPIOA_CLK_ENABLE();;/* 使能 DAC OUT1/2 的 IO 口时钟(都在 PA 口,PA4/PA5) */
        
        gpio_init_struct.Pin = GPIO_PIN_4;
        gpio_init_struct.Mode = GPIO_MODE_ANALOG;
        HAL_GPIO_Init(GPIOA, &gpio_init_struct);
    }
}

/* 设置通道输出电压,(vol : 0~3300,代表 0~3.3V) */
void dac_set_voltage(uint16_t vol)
{
    double temp = vol;
    temp /= 1000;
    temp = temp * 4096 / 3.3;
    
    if(temp >= 4096)
    {
        temp = 4095;/* 如果值大于等于 4096, 则取 4095 */
    }
    
    HAL_DAC_SetValue(&g_dac_handle, DAC_CHANNEL_1, DAC_ALIGN_12B_R, temp);
}

该函数主要调用 HAL_DAC_Init 和 HAL_DAC_ConfigChannel 函数初始化 DAC,并调用 HAL_DAC_Start 函数使能 DAC 通道。HAL_DAC_Init 函数会调用 HAL_DAC_MspInit 回调函 数,该函数用于存放 DAC 和对应通道的 IO 时钟使能和初始化 IO 等代码。本实验为了让 dac_init 函数支持 DAC 的 OUT1/2 两个通道的初始化,就没有用到该函数。

该函数实际就是将电压值转换为 DAC 输入值,形参 1 设置要输出 的电压值,设置的范围:0~3300,代表 0~3.3V。 

#include "./SYSTEM/sys/sys.h"
#include "./SYSTEM/usart/usart.h"
#include "./SYSTEM/delay/delay.h"
#include "./BSP/LED/led.h"
#include "./BSP/LCD/lcd.h"
#include "./BSP/ADC/adc.h"
#include "./BSP/DAC/dac.h"

int main(void)
{
    uint16_t adcx;
    float temp;
    
    HAL_Init();                         /* 初始化 HAL 库 */
    sys_stm32_clock_init(RCC_PLL_MUL9); /* 设置时钟, 72Mhz */
    delay_init(72);                     /* 延时初始化 */
    usart_init(115200);                 /* 传口初始化 */
    
    led_init();                         /* LED初始化 */
    lcd_init();                         /* LCD初始化 */
    adc_init();                         /* ADC初始化 */
    dac_init();                         /* DAC初始化 */
    
    dac_set_voltage(2000);
    
    lcd_show_string(30, 50, 200, 16, 16, "STM32", RED);
    lcd_show_string(30, 70, 200, 16, 16, "ADC TEST", RED);
    lcd_show_string(30, 90, 200, 16, 16, "ATOM@ALIENTEK", RED);
    lcd_show_string(30, 110, 200, 16, 16, "ADC1_CH1_VAL:", BLUE);
    lcd_show_string(30, 130, 200, 16, 16, "ADC1_CH1_VOL:0.000V", BLUE); /* 先在固定位置显示小数点 */
    
    while(1)
    {
        adcx = adc_get_result_average(10);/* 获取通道1的转换值,10次取平均 */
        lcd_show_xnum(134, 110, adcx, 5, 16, 0, BLUE);      /* 显示ADCC采样后的原始值 */
        
        temp = (float)adcx * (3.3 / 4096);/* 获取计算后的带小数的实际电压值,比如3.1111 */
        adcx = temp;/* 赋值整数部分给adcx变量,因为adcx为u16整形 */
        lcd_show_xnum(134, 130, adcx, 1, 16, 0, BLUE);/* 显示电压值的整数部分,3.1111的话,这里就是显示3 */
        
        temp -=adcx;/* 把已经显示的整数部分去掉,留下小数部分,比如3.1111-3=0.1111 */
        temp *= 1000;/* 小数部分乘以1000,例如:0.1111就转换为111.1,相当于保留三位小数。 */
        lcd_show_xnum(150, 130, temp, 3, 16, 0X80, BLUE);   /* 显示小数部分(前面转换为了整形显示),这里显示的就是111. */
        
        LED0_TOGGLE();
        delay_ms(100);
    }
}
  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值