Browse Source

[bsp/at32] add support dac driver

sheltonyu 2 years ago
parent
commit
8612d5e119

+ 3 - 0
bsp/at32/at32f403a-start/README.md

@@ -43,6 +43,7 @@ AT32F403A-START板级包支持MDK4﹑MDK5﹑IAR开发环境和GCC编译器,以
 | IIC       | 支持     | GPIO模拟I2C                |
 | SPI       | 支持     | SPI1/2                     |
 | ADC       | 支持     | ADC1/2                     |
+| DAC       | 支持     | DAC1                       |
 | PWM       | 支持     | TMR1/2                     |
 | HWTIMER   | 支持     | TMR3/4/5                   |
 | SDIO      | 支持     | SDIO1                      |
@@ -91,6 +92,8 @@ AT32F403A-START板级包支持MDK4﹑MDK5﹑IAR开发环境和GCC编译器,以
 | PC3  | ADC1/2_IN13    |
 | PC4  | ADC1/2_IN14    |
 | PC5  | ADC1/2_IN15    |
+| PA4  | DAC_OUT1       |
+| PA5  | DAC_OUT2       |
 | PB8  | CAN1_RX        |
 | PB9  | CAN1_TX        |
 | PB5  | CAN2_RX        |

+ 10 - 0
bsp/at32/at32f403a-start/board/Kconfig

@@ -278,6 +278,16 @@ menu "On-chip Peripheral Drivers"
                 default n
         endif
 
+    menuconfig BSP_USING_DAC
+        bool "Enable DAC"
+        default n
+        select RT_USING_DAC
+        if BSP_USING_DAC
+            config BSP_USING_DAC1
+                bool "Enable DAC1"
+                default n
+        endif
+
     menuconfig BSP_USING_CAN
         bool "Enable CAN"
         default n

+ 1 - 0
bsp/at32/at32f403a-start/board/inc/at32_msp.h

@@ -20,5 +20,6 @@ void at32_msp_adc_init(void *instance);
 void at32_msp_hwtmr_init(void *instance);
 void at32_msp_can_init(void *instance);
 void at32_msp_usb_init(void *instance);
+void at32_msp_dac_init(void *instance);
 
 #endif /* __AT32_MSP_H__ */

+ 25 - 1
bsp/at32/at32f403a-start/board/src/at32_msp.c

@@ -381,5 +381,29 @@ void at32_msp_usb_init(void *instance)
         }
     }
 }
-
 #endif /* BSP_USING_USBD */
+
+#ifdef BSP_USING_DAC
+void at32_msp_dac_init(void *instance)
+{
+    gpio_init_type gpio_init_struct;
+    dac_type *dac_x = (dac_type *)instance;
+
+    gpio_default_para_init(&gpio_init_struct);
+    gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
+#ifdef BSP_USING_DAC1
+    if(dac_x == DAC)
+    {
+        /* dac & gpio clock enable */
+        crm_periph_clock_enable(CRM_DAC_PERIPH_CLOCK, TRUE);
+        crm_periph_clock_enable(CRM_GPIOA_PERIPH_CLOCK, TRUE);
+
+        /* configure adc channel as analog output */
+        gpio_init_struct.gpio_pins = GPIO_PINS_4 | GPIO_PINS_5;
+        gpio_init_struct.gpio_mode = GPIO_MODE_ANALOG;
+        gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
+        gpio_init(GPIOA, &gpio_init_struct);
+    }
+#endif
+}
+#endif /* BSP_USING_DAC */

+ 3 - 0
bsp/at32/at32f407-start/README.md

@@ -43,6 +43,7 @@ AT32F407-START板级包支持MDK4﹑MDK5﹑IAR开发环境和GCC编译器,以
 | IIC       | 支持     | GPIO模拟I2C                |
 | SPI       | 支持     | SPI1/2                     |
 | ADC       | 支持     | ADC1/2                     |
+| DAC       | 支持     | DAC1                       |
 | PWM       | 支持     | TMR1/2                     |
 | HWTIMER   | 支持     | TMR3/4/5                   |
 | SDIO      | 支持     | SDIO1                      |
@@ -92,6 +93,8 @@ AT32F407-START板级包支持MDK4﹑MDK5﹑IAR开发环境和GCC编译器,以
 | PC3  | ADC1/2_IN13       |
 | PC4  | ADC1/2_IN14       |
 | PC5  | ADC1/2_IN15       |
