# 05.01_DAC-1.2V量程(DAC0)

## 测试步骤

配置DAC0使用1.2V量程输出电压到P0.0。

## 实测数据

## 参考代码

05.01_DAC.c

    /**
     * @brief DAC-1.2V量程(DAC0)
     * @details 配置DAC0使用1.2V量程输出电压到P0.0。
     */

    #include "lks32mc09x_gpio.h"
    #include "lks32mc09x_dac.h"
    volatile uint32_t setdacval = 0;
    /**
     * @brief 主函数
     */
    int main(void)
    {
        // 配置P0.0为DAC0输出
        GPIO_InitTypeDef GPIO_InitStruct;
        GPIO_StructInit(&GPIO_InitStruct);
        GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0;
        GPIO_InitStruct.GPIO_Mode = GPIO_Mode_ANA; // 模拟输入模式
        GPIO_Init(GPIO0, &GPIO_InitStruct);
        // 使能DAC0输出到IO口
        DAC_Enable(DAC_CHANNEL_0);
        DAC_SetRange(DAC_CHANNEL_0, DAC_RANGE_0_1V2);
        DAC_Output(DAC_CHANNEL_0, 1);

        while (1)
        {
            DAC_OutputValue(DAC_CHANNEL_0, setdacval); // 设置DAC0输出电压
        }
    }

## 使用到的库函数

