【RTT-Studio】DAC模拟输出详细使用指南

文章目录

  • 一、简介
  • 二、RTT时钟配置
  • 三、DAC初始化配置
  • 四、驱动代码编写
  • 五、测试验证
  • 一、简介

    本文将基于STM32F407VET6介绍,如何使用RT-Thread Studio开发环境下使用DAC设备。并且DAC的相关介绍在另外一篇博客中介绍到,如果想对DAC有一个更加深刻的了解,可以参考下面这篇文章。

  • 【STM32】RTT-Studio中HAL库开发教程四:DAC+DMA输出波形

  • 二、RTT时钟配置

    由于使用RTT生成的工程默认使用的是系统内部时钟,便于我们对时间的控制,所以通常会使用外部时钟,因此需要对工程中的时钟进行更改,更改内容如下:

  • 打开RT-Thread Studio软件新建基于芯片的项目,并使用外部时钟系统。
  • 在drv_clk.c文件中添加时钟配置函数,并且注释内部时钟的调用。
  • /**
      * @brief System Clock Configuration
      * @retval None
      */
    void SystemClock_Config(void)
    {
        RCC_OscInitTypeDef RCC_OscInitStruct = {0};
        RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
    
        /** Configure the main internal regulator output voltage
         */
        __HAL_RCC_PWR_CLK_ENABLE();
        __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
    
        /** Initializes the CPU, AHB and APB busses clocks
         */
        RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
        RCC_OscInitStruct.HSEState = RCC_HSE_ON;
        RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
        RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
        RCC_OscInitStruct.PLL.PLLM = 4;
        RCC_OscInitStruct.PLL.PLLN = 168;
        RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
        RCC_OscInitStruct.PLL.PLLQ = 4;
        if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
        {
            Error_Handler();
        }
    
        /** Initializes the CPU, AHB and APB busses clocks
         */
        RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK
                | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
        RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
        RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
        RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
        RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
    
        if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK)
        {
            Error_Handler();
        }
    }
    
    void clk_init(char *clk_source, int source_freq, int target_freq)
    {
    //    system_clock_config(target_freq);
        SystemClock_Config();
    }
    

    三、DAC初始化配置

    1.打开DAC驱动框架
    RT-Thread Setting 中借助图形化配置工具打开软件DAC的驱动框架,如下图所示:

    2.定义DAC宏定义
    在board.h文件中添加DAC的宏定义,从而保证能够使用DAC的相关驱动函数。

    /*-------------------------- DAC CONFIG BEGIN --------------------------*/
    
    /** if you want to use DAC you can use the following instructions.
     *
     * STEP 1, open DAC driver framework support in the RT-Thread Settings file
     *
     * STEP 2, define macro related to the DAC
     *                 such as     #define BSP_USING_DAC1
     *
     * STEP 3, copy your DAC init function from stm32xxxx_hal_msp.c generated by stm32cubemx to the end of board.c file
     *                 such as     void HAL_DAC_MspInit(DAC_HandleTypeDef* hdac)
     *
     * STEP 4, modify your stm32xxxx_hal_config.h file to support DAC peripherals. define macro related to the peripherals
     *                 such as     #define HAL_DAC_MODULE_ENABLED
     *
     */
    
    #define BSP_USING_DAC1
    
    /*-------------------------- DAC CONFIG END --------------------------*/
    

    3.编写DAC初始化代码
    可以使用STM32CubeMx自动生成代码,也可以自己编写初始化代码,使能DAC1和DAC2。然后将生成的函数HAL_DAC_MspInit(DAC_HandleTypeDef* dacHandle)复制到board.c文件中进行初始化。

    void HAL_DAC_MspInit(DAC_HandleTypeDef* dacHandle)
    {
        GPIO_InitTypeDef GPIO_InitStruct = {0};
        if(dacHandle->Instance==DAC)
        {
            /* DAC clock enable */
            __HAL_RCC_DAC_CLK_ENABLE();
    
            __HAL_RCC_GPIOA_CLK_ENABLE();
            /**DAC GPIO Configuration
            PA4     ------> DAC_OUT1
            PA5     ------> DAC_OUT2
            */
            GPIO_InitStruct.Pin = GPIO_PIN_4|GPIO_PIN_5;
            GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
            GPIO_InitStruct.Pull = GPIO_NOPULL;
            HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
        }
    }
    

    4.打开STM32宏定义
    在driver中的stm32f4xx_hal_conf.h中DAC宏定义打开。


    四、驱动代码编写

    1.dac.c
    主要包含两个函数,int set_dac_output(uint32_t dac_value, uint8_t channel)void close_dac_output(uint8_t channel),设置通道和输出电压,以及关闭通道的输出函数。参考电压:2.5V为参考,最大输出2.5V。

    #include "dac.h"
    
    /**
     * @brief 设置DAC输出电压
     * @param dac_value DAC值
     * @param channel 通道
     * @return
     */
    int set_dac_output(uint32_t dac_value, uint8_t channel)
    {
        rt_dac_device_t dac_dev;
        rt_uint32_t value, vol;
        rt_err_t ret = RT_EOK;
    
        /* 查找设备 */
        dac_dev = (rt_dac_device_t)rt_device_find(DAC_DEV_NAME);
        if (dac_dev == RT_NULL)
        {
            rt_kprintf("dac sample run failed! can't find %s device!\n", DAC_DEV_NAME);
            return RT_ERROR;
        }
    
        /* 打开通道 */
        ret = rt_dac_enable(dac_dev, channel);
    
        /* 设置输出值 */
        value = dac_value;
        if (value > 4095)
        {
            value = 4095;
        }
        rt_dac_write(dac_dev, channel, value);
        rt_kprintf("the value is :%d \n", value);
    
        /* 转换为对应电压值 */
        vol = value * REFER_VOLTAGE / CONVERT_BITS;
        rt_kprintf("the voltage is :%d.%02d \n", vol / 100, vol % 100);
    
        return ret;
    }
    
    
    /**
     * @brief 关闭DAC输出
     * @param channel 通道
     */
    void close_dac_output(uint8_t channel)
    {
        rt_dac_device_t dac_dev;
    
        /* 查找设备 */
        dac_dev = (rt_dac_device_t)rt_device_find(DAC_DEV_NAME);
        if (dac_dev == RT_NULL)
        {
            rt_kprintf("dac sample run failed! can't find %s device!\n", DAC_DEV_NAME);
            return RT_ERROR;
        }
    
        rt_dac_disable(dac_dev, channel);
    }
    

    2.dac.h

    #ifndef APPLICATIONS_DAC_H_
    #define APPLICATIONS_DAC_H_
    
    #include <rtthread.h>
    #include <rtdevice.h>
    #include <drv_common.h>
    #include <stdlib.h>
    
    #define DAC_PORT    GPIOA
    #define DAC_PIN     GPIO_PIN_5          // dac引脚号 -- DAC1_OUT2
    
    
    #define DAC_DEV_NAME        "dac1"      // DAC 设备名称
    #define DAC_DEV_CHANNEL_1   1           // DAC 通道1
    #define DAC_DEV_CHANNEL_2   2           // DAC 通道2
    #define REFER_VOLTAGE       250         // 参考电压 2.5V,数据精度乘以100保留2位小数
    #define CONVERT_BITS        (1 << 12)   // 转换位数为12位
    
    
    extern int set_dac_output(uint32_t dac_value, uint8_t channel);
    extern void close_dac_output(uint8_t channel);
    
    #endif /* APPLICATIONS_DAC_H_ */
    

    3.main.c
    主要是设置DAC的输出值和通道,然后进行DAC的输出。

    #include <rtthread.h>
    
    #define DBG_TAG "main"
    #define DBG_LVL DBG_LOG
    #include <rtdbg.h>
    
    #include "dac.h"
    
    int main(void)
    {
        int count = 1;
    
        while (count)
        {
            set_dac_output(2048, 1);
            set_dac_output(4095, 2);
            rt_thread_mdelay(3000);
        }
    
        return RT_EOK;
    }
    

    五、测试验证

    通过示波器可以观察到输出的波形,两个通道的电压分别是2.52V和1.3V,和我们设置的参数基本上一直,设置的4095为输出电压2.5V,2048则是1.25V,测试的会存在一定的电压误差,所以两者不是完全相等。测试波形如下:

    作者:0南城逆流0

    物联沃分享整理
    物联沃-IOTWORD物联网 » 【RTT-Studio】DAC模拟输出详细使用指南

    发表回复