+| PA4  | DAC_OUT1          |
+| PA5  | DAC_OUT2          |
 | PB8  | CAN1_RX           |
 | PB9  | CAN1_TX           |
 | PB5  | CAN2_RX           |

+ 10 - 0
bsp/at32/at32f407-start/board/Kconfig

@@ -295,6 +295,16 @@ menu "On-chip Peripheral Drivers"
                 default n
         endif
 
+    menuconfig BSP_USING_DAC
+        bool "Enable DAC"
+        default n
+        select RT_USING_DAC
+        if BSP_USING_DAC
+            config BSP_USING_DAC1
+                bool "Enable DAC1"
+                default n
+        endif
+
     menuconfig BSP_USING_CAN
         bool "Enable CAN"
         default n

+ 1 - 0
bsp/at32/at32f407-start/board/inc/at32_msp.h

@@ -21,5 +21,6 @@ void at32_msp_hwtmr_init(void *instance);
 void at32_msp_can_init(void *instance);
 void at32_msp_emac_init(void *instance);
 void at32_msp_usb_init(void *instance);
+void at32_msp_dac_init(void *instance);
 
 #endif /* __AT32_MSP_H__ */

+ 24 - 1
bsp/at32/at32f407-start/board/src/at32_msp.c

@@ -422,6 +422,29 @@ void at32_msp_usb_init(void *instance)
         }
     }
 }
-
 #endif /* BSP_USING_USBD */
 
+#ifdef BSP_USING_DAC
+void at32_msp_dac_init(void *instance)
+{
+    gpio_init_type gpio_init_struct;
+    dac_type *dac_x = (dac_type *)instance;
+
+    gpio_default_para_init(&gpio_init_struct);
+    gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
+#ifdef BSP_USING_DAC1
+    if(dac_x == DAC)
+    {
+        /* dac & gpio clock enable */
+        crm_periph_clock_enable(CRM_DAC_PERIPH_CLOCK, TRUE);
+        crm_periph_clock_enable(CRM_GPIOA_PERIPH_CLOCK, TRUE);
+
+        /* configure adc channel as analog output */
+        gpio_init_struct.gpio_pins = GPIO_PINS_4 | GPIO_PINS_5;
+        gpio_init_struct.gpio_mode = GPIO_MODE_ANALOG;
+        gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
+        gpio_init(GPIOA, &gpio_init_struct);
+    }
+#endif
+}
+#endif /* BSP_USING_DAC */

+ 3 - 0
bsp/at32/at32f423-start/README.md

@@ -43,6 +43,7 @@ AT32F423-START板级包支持MDK4﹑MDK5﹑IAR开发环境和GCC编译器,以
 | IIC       | 支持     | GPIO模拟I2C                |
 | SPI       | 支持     | SPI1/2                     |
 | ADC       | 支持     | ADC1                       |
+| DAC       | 支持     | DAC1                       |
 | PWM       | 支持     | TMR1/2                     |
 | HWTIMER   | 支持     | TMR3                       |
 | CAN       | 支持     | CAN1/2                     |
@@ -84,6 +85,8 @@ AT32F423-START板级包支持MDK4﹑MDK5﹑IAR开发环境和GCC编译器,以
 | PC3  | ADC1_IN13      |
 | PC4  | ADC1_IN14      |
 | PC5  | ADC1_IN15      |
+| PA4  | DAC_OUT1       |
+| PA5  | DAC_OUT2       |
 | PB8  | CAN1_RX        |
 | PB9  | CAN1_TX        |
 | PB5  | CAN2_RX        |

+ 10 - 0
bsp/at32/at32f423-start/board/Kconfig

@@ -287,6 +287,16 @@ menu "On-chip Peripheral Drivers"
                 default n
         endif
 
+    menuconfig BSP_USING_DAC
+        bool "Enable DAC"
+        default n
+        select RT_USING_DAC
+        if BSP_USING_DAC
+            config BSP_USING_DAC1
+                bool "Enable DAC1"
+                default n
+        endif
+
     menuconfig BSP_USING_CAN
         bool "Enable CAN"
         default n

+ 1 - 0
bsp/at32/at32f423-start/board/inc/at32_msp.h