库函数部分代码

    #define DAC_CHANNEL_0 0
    #define DAC_CHANNEL_1 1
    #define DAC_RANGE_0_1V2 1
    #define DAC_RANGE_1_1V2 1
    #define NVR_ADDR_DAC_0_AMC_1_20V 0x00001458
    #define NVR_ADDR_DAC_0_AMC_4_8V 0x00001450
    #define NVR_ADDR_DAC_0_DC_1_20V 0x0000145C
    #define NVR_ADDR_DAC_0_DC_4_8V 0x00001454
    #define NVR_ADDR_DAC_1_AMC_1_20V 0x00001468
    #define NVR_ADDR_DAC_1_AMC_3_0V 0x00001460
    #define NVR_ADDR_DAC_1_DC_1_20V 0x0000146C
    #define NVR_ADDR_DAC_1_DC_3_0V 0x00001464
    #define REG_RESET(reg,mask) reg &= ~(mask)
    #define REG_SET(reg,mask) reg |= (mask)
    #define REG_WRITE(reg,mask) reg = (mask)
    #define SYS0 ((SYS_TypeDef *)(SYS_BASE))
    #define SYS_MODULE_GPIO BIT11
    /**
     * @brief GPIO功能配置结构体句柄
     */
    typedef struct GPIO_InitTypeDef {
        uint32_t GPIO_Pin;
        GPIO_Mode_TypeDef GPIO_Mode;
        GPIO_PuPd_TypeDef GPIO_PuPd;
        uint32_t GPIO_PODEna;
        uint32_t GPIO_PFLT;
    };
    /**
     * @brief DAC使能
     * @param DAC_Channel DAC通道选择
     */
    void DAC_Enable(uint8_t DAC_Channel)
    {
        DAC_Cmd(DAC_Channel, ENABLE);
    }
    /**
     * @brief DAC输出数值设置（数字量）
     * @param DAC_Channel DAC通道选择
     * @param DACValue DAC输出数字量
     */
    void DAC_OutputValue(uint8_t DAC_Channel, uint32_t DACValue)
    {
        if (DACValue > 4095)
        {
            DACValue = 4095;
        }
        else
        {
            __NOP();
        }
        if (DAC_Channel == DAC_CHANNEL_0)
        {
            SYS0->AFE_DAC0 = DACValue;
        }
        else if (DAC_Channel == DAC_CHANNEL_1)
        {
            SYS0->AFE_DAC1 = DACValue >> 4; // DAC1本身是8位，DACValue是12位，这里右移4位，以方便使用
        }
        else
        {
            __NOP();
        }
    }
    /**
     * @brief DAC输出至IO口使能配置
     * @param DAC_Channel DAC通道选择
     * @param state 1Dac电压p0.0口 0停止输出到P0.0
     */
    void DAC_Output(uint8_t DAC_Channel, uint8_t state)
    {
        SYS0->PROTECT = 0x7a83;
        if (DAC_Channel == DAC_CHANNEL_0)
        {
            if (state)
            {
                SYS0->AFE_REG2 |= BIT6;
            }
            else
            {
                SYS0->AFE_REG2 &= ~BIT6;
            }
        }
        else if (DAC_Channel == DAC_CHANNEL_1)
        {
            if (state)
            {
                SYS0->AFE_REG2 |= BIT7;
            }
            else
            {
                SYS0->AFE_REG2 &= ~BIT7;
            }
        }
        else
        {
            __NOP();
        }
        SYS0->PROTECT = 0;
    }
    /**
     * @brief DAC通道时钟使能
     * @param DAC_Channel DAC通道选择
     * @param state 使能状态，1模块使能 0 模块关闭
     */
    void DAC_Cmd(uint8_t DAC_Channel, uint8_t state)
    {
        SYS0->PROTECT = 0x7a83;
        if (DAC_Channel == DAC_CHANNEL_0)
        {
            if (state)
            {
                SYS0->AFE_REG5 |= BIT1;
            }
            else
            {
                SYS0->AFE_REG5 &= ~BIT1;
            }
        }
        else
        {
            __NOP();
        }
        if (DAC_Channel == DAC_CHANNEL_1)
        {
            if (state)
            {
                SYS0->AFE_REG5 |= BIT2;
            }
            else
            {
                SYS0->AFE_REG5 &= ~BIT2;
            }
        }
        else
        {
            __NOP();
        }
        SYS0->PROTECT = 0;
    }
    /**
     * @brief 初始化GPIO
     * @param GPIOx GPIO模块指针
     * @param GPIO_InitStruct 指向包含初始化参数的GPIO_InitTypeDef结构体
     */
    void GPIO_Init(GPIO_TypeDef *GPIOx, GPIO_InitTypeDef *GPIO_InitStruct)
    {
        // 使能GPIO时钟
        SYS_ModuleClockCmd(SYS_MODULE_GPIO, ENABLE);

        // 配置引脚模式
        if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IN)
        {
            GPIOx->PIE |= GPIO_InitStruct->GPIO_Pin;  // 打开输入使能
            GPIOx->POE &= ~GPIO_InitStruct->GPIO_Pin; // 关闭输出使能
            GPIOx->PUE &= ~GPIO_InitStruct->GPIO_Pin; // 关闭上拉使能
        }
        else if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_OUT)
        {
            GPIOx->PIE &= ~GPIO_InitStruct->GPIO_Pin; // 关闭输入使能
            GPIOx->POE |= GPIO_InitStruct->GPIO_Pin;  // 使能输出
        }
        else if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IO)
        {
            GPIOx->PIE |= GPIO_InitStruct->GPIO_Pin; // 使能输入
            GPIOx->POE |= GPIO_InitStruct->GPIO_Pin; // 使能输出
        }
        else // GPIO_Mode_ANA
        {
            GPIOx->PIE &= ~GPIO_InitStruct->GPIO_Pin; // 关闭输入使能
            GPIOx->POE &= ~GPIO_InitStruct->GPIO_Pin; // 关闭输出使能
            GPIOx->PUE &= ~GPIO_InitStruct->GPIO_Pin; // 关闭上拉使能
        }

        if (GPIO_InitStruct->GPIO_PuPd == GPIO_PuPd_UP)
        {
            GPIOx->PUE |= GPIO_InitStruct->GPIO_Pin; // 使能上拉
        }
        else
        {
            GPIOx->PUE &= ~GPIO_InitStruct->GPIO_Pin; // 关闭上拉
        }
        // 配置开漏使能
        if (GPIO_InitStruct->GPIO_PODEna)
        {
            GPIOx->PODE |= GPIO_InitStruct->GPIO_Pin;
        }
        else
        {
            GPIOx->PODE &= ~GPIO_InitStruct->GPIO_Pin;
        }

        // 配置滤波使能
        if (GPIO_InitStruct->GPIO_PFLT)
        {
            GPIOx->PFLT |= GPIO_InitStruct->GPIO_Pin;
        }
        else
        {
            GPIOx->PFLT &= ~GPIO_InitStruct->GPIO_Pin;
        }
    }
    /**
     * @brief 初始化GPIO结构体为默认值
     * @param GPIO_InitStruct 指向要初始化的GPIO_InitTypeDef结构体
     */
    void GPIO_StructInit(GPIO_InitTypeDef *GPIO_InitStruct)
    {
        for (int i = 0; i < sizeof(GPIO_InitTypeDef); i++)
        {
            ((uint8_t *)GPIO_InitStruct)[i] = 0;
        }
    }
    /**
     * @brief 数字模块时钟使能
     * @param nModule 模块编号
     * @param state 使能或禁用状态
     */
    void SYS_ModuleClockCmd(uint32_t nModule, uint8_t state)
    {
        REG_WRITE(SYS0->PROTECT, 0x7a83);
        if (state)
        {
            REG_SET(SYS0->CLK_FEN, nModule);
        }
        else
        {
            REG_RESET(SYS0->CLK_FEN, nModule);
        }
        REG_WRITE(SYS0->PROTECT, 0);
    }
    /**
     * @brief 设置DAC量程
     * @param DAC_Channel DAC通道选择
     * @param DAC_RANGE_x DAC输出量程
     */
    void DAC_SetRange(uint8_t DAC_Channel, uint32_t DAC_RANGE_x)
    {
        SYS0->PROTECT = 0x7a83;
        if (DAC_Channel == DAC_CHANNEL_0)
        {
            if (DAC_RANGE_x == DAC_RANGE_0_1V2)
            {
                SYS0->AFE_REG1 |= BIT6;
                SYS0->AFE_DAC0_AMC = TRIM_Read(NVR_ADDR_DAC_0_AMC_1_20V);
                SYS0->AFE_DAC0_DC  = TRIM_Read(NVR_ADDR_DAC_0_DC_1_20V);
            }
            else
            {
                SYS0->AFE_REG1 &= ~BIT6;
                SYS0->AFE_DAC0_AMC = TRIM_Read(NVR_ADDR_DAC_0_AMC_4_8V);
                SYS0->AFE_DAC0_DC  = TRIM_Read(NVR_ADDR_DAC_0_DC_4_8V);
            }
        }
        else if (DAC_Channel == DAC_CHANNEL_1)
        {
            if (DAC_RANGE_x == DAC_RANGE_1_1V2)
            {
                SYS0->AFE_REG1 |= BIT7;
                SYS0->AFE_DAC1_AMC = TRIM_Read(NVR_ADDR_DAC_1_AMC_1_20V);
                SYS0->AFE_DAC1_DC  = TRIM_Read(NVR_ADDR_DAC_1_DC_1_20V);
            }
            else
            {
                SYS0->AFE_REG1 &= ~BIT7;
                SYS0->AFE_DAC1_AMC = TRIM_Read(NVR_ADDR_DAC_1_AMC_3_0V);
                SYS0->AFE_DAC1_DC  = TRIM_Read(NVR_ADDR_DAC_1_DC_3_0V);
            }
        }
        else
        {
            __NOP();
        }
        SYS0->PROTECT = 0;
    }