@@ -18,5 +18,6 @@ void at32_msp_adc_init(void *instance);
 void at32_msp_hwtmr_init(void *instance);
 void at32_msp_can_init(void *instance);
 void at32_msp_usb_init(void *instance);
+void at32_msp_dac_init(void *instance);
 
 #endif /* __AT32_MSP_H__ */

+ 25 - 1
bsp/at32/at32f423-start/board/src/at32_msp.c

@@ -316,5 +316,29 @@ void at32_msp_usb_init(void *instance)
         }
     }
 }
-
 #endif /* BSP_USING_USBFS */
+
+#ifdef BSP_USING_DAC
+void at32_msp_dac_init(void *instance)
+{
+    gpio_init_type gpio_init_struct;
+    dac_type *dac_x = (dac_type *)instance;
+
+    gpio_default_para_init(&gpio_init_struct);
+    gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
+#ifdef BSP_USING_DAC1
+    if(dac_x == DAC)
+    {
+        /* dac & gpio clock enable */
+        crm_periph_clock_enable(CRM_DAC_PERIPH_CLOCK, TRUE);
+        crm_periph_clock_enable(CRM_GPIOA_PERIPH_CLOCK, TRUE);
+
+        /* configure adc channel as analog output */
+        gpio_init_struct.gpio_pins = GPIO_PINS_4 | GPIO_PINS_5;
+        gpio_init_struct.gpio_mode = GPIO_MODE_ANALOG;
+        gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
+        gpio_init(GPIOA, &gpio_init_struct);
+    }
+#endif
+}
+#endif /* BSP_USING_DAC */

+ 3 - 0
bsp/at32/at32f435-start/README.md

@@ -43,6 +43,7 @@ AT32F437-START板级包支持MDK4﹑MDK5﹑IAR开发环境和GCC编译器,以
 | IIC       | 支持     | GPIO模拟I2C                |
 | SPI       | 支持     | SPI1/2                     |
 | ADC       | 支持     | ADC1/2                     |
+| DAC       | 支持     | DAC1                       |
 | PWM       | 支持     | TMR1/2                     |
 | HWTIMER   | 支持     | TMR3/4/5                   |
 | SDIO      | 支持     | SDIO1                      |
@@ -93,6 +94,8 @@ AT32F437-START板级包支持MDK4﹑MDK5﹑IAR开发环境和GCC编译器,以
 | PC3  | ADC1/2_IN13       |
 | PC4  | ADC1/2_IN14       |
 | PC5  | ADC1/2_IN15       |
+| PA4  | DAC_OUT1          |
+| PA5  | DAC_OUT2          |
 | PB8  | CAN1_RX           |
 | PB9  | CAN1_TX           |
 | PB5  | CAN2_RX           |

+ 10 - 0
bsp/at32/at32f435-start/board/Kconfig

@@ -327,6 +327,16 @@ menu "On-chip Peripheral Drivers"
                 default n
         endif
 
+    menuconfig BSP_USING_DAC
+        bool "Enable DAC"
+        default n
+        select RT_USING_DAC
+        if BSP_USING_DAC
+            config BSP_USING_DAC1
+                bool "Enable DAC1"
+                default n
+        endif
+
     menuconfig BSP_USING_CAN
         bool "Enable CAN"
         default n

+ 1 - 0
bsp/at32/at32f435-start/board/inc/at32_msp.h

@@ -22,5 +22,6 @@ void at32_msp_can_init(void *instance);
 void at32_msp_qspi_init(void *instance);
 void at32_msp_sdram_init(void *instance);
 void at32_msp_usb_init(void *instance);
+void at32_msp_dac_init(void *instance);
 
 #endif /* __AT32_MSP_H__ */

+ 25 - 1
bsp/at32/at32f435-start/board/src/at32_msp.c

@@ -570,5 +570,29 @@ void at32_msp_usb_init(void *instance)
         }
     }
 }
-
 #endif /* BSP_USING_USBFS */
+
+#ifdef BSP_USING_DAC
+void at32_msp_dac_init(void *instance)
+{
+    gpio_init_type gpio_init_struct;
+    dac_type *dac_x = (dac_type *)instance;
+
+    gpio_default_para_init(&gpio_init_struct);
+    gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
+#ifdef BSP_USING_DAC1
+    if(dac_x == DAC)
+    {
+        /* dac & gpio clock enable */
+        crm_periph_clock_enable(CRM_DAC_PERIPH_CLOCK, TRUE);
+        crm_periph_clock_enable(CRM_GPIOA_PERIPH_CLOCK, TRUE);
+
+        /* configure adc channel as analog output */
+        gpio_init_struct.gpio_pins = GPIO_PINS_4 | GPIO_PINS_5;
+        gpio_init_struct.gpio_mode = GPIO_MODE_ANALOG;
+        gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
+        gpio_init(GPIOA, &gpio_init_struct);
+    }
+#endif
+}
+#endif /* BSP_USING_DAC */

+ 3 - 0
bsp/at32/at32f437-start/README.md

@@ -43,6 +43,7 @@ AT32F437-START板级包支持MDK4﹑MDK5﹑IAR开发环境和GCC编译器,以
 | IIC       | 支持     | GPIO模拟I2C                |
 | SPI       | 支持     | SPI1/2                     |
 | ADC       | 支持     | ADC1/2                     |
+| DAC       | 支持     | DAC1                       |
 | PWM       | 支持     | TMR1/2                     |
 | HWTIMER   | 支持     | TMR3/4/5                   |
 | SDIO      | 支持     | SDIO1                      |
@@ -94,6 +95,8 @@ AT32F437-START板级包支持MDK4﹑MDK5﹑IAR开发环境和GCC编译器,以
 | PC3  | ADC1/2_IN13       |
 | PC4  | ADC1/2_IN14       |
 | PC5  | ADC1/2_IN15       |
+| PA4  | DAC_OUT1          |
+| PA5  | DAC_OUT2          |
 | PB8  | CAN1_RX           |
 | PB9  | CAN1_TX           |
 | PB5  | CAN2_RX           |

+ 10 - 0
bsp/at32/at32f437-start/board/Kconfig

@@ -344,6 +344,16 @@ menu "On-chip Peripheral Drivers"
                 default n
         endif
 
+    menuconfig BSP_USING_DAC
+        bool "Enable DAC"
+        default n
+        select RT_USING_DAC
+        if BSP_USING_DAC
+            config BSP_USING_DAC1
+                bool "Enable DAC1"
+                default n
+        endif
+
     menuconfig BSP_USING_CAN
         bool "Enable CAN"
         default n

+ 1 - 0
bsp/at32/at32f437-start/board/inc/at32_msp.h

@@ -23,5 +23,6 @@ void at32_msp_qspi_init(void *instance);
 void at32_msp_sdram_init(void *instance);
 void at32_msp_emac_init(void *instance);
 void at32_msp_usb_init(void *instance);
+void at32_msp_dac_init(void *instance);
 
 #endif /* __AT32_MSP_H__ */

+ 25 - 1
bsp/at32/at32f437-start/board/src/at32_msp.c

@@ -610,5 +610,29 @@ void at32_msp_usb_init(void *instance)
         }
     }
 }
-
 #endif /* BSP_USING_USBFS */
+
+#ifdef BSP_USING_DAC
+void at32_msp_dac_init(void *instance)
+{
+    gpio_init_type gpio_init_struct;
+    dac_type *dac_x = (dac_type *)instance;
+
+    gpio_default_para_init(&gpio_init_struct);
+    gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
+#ifdef BSP_USING_DAC1
+    if(dac_x == DAC)
+    {
+        /* dac & gpio clock enable */
+        crm_periph_clock_enable(CRM_DAC_PERIPH_CLOCK, TRUE);
+        crm_periph_clock_enable(CRM_GPIOA_PERIPH_CLOCK, TRUE);
+
+        /* configure adc channel as analog output */
+        gpio_init_struct.gpio_pins = GPIO_PINS_4 | GPIO_PINS_5;
+        gpio_init_struct.gpio_mode = GPIO_MODE_ANALOG;
+        gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
+        gpio_init(GPIOA, &gpio_init_struct);
+    }
+#endif
+}
+#endif /* BSP_USING_DAC */

+ 3 - 0
bsp/at32/libraries/rt_drivers/SConscript

@@ -47,6 +47,9 @@ if GetDepend(['RT_USING_I2C', 'RT_USING_I2C_BITOPS']):
 if GetDepend(['BSP_USING_ADC']):
     src += Glob('drv_adc.c')
 
+if GetDepend(['BSP_USING_DAC']):
+    src += Glob('drv_dac.c')
+
 if GetDepend('BSP_USING_RTC'):
     src += ['drv_rtc.c']
 

+ 32 - 0
bsp/at32/libraries/rt_drivers/config/f403a_407/dac_config.h

@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2006-2021, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2023-04-18     shelton      first version
+ */
+
+#ifndef __DAC_CONFIG_H__
+#define __DAC_CONFIG_H__
+
+#include <rtthread.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if defined(BSP_USING_DAC1)
+#define DAC1_CONFIG                                                 \
+    {                                                               \
+        .name = "dac1",                                             \
+        .dac_x = DAC,                                               \
+    }
+#endif /* BSP_USING_DAC1 */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

+ 32 - 0
bsp/at32/libraries/rt_drivers/config/f423/dac_config.h

@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2006-2021, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2023-04-18     shelton      first version
+ */
+
+#ifndef __DAC_CONFIG_H__
+#define __DAC_CONFIG_H__
+
+#include <rtthread.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if defined(BSP_USING_DAC1)
+#define DAC1_CONFIG                                                 \
+    {                                                               \
+        .name = "dac1",                                             \
+        .dac_x = DAC,                                               \
+    }
+#endif /* BSP_USING_DAC1 */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

+ 32 - 0
bsp/at32/libraries/rt_drivers/config/f435_437/dac_config.h

@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2006-2021, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2023-04-18     shelton      first version
+ */
+
+#ifndef __DAC_CONFIG_H__
+#define __DAC_CONFIG_H__
+
+#include <rtthread.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if defined(BSP_USING_DAC1)
+#define DAC1_CONFIG                                                 \
+    {                                                               \
+        .name = "dac1",                                             \
+        .dac_x = DAC,                                               \
+    }
+#endif /* BSP_USING_DAC1 */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

+ 3 - 0
bsp/at32/libraries/rt_drivers/drv_config.h

@@ -25,6 +25,7 @@ extern "C" {
 #include "f403a_407/uart_config.h"
 #include "f403a_407/spi_config.h"
 #include "f403a_407/usb_config.h"
+#include "f403a_407/dac_config.h"
 #elif defined(SOC_SERIES_AT32F413)
 #include "f413/dma_config.h"
 #include "f413/uart_config.h"
@@ -44,6 +45,7 @@ extern "C" {
 #include "f423/uart_config.h"
 #include "f423/spi_config.h"
 #include "f423/usb_config.h"
+#include "f423/dac_config.h"
 #elif defined(SOC_SERIES_AT32F425)
 #include "f425/dma_config.h"
 #include "f425/uart_config.h"
@@ -54,6 +56,7 @@ extern "C" {
 #include "f435_437/uart_config.h"
 #include "f435_437/spi_config.h"
 #include "f435_437/usb_config.h"
+#include "f435_437/dac_config.h"
 #endif
 
 #ifdef __cplusplus

+ 203 - 0
bsp/at32/libraries/rt_drivers/drv_dac.c

@@ -0,0 +1,203 @@
+/*
+ * Copyright (c) 2006-2023, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2023-04-18     shelton      first version
+ */
+
+#include "drv_common.h"
+
+#if defined(BSP_USING_DAC1)
+#include "drv_config.h"
+
+//#define DRV_DEBUG
+#define LOG_TAG             "drv.dac"
+#include <drv_log.h>
+
+struct at32_dac {
+    char *name;
+    dac_type *dac_x;
+    struct rt_dac_device dac_device;
+};
+
+enum {
+#ifdef BSP_USING_DAC1
+    DAC1_INDEX,
+#endif
+};
+
+static struct at32_dac dac_config[] =
+{
+#ifdef BSP_USING_DAC1
+    DAC1_CONFIG,
+#endif
+};
+
+static dac_select_type at32_dac_get_channel(rt_uint32_t channel)
+{
+    dac_select_type at32_channel = DAC1_SELECT;
+
+    switch (channel)
+    {
+    case 1:
+        at32_channel = DAC1_SELECT;
+        break;
+    case 2:
+        at32_channel = DAC2_SELECT;
+        break;
+    default:
+        RT_ASSERT(0);
+        break;
+    }
+
+    return at32_channel;
+}
+
+static rt_err_t at32_dac_enabled(struct rt_dac_device *device, rt_uint32_t channel)
+{
+    dac_select_type dac_channel;
+    dac_type *instance;
+
+    RT_ASSERT(device != RT_NULL);
+    instance = device->parent.user_data;
+    /* prepare for mult dac instance */
+    (void)instance;
+
+    if ((channel <= 2) && (channel > 0))
+    {
+        /* set at32 dac channel */
+        dac_channel =  at32_dac_get_channel(channel);
+    }
+    else
+    {
+      LOG_E("dac channel must be 1 or 2.");
+      return -RT_ERROR;
+    }
+    dac_enable(dac_channel, TRUE);
+
+    return RT_EOK;
+}
+
+static rt_err_t at32_dac_disabled(struct rt_dac_device *device, rt_uint32_t channel)
+{
+    dac_select_type dac_channel;
+    dac_type *instance;
+
+    RT_ASSERT(device != RT_NULL);
+    instance = device->parent.user_data;
+    /* prepare for mult dac instance */
+    (void)instance;
+
+    if ((channel <= 2) && (channel > 0))
+    {
+        /* set at32 dac channel */
+        dac_channel =  at32_dac_get_channel(channel);
+    }
+    else
+    {
+      LOG_E("dac channel must be 1 or 2.");
+      return -RT_ERROR;
+    }
+    dac_enable(dac_channel, FALSE);
+
+    return RT_EOK;
+}
+
+static rt_uint8_t at32_dac_get_resolution(struct rt_dac_device *device)
+{
+    dac_type *instance;
+
+    RT_ASSERT(device != RT_NULL);
+    instance = device->parent.user_data;
+    /* prepare for mult dac instance */
+    (void)instance;
+
+    /* Only has supported DAC_ALIGN_12B_R, so it will return 12 bits */
+    return 12;
+}
+
+static rt_err_t at32_set_dac_value(struct rt_dac_device *device, rt_uint32_t channel, rt_uint32_t *value)
+{
+    dac_select_type dac_channel;
+    dac_type *instance;
+
+    RT_ASSERT(device != RT_NULL);
+    RT_ASSERT(value != RT_NULL);
+
+    instance = device->parent.user_data;
+    /* prepare for mult dac instance */
+    (void)instance;
+
+    if ((channel <= 2) && (channel > 0))
+    {
+        /* set at32 dac channel */
+        dac_channel =  at32_dac_get_channel(channel);
+    }
+    else
+    {
+        LOG_E("dac channel must be 1 or 2.");
+        return -RT_ERROR;
+    }
+
+    dac_output_buffer_enable(dac_channel, FALSE);
+    dac_trigger_enable(dac_channel, FALSE);
+
+    /* set dac channel out value*/
+    if(dac_channel == DAC1_SELECT)
+    {
+        dac_1_data_set(DAC1_12BIT_RIGHT, *value);
+    }
+    else
+    {
+        dac_2_data_set(DAC2_12BIT_RIGHT, *value);
+    }
+
+    /* start dac */
+    dac_enable(dac_channel, TRUE);
+
+    return RT_EOK;
+}
+
+static const struct rt_dac_ops at32_dac_ops =
+{
+    .disabled = at32_dac_disabled,
+    .enabled  = at32_dac_enabled,
+    .convert  = at32_set_dac_value,
+    .get_resolution = at32_dac_get_resolution,
+};
+
+static int at32_dac_init(void)
+{
+    rt_size_t obj_num;
+    int index;
+
+    obj_num = sizeof(dac_config) / sizeof(struct at32_dac);
+    rt_err_t result = 0;
+
+    for (index = 0; index < obj_num; index++) {
+        at32_msp_dac_init((void *)(dac_config[index].dac_x));
+        /* reset dac */
+        dac_reset();
+
+        /* register dac device */
+        if (rt_hw_dac_register(&dac_config[index].dac_device, dac_config[index].name, &at32_dac_ops, \
+            &dac_config[index].dac_x) == RT_EOK)
+        {
+            LOG_D("%s init success", dac_config[index].name);
+        }
+        else
+        {
+            LOG_E("%s register failed", dac_config[index].name);
+            result = -RT_ERROR;
+        }
+    }
+
+    return result;
+}
+
+INIT_DEVICE_EXPORT(at32_dac_init);
+
+#endif /* BSP_USING_DAC */