5.6 DAC 使用说明

本章说明 N32H49x 标准外设库中 DAC 驱动的文件组成与 29 个公开函数,以及 5 个示例。DAC 是 12 位数字/模拟转换器,支持 8 位与 12 位数据、DMA、噪声波/三角波/锯齿波生成与缓冲器偏移校准,可独立或双通道同步转换;触发源选择、输出缓冲与波形更新规则请配合用户手册的“数字/模拟转换(DAC)”章节阅读。

5.6.1 相关文件

相对路径 作用
firmware/n32h49x_std_periph_driver/inc/n32h49x_dac.h 定义触发源、波形、对齐方式等参数枚举,声明 29 个公开函数
firmware/n32h49x_std_periph_driver/src/n32h49x_dac.c 实现上述 29 个函数:初始化与使能、输出与校准、软件触发、波形与数据、状态与中断、时钟分频与修调
projects/n32h49x_EVAL/examples/DAC/ DAC 示例根目录,含 DoubleDataDMAModeSineWave、NoiseWaveOutput、SawtoothWaveOutput、TwoDACsTriangleWave、UserBufferCalibration 5 个示例
projects/n32h49x_EVAL/examples/DAC/DoubleDataDMAModeSineWave/ 该示例的工程目录组成:MDK-ARM/、EWARM/、inc/、src/、readme.txt
projects/n32h49x_EVAL/bsp/ 该示例引用的公共板级文件:串口日志与微秒/毫秒延时函数

5.6.2 API 参考

搜索 API共 29 个函数

以下 29 个公开函数按 n32h49x_dac.h 的声明顺序分为 6 组;每个条目给出功能摘要与 n32h49x_dac.c 中该函数正上方的注释原文。

初始化与使能

DAC_DeInit、DAC_StructInit、DAC_Init、DAC_Enable

输出、DMA 与校准

DAC_DmaEnable、DAC_CaliEnable、DAC_ConnetToExternalPinEnable、DAC_ConnetToOnChipEnable、DAC_HighDriveAbilityEnable、DAC_SignFormatModeEnable、DAC_DMADoubleDataModeEnable

软件触发

DAC_SoftTrgEnable、DAC_SoftTrgSawStepEnable、DAC_DualSoftwareTrgEnable、DAC_DualSoftwareTrgSawStepEnable

波形与数据

DAC_WaveGenerationConfig、DAC_SetSawtoothResetValue、DAC_SetSawtoothStepValue、DAC_SetData、DAC_SetDualChData

状态与中断

DAC_GetOutputDataVal、DAC_GetFlagSts、DAC_ClearFlag、DAC_ConfigInt、DAC_GetIntSts、DAC_ClearITPendingBit

时钟与修调

DAC_ConfigClkPrescaler、DAC_SetHighFrequencyMode、DAC_SetUserTrimming

void DAC_DeInit(DACX DACx)复位 DAC 寄存器。
源码注释
name    DAC_DeInit.
fun     Reset the DAC registers.
param   DACx :
          - DAC1
          - DAC2

return  none
void DAC_StructInit(DAC_InitType* DAC_InitStruct)把 DAC_InitType 结构体的所有成员填为默认值。
源码注释
name    DAC_StructInit.
fun     Fills all DAC_StructInit member with default value.
param   DAC_StructInit :
          - DAC_Trigger
          - DAC_Trigger2
          - DAC_WaveGeneration
          - DAC_LFSRUnmask_TriangleAmplitude
          - DAC_OutputBuffer
          - DAC_TriggerEnable
          - DAC_DMADoubleDataMode
          - DAC_SignedFormat
          - DAC_ConnectOnChipPeripheral
          - DAC_ConnectExternalPin
return  none
void DAC_Init(DACX DACx, DAC_InitType* DAC_InitStruct)使能或关闭指定的 DAC。
源码注释
name    DAC_Init.
fun     Enables or disables the specified DAC.
param   DACx :
          - DAC1
          - DAC2
param   DAC_InitStruct :
          - DAC_Trigger
             - DAC_Trigger_Software
             - DAC_Trigger_ATIM1_TRGO
             - DAC_Trigger_ATIM2_TRGO
             - DAC_Trigger_ATIM3_TRGO
             - DAC_Trigger_GTIM1_TRGO
             - DAC_Trigger_GTIM2_TRGO
             - DAC_Trigger_GTIM3_TRGO
             - DAC_Trigger_GTIM4_TRGO
             - DAC_Trigger_GTIM5_TRGO
             - DAC_Trigger_GTIM6_TRGO
             - DAC_Trigger_GTIM7_TRGO
             - DAC_Trigger_GTIM8_TRGO
             - DAC_Trigger_GTIM9_TRGO
             - DAC_Trigger_GTIM10_TRGO
             - DAC_Trigger_EXTI5
             - DAC_Trigger_EXTI7
             - DAC_Trigger_EXTI9
          - DAC_Trigger2
             - DAC_Trigger2_Software
             - DAC_Trigger2_ATIM1_TRGO
             - DAC_Trigger2_ATIM2_TRGO
             - DAC_Trigger2_ATIM3_TRGO
             - DAC_Trigger2_GTIM1_TRGO
             - DAC_Trigger2_GTIM2_TRGO
             - DAC_Trigger2_GTIM3_TRGO
             - DAC_Trigger2_GTIM4_TRGO
             - DAC_Trigger2_GTIM5_TRGO
             - DAC_Trigger2_GTIM6_TRGO
             - DAC_Trigger2_GTIM7_TRGO
             - DAC_Trigger2_GTIM8_TRGO
             - DAC_Trigger2_GTIM9_TRGO
             - DAC_Trigger2_GTIM10_TRGO
             - DAC_Trigger2_EXTI6
             - DAC_Trigger2_EXTI8
             - DAC_Trigger2_EXTI10
          - DAC_LFSRUnmask_TriangleAmplitude
             - DAC_LFSRUnmask_Bit0
             - DAC_LFSRUnmask_Bits1_0
             - DAC_LFSRUnmask_Bits2_0
             - DAC_LFSRUnmask_Bits3_0
             - DAC_LFSRUnmask_Bits4_0
             - DAC_LFSRUnmask_Bits5_0
             - DAC_LFSRUnmask_Bits6_0
             - DAC_LFSRUnmask_Bits7_0
             - DAC_LFSRUnmask_Bits8_0
             - DAC_LFSRUnmask_Bits9_0
             - DAC_LFSRUnmask_Bits10_0
             - DAC_LFSRUnmask_Bits11_0
             - DAC_TriangleAmplitude_1
             - DAC_TriangleAmplitude_3
             - DAC_TriangleAmplitude_7
             - DAC_TriangleAmplitude_15
             - DAC_TriangleAmplitude_31
             - DAC_TriangleAmplitude_63
             - DAC_TriangleAmplitude_127
             - DAC_TriangleAmplitude_255
             - DAC_TriangleAmplitude_511
             - DAC_TriangleAmplitude_1023
             - DAC_TriangleAmplitude_2047
             - DAC_TriangleAmplitude_4095
          - DAC_WaveGeneration
             - DAC_WaveGeneration_None
             - DAC_WaveGeneration_Noise
             - DAC_WaveGeneration_Triangle
             - DAC_WaveGeneration_SAWTOOTH_INC
             - DAC_WaveGeneration_SAWTOOTH_DEC
          - DAC_OutputBuffer
             - ENABLE
             - DISABLE
          - DAC_TriggerEnable
             - ENABLE
             - DISABLE
          - DAC_DMADoubleDataMode
             - ENABLE
             - DISABLE
          - DAC_SignedFormat
             - ENABLE
             - DISABLE
          - DAC_ConnectOnChipPeripheral
             - ENABLE
             - DISABLE
          - DAC_ConnectExternalPin
             - ENABLE
             - DISABLE
return  none
void DAC_Enable(DACX DACx, FunctionalState Cmd)使能或关闭指定的 DAC。
源码注释
name    DAC_Enable.
fun     Enables or disables the specified DAC.
param   DACx :
          - DAC1
          - DAC2
param   Cmd :
          - ENABLE
          - DISABLE
return  none
void DAC_DmaEnable(DACX DACx, FunctionalState Cmd)使能或关闭指定 DAC 的 DMA 请求。
源码注释
name    DAC_DmaEnable.
fun     Enables or disables the specified DAC DMA request.
param   DACx :
          - DAC1
          - DAC2
param   Cmd :
          - ENABLE
          - DISABLE
return  none
void DAC_CaliEnable(DACX DACx, FunctionalState Cmd)使能或关闭指定 DACx 的校准功能。
源码注释
name    DAC_CaliEnable.
fun     Enables or disables the specified DACx calibration function.
param   DACx :
          - DAC1
          - DAC2
param   Cmd :
          - ENABLE
          - DISABLE
return  none
void DAC_ConnetToExternalPinEnable(DACX DACx, FunctionalState Cmd)使能或关闭 DACx 输出连接到外部引脚。
源码注释
name    DAC_ConnetToExternalPinEnable.
fun     Enables or disables the DACx output connected to external pin.
param   DACx :
          - DAC1
          - DAC2
param   Cmd :
          - ENABLE
          - DISABLE
return  none
void DAC_ConnetToOnChipEnable(DACX DACx, FunctionalState Cmd)使能或关闭 DACx 输出连接到芯片内部。
源码注释
name    DAC_ConnetToOnChipEnable.
fun     Enables or disables the DACx output connected to on the chip.
param   DACx :
          - DAC1
          - DAC2
param   Cmd :
          - ENABLE
          - DISABLE
return  none
void DAC_HighDriveAbilityEnable(DACX DACx, FunctionalState Cmd)使能或关闭 DACx 高驱动能力输出。
源码注释
name    DAC_HighDriveAbilityEnable.
fun     Enables or disables the DACx high driver ability output.
param   DACx :
          - DAC1
          - DAC2
param   Cmd :
          - ENABLE
          - DISABLE
return  none
void DAC_SignFormatModeEnable(DACX DACx, FunctionalState Cmd)使能或关闭 DACx 有符号格式模式。
源码注释
name    DAC_SignFormatModeEnable.
fun     Enables or disables the DACx signed format mode.
param   DACx :
          - DAC1
          - DAC2
param   Cmd :
          - ENABLE
          - DISABLE
return  none
void DAC_DMADoubleDataModeEnable(DACX DACx, FunctionalState Cmd)使能或关闭 DACx DMA 双数据模式。
源码注释
name    DAC_DMADoubleDataModeEnable.
fun     Enables or disables the DACx DMA double data mode.
param   DACx :
          - DAC1
          - DAC2
param   Cmd :
          - ENABLE
          - DISABLE
return  none
void DAC_SoftTrgEnable(DACX DACx, FunctionalState Cmd)使能或关闭选中 DAC 的软件触发。
源码注释
name    DAC_SoftTrgEnable.
fun     Enables or disables software trigger of the selected DAC.
param   DACx :
          - DAC1
          - DAC2
param   Cmd :
          - ENABLE
          - DISABLE
return  none
void DAC_SoftTrgSawStepEnable(DACX DACx, FunctionalState Cmd)使能或关闭选中 DAC 锯齿波的软件触发步进信号。
源码注释
name    DAC_SoftTrgSawStepEnable.
fun     Enables or disables software trigger step signal of the selected DAC sawtooth wave .
param   DACx :
          - DAC1
          - DAC2
param   Cmd :
          - ENABLE
          - DISABLE
return  none
void DAC_DualSoftwareTrgEnable(DAC_Module *Dual_DACx, FunctionalState Cmd)同时使能或关闭两个 DAC 的软件触发。
源码注释
name    DAC_DualSoftwareTrgEnable.
fun     Enables or disables simultaneously the two DAC software triggers.
param   DACx :
          - DAC12
param   Cmd :
          - ENABLE
          - DISABLE
return  none
void DAC_DualSoftwareTrgSawStepEnable(DAC_Module *Dual_DACx, FunctionalState Cmd)同时使能或关闭两个 DAC 锯齿波的软件触发步进信号。
源码注释
name    DAC_DualSoftwareTrgEnable.
fun     Enables or disables software trigger step signal of simultaneously two DACs sawtooth wave .
param   DACx :
          - DAC12
param   Cmd :
          - ENABLE
          - DISABLE
return  none

使用提示: 源码注释的 name 字段写作 DAC_DualSoftwareTrgEnable.,与函数名 DAC_DualSoftwareTrgSawStepEnable 不一致,按函数名调用即可。

void DAC_WaveGenerationConfig(DACX DACx, uint32_t DAC_Wave)配置选中 DAC 的波形生成。
源码注释
name    DAC_WaveGenerationConfig.
fun     Configure the selected DAC wave generation. .
param   DACx :
          - DAC1
          - DAC2
param   DAC_Wave :
          - DAC_WaveGeneration_None
          - DAC_WaveGeneration_Noise
          - DAC_WaveGeneration_Triangle
          - DAC_WaveGeneration_SAWTOOTH_INC
          - DAC_WaveGeneration_SAWTOOTH_DEC
return  none
void DAC_SetSawtoothResetValue(DACX DACx, uint16_t ResetValue)设置锯齿波生成的复位数据。
源码注释
name    DAC_SetSawtoothResetValue.
fun     Set the swatooth waveform generation reset data.
param   DACx :
          - DAC1
          - DAC2
param   ResetValue:
          - the value is range from 0- 0xfff;
return  none
void DAC_SetSawtoothStepValue(DACX DACx, uint16_t StepData)设置锯齿波生成的步进数据。
源码注释
name    DAC_SetSawtoothStepValue.
fun     Set the swatooth waveform generation step data.
param   DACx :
          - DAC1
          - DAC2
param   StepData:
          - the value is range from 0- 0xfff;
return  none
void DAC_SetData(DACX DACx, uint32_t DAC_Align, uint16_t Data)设置指定 DAC 的数据保持寄存器值。
源码注释
name    DAC_SetData.
fun     Set the data holding register value for the specified DAC.
param   DACx :
          - DAC1
          - DAC2
param   DAC_Align :
          - DAC_ALIGN_R_8BIT
          - DAC_ALIGN_L_12BIT
          - DAC_ALIGN_R_12BIT
param   Data : Data to be loaded in the selected data holding register.
return  none
void DAC_SetDualChData(DAC_Module *Dual_DACx, uint32_t DAC_Align, uint16_t Data2, uint16_t Data1)设置指定双 DAC 的数据保持寄存器值。
源码注释
name    DAC_SetDualChData.
fun     Set the data holding register value for the specified dual-DAC.
param   DACx :
          - DAC12
param   DAC_Align :
          - DAC_ALIGN_R_8BIT
          - DAC_ALIGN_L_12BIT
          - DAC_ALIGN_R_12BIT
param   Data2 : Data to be loaded in the selected DACy data holding register.
param   Data1 : Data to be loaded in the selected DACx data holding register.
return  none
uint16_t DAC_GetOutputDataVal(DACX DACx)获取选中 DAC 最后一次的数据输出值。
源码注释
name    DAC_GetOutputDataVal.
fun     Get the last data output value of the selected DAC .
param   DACx :
          - DAC1
          - DAC2
return  The selected DAC data output value.
FlagStatus DAC_GetFlagSts(DACX DACx, uint32_t DAC_FLAG)获取指定 DAC 的状态标志。
源码注释
name    DAC_GetFlagSts.
fun     Get the specified DAC status flag.
param   DACx :
          - DAC1
          - DAC2
param   DAC_FLAG:
          - DAC_FLAG_DMAUDR
          - DAC_FLAG_CALCOMPLETE
          - DAC_FLAG_DORSTAT
          - DAC_FLAG_TROVC
return   FlagStatus :
          - SET
          - RESET
void DAC_ClearFlag(DACX DACx, uint32_t DAC_FLAG)清除指定 DAC 的状态标志。
源码注释
name    DAC_ClearFlag.
fun     Clear the specified DAC status flag.
param   DACx :
          - DAC1
          - DAC2
param   DAC_FLAG:
          - DAC_FLAG_DMAUDR
          - DAC_FLAG_TROVC
return   none
void DAC_ConfigInt(DACX DACx, uint32_t DAC_IT, FunctionalState Cmd)使能或关闭指定 DAC 的中断。
源码注释
name    DAC_ConfigInt.
fun     Enables or disables the specified DAC interrupts.
param   DACx :
          - DAC1
          - DAC2
param   DAC_IT:
          - DAC_INT_DMAUDRIEN
          - DAC_INT_TROVIEN
param   Cmd :
          - ENABLE
          - DISABLE
return  none
FlagStatus DAC_GetIntSts(DACX DACx, uint32_t DAC_IT)获取指定 DAC 的中断标志。
源码注释
name    DAC_GetIntSts.
fun     Get the specified DAC interrupts flag.
param   DACx :
          - DAC1
          - DAC2
param   DAC_IT:
          - DAC_INTFLAG_DMAUDR
          - DAC_INTFLAG_TROVC
return   FlagStatus :
          - SET
          - RESET
void DAC_ClearITPendingBit(DACX DACx, uint32_t DAC_IT)清除 DACx 中断挂起位。
源码注释
name    DAC_ClearITPendingBit.
fun     Clears the DACx interrupt pending bit.
param   DACx :
          - DAC1
          - DAC2
param   DAC_IT:
          - DAC_INTFLAG_DMAUDR
          - DAC_INTFLAG_TROVC
return   FlagStatus :
          - SET
          - RESET
void DAC_ConfigClkPrescaler(DAC_Module* DACx, uint8_t Prescaler)配置 DAC_CLK 预分频。
源码注释
name    DAC_ConfigClkPrescaler.
fun     Configures the DAC_CLK prescaler.
param   DACx :
          - DAC12
param   Prescaler:
          - the value range from 1 - 0xff
return   none
void DAC_SetHighFrequencyMode(DAC_Module* DACx, uint32_t mode)配置选中 DAC 的高频接口模式。
源码注释
name    DAC_SetHighFrequencyMode.
fun     Configures the high frequency interface mode for the selected DAC.
param   DACx :
          - DAC12
param   mode:
          - DAC_HIGH_FREQ_MODE_DISABLE
          - DAC_HIGH_FREQ_MODE_BELOW_80M
          - DAC_HIGH_FREQ_MODE_BELOW_160M
          - DAC_HIGH_FREQ_MODE_ABOVE_160M
return   none
void DAC_SetUserTrimming(DACX DACx, uint8_t TrimmingValue)配置选中 DAC 的偏移修调值。
源码注释
name    DAC_SetUserTrimming.
fun     Config the offset trimming value for the selected DAC .
param   DACx :
          - DAC1
          - DAC2
param   TrimmingValue: DAC new trimming value
          - the data is range from 0 - 31
return   none

5.6.3 Demo 示例说明

本节说明 DAC 的 5 个示例:DoubleDataDMAModeSineWave 用 GTIM1 触发配合 DMA 双数据模式输出正弦波,NoiseWaveOutput 用软件触发输出伪噪声波,SawtoothWaveOutput 输出递增锯齿波并由软件触发步进,TwoDACsTriangleWave 由 ATIM1 同步触发 DAC1 与 DAC2 输出两路三角波,UserBufferCalibration 演示缓冲器偏移校准并给出用户修调值。DAC1_OUT 固定为 PA4,DAC2_OUT 为 PA5。

5.6.3.1 DoubleDataDMAModeSineWave 双数据模式 DMA 正弦波输出

工程目录: projects/n32h49x_EVAL/examples/DAC/DoubleDataDMAModeSineWave/

配置系统时钟与 DAC 时钟分频→将 PA4 配置为模拟输出→配置 DMA1 通道 1 循环搬运正弦表→配置 DAC1 使用 GTIM1 触发与 DMA 双数据模式→启动 DMA 与 GTIM1 由更新事件持续触发转换

项目 源码解读
功能 GTIM1 更新事件经 TRGO 触发 DAC1,DMA1 通道 1 以循环方式把 Sine32bit 表搬运到 DAC 双数据保持寄存器;
PA4 输出 16 点正弦波,每两点打包进一个 32 位字,双数据模式在一次触发中依次转换低 16 位与高 16 位。
源码组成 src/main.c:main、RCC_Configuration、GPIO_Configuration、DMA_Config、DAC_Configuratoin、GTIM1_Init;
inc/main.h:包含 n32h49x_dac.h、n32h49x_dma.h、n32h49x_tim.h、n32h49x_gpio.h、n32h49x_rcc.h;
src/n32h49x_it.c、inc/n32h49x_it.h:中断服务程序(仅异常处理);
readme.txt:功能、环境与使用说明;
MDK-ARM/、EWARM/:Keil 与 IAR 工程。
关键配置 时钟:RCC_ConfigPclk1(RCC_HCLK_DIV4),DAC_ConfigClkPrescaler(DAC12,120) 使 DAC_CLK 约 1 MHz,DAC_SetHighFrequencyMode(DAC12,DAC_HIGH_FREQ_MODE_BELOW_160M);
引脚:PA4 模拟模式作为 DAC1_OUT;
DAC:DAC_Trigger_GTIM1_TRGO、DAC_DMADoubleDataMode=ENABLE、DAC_OutputBuffer=DISABLE、DAC_ConnectExternalPin=ENABLE;
DMA:DMA1_CH1 外设地址 DAC12->DR12CH1,缓冲区 16 字,循环模式,并调用 DMA_RequestRemap(DMA_REMAP_DAC1,DMA1_CH1,ENABLE)。
程序与数据路径 main 依次调用 RCC_Configuration、GPIO_Configuration、DMA_Config、DAC_Configuratoin、GTIM1_Init;
随后把 Sine12bit 相邻两点拼成 Sine32bit[16],使能 DMA1 通道 1 并启动 GTIM1;
GTIM1 每次更新事件输出 TRGO,DAC 触发一次读取一个 32 位字并依次转换两个采样点。
主要 API DAC_StructInit, DAC_Init, DAC_DmaEnable, DAC_Enable, DAC_ConfigClkPrescaler, DAC_SetHighFrequencyMode
验证方法 下载运行后用示波器观察 PA4,可得到 16 点正弦波;
GTIM1 触发频率为 16 MHz / 16 = 1 MHz,每触发一次转换两点,故正弦波频率约为 1 MHz / 16 = 62.5 kHz。
使用提示 硬件平台为 N32H497ZGL7_EVB;
开发环境为 KEIL MDK-ARM 5.34 或 IAR EWARM 8.50.1;
GTIM1-7/BTIM1-2 最高 120 MHz,PCLK1 不能为 1 或 2 分频,示例使用 4 分频。
核心代码解读与移植

示例先配置时钟、模拟输出引脚、DMA 与 DAC,再把正弦表两两合并为 32 位数据并启动 DMA 与定时器,由 GTIM1 更新事件持续触发转换。

数据路径: RCC_Configuration 配置 GPIO、DMA 与 DAC 时钟 → GPIO_Configuration 把 PA4 设为模拟输出 → DMA_Config 建立循环搬运 → DAC_Configuratoin 选择 GTIM1 触发与双数据模式 → GTIM1_Init 输出更新 TRGO → main 填充 Sine32bit 并启动 DMA 与 GTIM1

1. 配置系统时钟与 DAC 时钟分频。 RCC_Configuration 先把 PCLK1 设为 HCLK 的 1/4,使能 DMA1 与 GPIO 时钟,再使能 DAC12 与 GTIM1 时钟并把 DAC_CLK 分频到约 1 MHz。

src/main.csrc/main.c · RCC_Configuration
void RCC_Configuration(void)
{
    /* Enable peripheral clocks ------------------------------------------------*/
    RCC_ConfigPclk1(RCC_HCLK_DIV4);/* The maximum operating clock of GTIM1-7/BTIM1-2 is 120MHz,the division frequency of PCLK1 cannot be 1 or 2 divisions */
    /* Enable DMA1 clocks */
    RCC_EnableAHBPeriphClk(RCC_AHB_PERIPHEN_DMA1, ENABLE);
    /* Enable GPIOA, GPIOB, GPIOC clocks */
    RCC_EnableAHB1PeriphClk(RCC_AHB_PERIPHEN_GPIOA | RCC_AHB_PERIPHEN_GPIOB | RCC_AHB_PERIPHEN_GPIOC, ENABLE);
src/main.csrc/main.c · RCC_Configuration
    /* Enable DAC1 DAC2 GTIM1 clocks */
    RCC_EnableAPB1PeriphClk(RCC_APB1_PERIPHEN_DAC12 | RCC_APB1_PERIPHEN_GTIM1 ,ENABLE);
    /* Config DAC12 prescaler factor,DAC_CLK = 1M*/
    DAC_ConfigClkPrescaler(DAC12,120);
    DAC_SetHighFrequencyMode(DAC12,DAC_HIGH_FREQ_MODE_BELOW_160M);

移植到其他型号时可精简未使用的 GPIO 时钟,但 DMA1 与 DAC12、GTIM1 的时钟以及 DAC_CLK 分频必须保留。

2. 配置模拟输出引脚。 GPIO_Configuration 把 PA4 配置为模拟模式作为 DAC1_OUT。

src/main.csrc/main.c · GPIO_Configuration
void GPIO_Configuration(void)
{
    GPIO_InitType GPIO_InitStructure;
    /* DAC1_OUT  */
    GPIO_InitStructure.Pin        = GPIO_PIN_4 ;
    GPIO_InitStructure.GPIO_Mode  = GPIO_MODE_ANALOG;
    GPIO_InitPeripheral(GPIOA, &GPIO_InitStructure);
}

更换评估板时只需修改引脚号,模拟模式与 DAC1_OUT 的对应关系由芯片引脚复用决定。

3. 配置 DAC。 DAC_Configuratoin 选择 GTIM1 触发、关闭输出缓冲、连接外部引脚,并使能双数据模式、DMA、触发与 DAC1 本体。

src/main.csrc/main.c · DAC_Configuratoin
void DAC_Configuratoin(void)
{
    DAC_InitType DAC_InitStructure;

    DAC_StructInit(&DAC_InitStructure);
    /* DAC1 Configuration */
    DAC_InitStructure.DAC_Trigger                       = DAC_Trigger_GTIM1_TRGO;
    DAC_InitStructure.DAC_WaveGeneration                = DAC_WaveGeneration_None;
    DAC_InitStructure.DAC_DMADoubleDataMode             = ENABLE;
    DAC_InitStructure.DAC_OutputBuffer                  = DISABLE;
    DAC_InitStructure.DAC_ConnectOnChipPeripheral       = DISABLE;
    DAC_InitStructure.DAC_ConnectExternalPin            = ENABLE;
    DAC_InitStructure.DAC_TriggerEnable                 = ENABLE;
    DAC_Init(DAC1, &DAC_InitStructure);
    /* Enable DAC1 DMA function */
    DAC_DmaEnable(DAC1, ENABLE);
    /* Enable DAC1  */
    DAC_Enable(DAC1, ENABLE);
}

双数据模式要求 DMA 每次搬运一个 32 位字;关闭输出缓冲可提高刷新率,但需根据负载评估建立时间。

4. 配置 DMA 通道。 DMA_Config 让 DMA1_CH1 从 Sine32bit 循环搬运 16 个字到 DAC12->DR12CH1,并把 DMA 请求映射到 DAC1。

src/main.csrc/main.c · DMA_Config
void DMA_Config(void)
{
    DMA_InitType DMA_InitStructure;
    DMA_StructInit(&DMA_InitStructure);
    DMA_InitStructure.PeriphAddr     = (uint32_t)&DAC12->DR12CH1;
    DMA_InitStructure.MemAddr        = (uint32_t)Sine32bit;
    DMA_InitStructure.Direction      = DMA_DIR_PERIPH_DST;
    DMA_InitStructure.BufSize        = 16;
    DMA_InitStructure.PeriphInc      = DMA_PERIPH_INC_DISABLE;
    DMA_InitStructure.MemoryInc      = DMA_MEM_INC_ENABLE;
    DMA_InitStructure.PeriphDataSize = DMA_PERIPH_DATA_WIDTH_WORD;
    DMA_InitStructure.MemDataSize    = DMA_MEM_DATA_WIDTH_WORD;
    DMA_InitStructure.CircularMode   = DMA_MODE_CIRCULAR;
    DMA_InitStructure.Priority       = DMA_PRIORITY_HIGH;
    DMA_InitStructure.Mem2Mem        = DMA_M2M_DISABLE;
    DMA_Init(DMA1_CH1, &DMA_InitStructure);
    
    DMA_RequestRemap(DMA_REMAP_DAC1, DMA1_CH1,ENABLE);
}

搬运用字宽(WORD)与双数据模式匹配,循环模式保证正弦表自动重复;DMA_RequestRemap 必须把 DAC1 请求接到通道 1。

5. 配置触发并启动。 GTIM1_Init 把 GTIM1 更新事件输出为 TRGO 作为 DAC 触发源,main 在填充正弦表后使能 DMA 并启动定时器。

src/main.csrc/main.c · GTIM1_Init
void GTIM1_Init(void)
{
    TIM_TimeBaseInitType TIM_TimeBaseStructure;
    uint16_t  PrescalerValue ;
    PrescalerValue = (uint32_t)(SystemCoreClock / 16000000) - 1;
    /* GTIM1 Configuration */
    /* Time base configuration */
    TIM_InitTimBaseStruct(&TIM_TimeBaseStructure);
    TIM_TimeBaseStructure.Period    = 16-1; 
    TIM_TimeBaseStructure.Prescaler = PrescalerValue;
    TIM_TimeBaseStructure.ClkDiv    = TIM_CLK_DIV1;
    TIM_TimeBaseStructure.CounterMode   = TIM_CNT_MODE_UP;
    TIM_InitTimeBase(GTIM1, &TIM_TimeBaseStructure);

    /* GTIM1 TRGO selection */
    TIM_SelectOutputTrig(GTIM1, TIM_TRGO_SRC_UPDATE);
}
src/main.csrc/main.c · main
    /* Fill Sine32bit table */
    for (index = 0; index < 16; index++ )
    {
        Sine32bit[index] = (Sine12bit[2*index+1] << 16) + (Sine12bit[2*index]);
    }
    /* Enable DMA1 channel1 */
    DMA_EnableChannel(DMA1_CH1, ENABLE);
src/main.csrc/main.c · main
    TIM_Enable(GTIM1, ENABLE);

触发频率由 GTIM1 周期与预分频共同决定;更换波形表时保持 Sine32bit 元素个数与 DMA BufSize 一致。

对应源码: src/main.c

5.6.3.2 NoiseWaveOutput 噪声波输出

工程目录: projects/n32h49x_EVAL/examples/DAC/NoiseWaveOutput/

配置系统与 DAC 时钟→将 PA4 配置为模拟输出→配置 DAC1 产生噪声波并写入初始数据→主循环软件触发产生噪声

项目 源码解读
功能 DAC1 以软件触发方式输出伪噪声波,LFSR 掩码为 DAC_LFSRUnmask_Bit0;
主循环反复触发转换,PA4 输出随 LFSR 变化的噪声电压。
源码组成 src/main.c:main、RCC_Configuration、GPIO_Configuration、DAC_Configuratoin;
inc/main.h:包含 n32h49x_dac.h、n32h49x_gpio.h、n32h49x_rcc.h、delay.h;
src/n32h49x_it.c、inc/n32h49x_it.h:中断服务程序(仅异常处理);
readme.txt:功能、环境与使用说明;
MDK-ARM/、EWARM/:Keil 与 IAR 工程。
关键配置 时钟:DAC_ConfigClkPrescaler(DAC12,120) 使 DAC_CLK 约 1 MHz,DAC_SetHighFrequencyMode(DAC12,DAC_HIGH_FREQ_MODE_BELOW_160M);
引脚:PA4 模拟模式作为 DAC1_OUT;
DAC:DAC_Trigger_Software、DAC_WaveGeneration_Noise、DAC_LFSRUnmask_Bit0、DAC_OutputBuffer=DISABLE、DAC_TriggerEnable=ENABLE;
初始数据:DAC_SetData(DAC1,DAC_ALIGN_R_12BIT,4094)。
程序与数据路径 main 先调用 RCC_Configuration 与 GPIO_Configuration,再调用 DAC_Configuratoin 配置并使能 DAC1;
while(1) 中反复 DAC_SoftTrgEnable 触发一次转换并延时 1 us,LFSR 在两次触发之间推进,产生伪随机噪声序列。
主要 API DAC_StructInit, DAC_Init, DAC_Enable, DAC_SetData, DAC_SoftTrgEnable, DAC_ConfigClkPrescaler, DAC_SetHighFrequencyMode
验证方法 下载运行后用示波器观察 PA4,可看到随机变化的噪声波形;
改变 DAC_LFSRUnmask_Bit0 或主循环延时,可调整噪声的频率与形态。
使用提示 硬件平台为 N32H497ZGL7_EVB;
开发环境为 KEIL MDK-ARM 5.34 或 IAR EWARM 8.50.1;
软件触发前必须使能触发,否则 DAC_SWTRGx 不产生效果。
核心代码解读与移植

示例配置 DAC1 产生噪声波,主循环通过软件触发让 LFSR 推进并更新输出。

数据路径: RCC_Configuration 配置 GPIO 与 DAC 时钟 → GPIO_Configuration 把 PA4 设为模拟输出 → DAC_Configuratoin 选择噪声波与软件触发 → main 主循环 DAC_SoftTrgEnable 触发转换

1. 配置系统与 DAC 时钟。 RCC_Configuration 使能 GPIO 与 DAC12 时钟,并把 DAC_CLK 分频到约 1 MHz。

src/main.csrc/main.c · RCC_Configuration
void RCC_Configuration(void)
{
    /* Enable GPIOA, GPIOB, GPIOC clocks */
    RCC_EnableAHB1PeriphClk(RCC_AHB_PERIPHEN_GPIOA | RCC_AHB_PERIPHEN_GPIOB | RCC_AHB_PERIPHEN_GPIOC, ENABLE);
src/main.csrc/main.c · RCC_Configuration
    /* Enable DAC1 clocks */
    RCC_EnableAPB1PeriphClk(RCC_APB1_PERIPHEN_DAC12 ,ENABLE);
    /* Config DAC12 prescaler factor,DAC_CLK = 1M*/
    DAC_ConfigClkPrescaler(DAC12,120);
    DAC_SetHighFrequencyMode(DAC12,DAC_HIGH_FREQ_MODE_BELOW_160M);

移植时保留 DAC12 时钟与分频设置即可,GPIO 时钟按实际使用的端口裁剪。

2. 配置模拟输出引脚。 GPIO_Configuration 把 PA4 配置为模拟模式作为 DAC1_OUT。

src/main.csrc/main.c · GPIO_Configuration
void GPIO_Configuration(void)
{
    GPIO_InitType GPIO_InitStructure;
    // DAC1_OUT 
    GPIO_InitStruct(&GPIO_InitStructure);
    GPIO_InitStructure.Pin        = GPIO_PIN_4  ;
    GPIO_InitStructure.GPIO_Mode  = GPIO_MODE_ANALOG;
    GPIO_InitPeripheral(GPIOA, &GPIO_InitStructure);
}

更换评估板时只需修改引脚号;噪声波只经 PA4 输出,不占用其他外设。

3. 配置 DAC 噪声波。 DAC_Configuratoin 选择软件触发与噪声波,关闭输出缓冲并使能触发,然后写入初始数据。

src/main.csrc/main.c · DAC_Configuratoin
void DAC_Configuratoin(void)
{
    DAC_InitType DAC_InitStructure;

    DAC_StructInit(&DAC_InitStructure);
    /* DAC1 Configuration */
    DAC_InitStructure.DAC_Trigger                       = DAC_Trigger_Software;
    DAC_InitStructure.DAC_WaveGeneration                = DAC_WaveGeneration_Noise;
    DAC_InitStructure.DAC_LFSRUnmask_TriangleAmplitude  = DAC_LFSRUnmask_Bit0;
    DAC_InitStructure.DAC_OutputBuffer                  = DISABLE;
    DAC_InitStructure.DAC_ConnectOnChipPeripheral       = DISABLE;
    DAC_InitStructure.DAC_ConnectExternalPin            = ENABLE;
    DAC_InitStructure.DAC_TriggerEnable                 = ENABLE;
    DAC_Init(DAC1, &DAC_InitStructure);

    /* Enable DAC1  */
    DAC_Enable(DAC1, ENABLE);

    /* Set DAC1 DHR12R register */
    DAC_SetData(DAC1,DAC_ALIGN_R_12BIT, 4094);
}

LFSR 掩码决定噪声幅度,DAC_SetData 设定 LFSR 的基准值;噪声模式下数值由硬件在每次触发时更新。

4. 主循环软件触发。 初始化完成后,while(1) 反复触发一次转换并延时 1 us。

src/main.csrc/main.c · main
    while (1)
    {
        DAC_SoftTrgEnable(DAC1, ENABLE);
        systick_delay_us(1);
    }

触发间隔决定噪声更新速率;缩短延时可以提高噪声的等效带宽。

对应源码: src/main.c

5.6.3.3 SawtoothWaveOutput 锯齿波输出

工程目录: projects/n32h49x_EVAL/examples/DAC/SawtoothWaveOutput/

配置时钟→配置 PA4 模拟输出与 PA5 推挽输出→配置 DAC1 递增锯齿波与软件步进触发→配置 ATIM1 更新中断与 TRGO→主循环每 2 ms 推进一次锯齿波台阶

项目 源码解读
功能 DAC1 输出递增锯齿波,复位值 0x100、步进值 60;
ATIM1 更新中断置位 DAC_Reset_Flag,主循环连续调用 150 次 DAC_SoftTrgSawStepEnable,锯齿波从复位值逐步上升并在达到满量程后回卷。
源码组成 src/main.c:main、RCC_Configuration、GPIO_Configuration、DAC_Configuratoin、NVIC_Configuration、TIM_Configuration;
inc/main.h:包含 n32h49x_dac.h、n32h49x_tim.h、n32h49x_gpio.h、n32h49x_rcc.h、delay.h;
src/n32h49x_it.c、inc/n32h49x_it.h:中断服务程序(含置位 DAC_Reset_Flag 的 ATIM1_IRQHandler);
readme.txt:功能、环境与使用说明;
MDK-ARM/、EWARM/:Keil 与 IAR 工程。
关键配置 时钟:DAC_ConfigClkPrescaler(DAC12,120)、DAC_SetHighFrequencyMode(DAC12,DAC_HIGH_FREQ_MODE_BELOW_160M),并使能 ATIM1 总线时钟;
引脚:PA4 模拟输出,PA5 推挽输出用于观察触发;
DAC:DAC_WaveGeneration_SAWTOOTH_INC、DAC_Trigger_ATIM1_TRGO、DAC_Trigger2_Software、DAC_SetSawtoothResetValue(DAC1,0x100)、DAC_SetSawtoothStepValue(DAC1,60);
定时器:ATIM1 周期 1500、TRGO 为更新事件并开启更新中断。
程序与数据路径 main 依次调用 RCC_Configuration、GPIO_Configuration、DAC_Configuratoin、NVIC_Configuration、TIM_Configuration;
ATIM1_IRQHandler 在更新中断里置位 DAC_Reset_Flag;
while(1) 中当标志为 1 且步进计数小于 150 时触发一次锯齿波步进并延时 2 ms,达到 150 次后清零重新开始。
主要 API DAC_Init, DAC_SetSawtoothResetValue, DAC_SetSawtoothStepValue, DAC_Enable, DAC_SoftTrgSawStepEnable
验证方法 下载运行后用示波器观察 PA4,可看到由 150 级台阶组成的递增锯齿波;
修改 DAC_SetSawtoothStepValue 的步长或复位值可改变波形幅度与台阶高度。
使用提示 硬件平台为 N32H497ZGL7_EVB;
开发环境为 KEIL MDK-ARM 5.34 或 IAR EWARM 8.50.1;
锯齿波的台阶推进由软件步进触发控制,需配合 DAC_SoftTrgSawStepEnable;
PA5 作为辅助输出便于用示波器同步观察。
核心代码解读与移植

示例配置 DAC1 输出递增锯齿波,由 ATIM1 更新事件周期置位标志,主循环按标志逐级推进锯齿波台阶。

数据路径: RCC_Configuration 配置 GPIO、ATIM1 与 DAC 时钟 → GPIO_Configuration 设置 PA4 模拟输出与 PA5 推挽输出 → DAC_Configuratoin 选择递增锯齿波与软件步进触发 → TIM_Configuration 令 ATIM1 更新事件输出 TRGO 并开中断 → main 主循环按标志调用 DAC_SoftTrgSawStepEnable 步进

1. 配置系统时钟。 RCC_Configuration 使能 GPIO、ATIM1 与 DAC12 时钟,并把 DAC_CLK 分频到约 1 MHz。

src/main.csrc/main.c · RCC_Configuration
void RCC_Configuration(void)
{
    /* Enable GPIOA, GPIOB, GPIOC clocks */
    RCC_EnableAHB1PeriphClk(RCC_AHB_PERIPHEN_GPIOA | RCC_AHB_PERIPHEN_GPIOB | RCC_AHB_PERIPHEN_GPIOC, ENABLE);
    RCC_EnableAHBPeriphClk(RCC_AHB_PERIPHEN_ATIM1,ENABLE);
    /* Enable DAC1 DAC2 clocks */
    RCC_EnableAPB1PeriphClk(RCC_APB1_PERIPHEN_DAC12 ,ENABLE);
    /* Config DAC12 prescaler factor,DAC_CLK = 1M*/
    DAC_ConfigClkPrescaler(DAC12,120);
    DAC_SetHighFrequencyMode(DAC12,DAC_HIGH_FREQ_MODE_BELOW_160M);

移植时保留 ATIM1、DAC12 时钟与分频设置;ATIM1 是高级定时器,其总线时钟需与触发频率目标匹配。

2. 配置输出引脚。 GPIO_Configuration 把 PA4 设为模拟输出用于锯齿波,PA5 设为推挽输出用于辅助观察。

src/main.csrc/main.c · GPIO_Configuration
void GPIO_Configuration(void)
{
    GPIO_InitType GPIO_InitStructure;  
    /* DAC1_OUT */
    GPIO_InitStruct(&GPIO_InitStructure);
    GPIO_InitStructure.Pin        = GPIO_PIN_4  ;
    GPIO_InitStructure.GPIO_Mode  = GPIO_MODE_ANALOG;
    GPIO_InitPeripheral(GPIOA, &GPIO_InitStructure);

    GPIO_InitStructure.Pin        = GPIO_PIN_5  ;
    GPIO_InitStructure.GPIO_Mode  = GPIO_MODE_OUTPUT_PP;
    GPIO_InitPeripheral(GPIOA, &GPIO_InitStructure);
}

PA4 必须为模拟模式,PA5 为推挽输出;更换引脚时保持模式与用途对应。

3. 配置 DAC 锯齿波。 DAC_Configuratoin 选择 ATIM1 触发与递增锯齿波,并设置复位值与步进值。

src/main.csrc/main.c · DAC_Configuratoin
void DAC_Configuratoin(void)
{
    DAC_InitType DAC_InitStructure;

    DAC_StructInit(&DAC_InitStructure);
    /* DAC1 Configuration */
    DAC_InitStructure.DAC_Trigger                       = DAC_Trigger_ATIM1_TRGO;
    DAC_InitStructure.DAC_Trigger2                      = DAC_Trigger2_Software;
    DAC_InitStructure.DAC_WaveGeneration                = DAC_WaveGeneration_SAWTOOTH_INC;
    DAC_InitStructure.DAC_OutputBuffer                  = DISABLE;
    DAC_InitStructure.DAC_ConnectOnChipPeripheral       = DISABLE;
    DAC_InitStructure.DAC_ConnectExternalPin            = ENABLE;
    DAC_InitStructure.DAC_TriggerEnable                 = ENABLE;
    DAC_Init(DAC1, &DAC_InitStructure);
    DAC_SetSawtoothResetValue(DAC1,0x100);
    DAC_SetSawtoothStepValue(DAC1,60);
    /* Enable DAC1  */
    DAC_Enable(DAC1, ENABLE);
}

DAC_Trigger2 为步进触发;锯齿波从复位值开始,每次步进增加 DAC_SetSawtoothStepValue 设定的量,回卷到复位值后重新递增。

4. 配置 ATIM1 触发与中断。 TIM_Configuration 设置 ATIM1 周期并把更新事件输出为 TRGO,同时开启更新中断。

src/main.csrc/main.c · TIM_Configuration
void TIM_Configuration(void)
{
    /* Compute the prescaler value */
    uint16_t  PrescalerValue = 0;
    TIM_TimeBaseInitType TIM_TimeBaseStructure;

    PrescalerValue = (uint32_t)(SystemCoreClock / 5000) - 1;
    /* Time base configuration */
    TIM_InitTimBaseStruct(&TIM_TimeBaseStructure);
    TIM_TimeBaseStructure.Period        = 1500;         //300ms Trigger DAC
    TIM_TimeBaseStructure.Prescaler     = PrescalerValue;
    TIM_TimeBaseStructure.ClkDiv        = TIM_CLK_DIV1;
    TIM_TimeBaseStructure.CounterMode   = TIM_CNT_MODE_UP;

    TIM_InitTimeBase(ATIM1, &TIM_TimeBaseStructure);

    /* Prescaler configuration */
    TIM_ConfigPrescaler(ATIM1, PrescalerValue, TIM_PSC_RELOAD_MODE_IMMEDIATE);
    TIM_SelectOutputTrig(ATIM1,TIM_TRGO_SRC_UPDATE);
    /* ATIM1 enable update irq */
    TIM_ConfigInt(ATIM1, TIM_INT_UPDATE, ENABLE);

    /* ATIM1 enable counter */
    TIM_Enable(ATIM1, ENABLE);
}

周期与预分频共同决定触发间隔;移植时按目标刷新周期重新计算 Period 与 Prescaler。

5. 主循环推进锯齿波台阶。 main 在检测到更新中断标志后,连续触发 150 次步进,每次延时 2 ms。

src/main.csrc/main.c · main
    while (1)
    {
        if(DAC_Reset_Flag == 1)
        {
            if(DAC_Step_Index < DAC_Step_Num )
            {   
                DAC_SoftTrgSawStepEnable(DAC1,ENABLE);
                systick_delay_ms(2);
                DAC_Step_Index++;
            }
            else
            {
                DAC_Step_Index = 0;
                DAC_Reset_Flag = 0;
            }
        }
    }
}

DAC_Step_Num 为 150,对应 150 级台阶;改变步长或台阶数会改变锯齿波的上升斜率。

对应源码: src/main.c

5.6.3.4 TwoDACsTriangleWave 双 DAC 三角波输出

工程目录: projects/n32h49x_EVAL/examples/DAC/TwoDACsTriangleWave/

配置时钟→将 PA4 与 PA5 配置为模拟输出→配置 DAC1 与 DAC2 三角波并写入双通道数据→配置 ATIM1 更新事件触发→使能 ATIM1 计数持续触发

项目 源码解读
功能 DAC1、DAC2 由同一 ATIM1 更新事件同步触发输出三角波,DAC1 幅度为 2047、DAC2 幅度为 1023;
PA4 与 PA5 分别输出两路三角波,初始数据通过 DAC_SetDualChData 一次写入。
源码组成 src/main.c:main、RCC_Configuration、GPIO_Configuration、DAC_Configuratoin、ATIM1_Init;
inc/main.h:包含 n32h49x_dac.h、n32h49x_tim.h、n32h49x_gpio.h、n32h49x_rcc.h;
src/n32h49x_it.c、inc/n32h49x_it.h:中断服务程序(仅异常处理);
readme.txt:功能、环境与使用说明;
MDK-ARM/、EWARM/:Keil 与 IAR 工程。
关键配置 时钟:使能 ATIM1 与 DAC12 总线时钟,DAC_ConfigClkPrescaler(DAC12,120) 使 DAC_CLK 约 1 MHz,DAC_SetHighFrequencyMode(DAC12,DAC_HIGH_FREQ_MODE_BELOW_160M);
引脚:PA4、PA5 均配置为模拟模式;
DAC:DAC_Trigger_ATIM1_TRGO、DAC_WaveGeneration_Triangle,DAC1 幅度 DAC_TriangleAmplitude_2047、DAC2 幅度 DAC_TriangleAmplitude_1023,并用 DAC_SetDualChData(DAC12,DAC_ALIGN_R_12BIT,0x100,0x100) 写初始数据;
定时器:ATIM1 周期 16、TRGO 为更新事件。
程序与数据路径 main 依次调用 RCC_Configuration、GPIO_Configuration、DAC_Configuratoin、ATIM1_Init;
DAC_Configuratoin 先配置 DAC1,再复用同一结构体修改幅度后配置 DAC2,然后写入双通道数据并分别使能两路;
最后 TIM_Enable(ATIM1,ENABLE) 启动定时器,两路 DAC 在每次更新事件同步转换。
主要 API DAC_Init, DAC_SetDualChData, DAC_Enable, DAC_ConfigClkPrescaler, DAC_SetHighFrequencyMode
验证方法 下载运行后用示波器同时观察 PA4 与 PA5,可看到两路频率相同、幅度不同的三角波;
两路由同一触发同步,相位一致。
使用提示 硬件平台为 N32H497ZGL7_EVB;
开发环境为 KEIL MDK-ARM 5.34 或 IAR EWARM 8.50.1;
两路共用 DAC_InitType 结构体,配置 DAC2 时只改需要不同的字段,其余沿用 DAC1 的设置。
核心代码解读与移植

示例用同一 ATIM1 更新事件同步触发 DAC1、DAC2,两路各自产生不同幅度的三角波。

数据路径: RCC_Configuration 配置 GPIO、ATIM1 与 DAC 时钟 → GPIO_Configuration 把 PA4 与 PA5 设为模拟输出 → DAC_Configuratoin 配置两路三角波并用 DAC_SetDualChData 写初始数据 → ATIM1_Init 令更新事件输出 TRGO → main 使能 ATIM1 持续触发

1. 配置系统时钟。 RCC_Configuration 使能 GPIO、ATIM1 与 DAC12 时钟,并把 DAC_CLK 分频到约 1 MHz。

src/main.csrc/main.c · RCC_Configuration
void RCC_Configuration(void)
{
    /* Enable GPIOA, GPIOB, GPIOC clocks */
    RCC_EnableAHB1PeriphClk(RCC_AHB_PERIPHEN_GPIOA | RCC_AHB_PERIPHEN_GPIOB | RCC_AHB_PERIPHEN_GPIOC, ENABLE);
    /* Enable ATIM1 clocks */
    RCC_EnableAHBPeriphClk(RCC_AHB_PERIPHEN_ATIM1, ENABLE);
src/main.csrc/main.c · RCC_Configuration
    /* Enable DAC1 DAC2 clocks */
    RCC_EnableAPB1PeriphClk(RCC_APB1_PERIPHEN_DAC12 ,ENABLE);

    DAC_ConfigClkPrescaler(DAC12,120);
    DAC_SetHighFrequencyMode(DAC12,DAC_HIGH_FREQ_MODE_BELOW_160M);
}

移植时保留 ATIM1 与 DAC12 时钟;DAC_CLK 分频影响转换刷新率与缓冲建立时间。

2. 配置输出引脚。 GPIO_Configuration 把 PA4、PA5 都配置为模拟模式,分别对应 DAC1_OUT 与 DAC2_OUT。

src/main.csrc/main.c · GPIO_Configuration
void GPIO_Configuration(void)
{
    GPIO_InitType GPIO_InitStructure;
    // DAC1_OUT DAC2_OUT
    GPIO_InitStruct(&GPIO_InitStructure);
    GPIO_InitStructure.Pin        = GPIO_PIN_4 | GPIO_PIN_5 ;
    GPIO_InitStructure.GPIO_Mode  = GPIO_MODE_ANALOG;
    GPIO_InitPeripheral(GPIOA, &GPIO_InitStructure);
}

两路输出引脚可一次配置;更换引脚时保持模拟模式与 DAC 通道的对应关系。

3. 配置两路 DAC。 DAC_Configuratoin 先配置 DAC1 的三角波幅度,再改幅度配置 DAC2,然后用 DAC_SetDualChData 写双通道数据并分别使能。

src/main.csrc/main.c · DAC_Configuratoin
void DAC_Configuratoin(void)
{
    DAC_InitType DAC_InitStructure;

    DAC_StructInit(&DAC_InitStructure);
    /* DAC1 Configuration */
    DAC_InitStructure.DAC_Trigger                       = DAC_Trigger_ATIM1_TRGO;
    DAC_InitStructure.DAC_WaveGeneration                = DAC_WaveGeneration_Triangle;
    DAC_InitStructure.DAC_LFSRUnmask_TriangleAmplitude  = DAC_TriangleAmplitude_2047;
    DAC_InitStructure.DAC_OutputBuffer                  = DISABLE;
    DAC_InitStructure.DAC_ConnectOnChipPeripheral       = DISABLE;
    DAC_InitStructure.DAC_ConnectExternalPin            = ENABLE;
    DAC_InitStructure.DAC_TriggerEnable                 = ENABLE;
    DAC_Init(DAC1, &DAC_InitStructure);
    
    /* DAC2 Configuration */
    DAC_InitStructure.DAC_LFSRUnmask_TriangleAmplitude  = DAC_TriangleAmplitude_1023;
    DAC_Init(DAC2, &DAC_InitStructure);
    
    /* Set DAC1 DAC2 DHR12R register */
    DAC_SetDualChData(DAC12,DAC_ALIGN_R_12BIT, 0x100, 0x100);
    /* Enable DAC1  */
    DAC_Enable(DAC1, ENABLE);
    /* Enable DAC2  */
    DAC_Enable(DAC2, ENABLE);
}

两个 DAC 共用触发源与波形设置,仅三角波幅度不同;DAC_SetDualChData(DAC12,...) 一次写入两路的初始数据。

4. 配置 ATIM1 触发。 ATIM1_Init 设置 ATIM1 周期并把更新事件输出为 TRGO。

src/main.csrc/main.c · ATIM1_Init
void ATIM1_Init(void)
{
    TIM_TimeBaseInitType TIM_TimeBaseStructure;
    uint16_t PrescalerValue ;
    PrescalerValue = (uint32_t)(SystemCoreClock / 16000000) - 1;
    /* ATIM1 Configuration */
    TIM_InitTimBaseStruct(&TIM_TimeBaseStructure);
    TIM_TimeBaseStructure.Period    = 16-1;
    TIM_TimeBaseStructure.Prescaler = PrescalerValue;
    TIM_TimeBaseStructure.ClkDiv    = TIM_CLK_DIV1;
    TIM_TimeBaseStructure.CounterMode   = TIM_CNT_MODE_UP;
    TIM_InitTimeBase(ATIM1, &TIM_TimeBaseStructure);

    /* ATIM1 TRGO selection */
    TIM_SelectOutputTrig(ATIM1, TIM_TRGO_SRC_UPDATE);
}

ATIM1 的触发频率决定三角波的台阶速率;移植时按目标波形频率重新计算周期。

5. 启动触发。 main 在初始化完成后使能 ATIM1 计数,两路 DAC 在每次更新事件同步转换。

src/main.csrc/main.c · main
    /* ATIM1 enable counter */
    TIM_Enable(ATIM1, ENABLE);

只要 ATIM1 持续计数,两路三角波就会自动刷新,无需主循环干预。

对应源码: src/main.c

5.6.3.5 UserBufferCalibration 缓冲器偏移校准

工程目录: projects/n32h49x_EVAL/examples/DAC/UserBufferCalibration/

配置时钟与 PA4 模拟输出→初始化串口日志→使能 DAC1 校准并启动→逐一写修调值直到校准完成→打印修调值或失败信息

项目 源码解读
功能 对 DAC1 的缓冲器做偏移校准:先使能校准与 DAC1,再循环写入候选修调值并检查 DAC_FLAG_CALCOMPLETE;
校准成功后把修调值通过串口打印,失败则提示修调无效。
源码组成 src/main.c:main、RCC_Configuration、GPIO_Configuration、Start_UserTrimming;
inc/main.h:包含 n32h49x_dac.h、n32h49x_gpio.h、n32h49x_rcc.h、delay.h、log.h;
src/n32h49x_it.c、inc/n32h49x_it.h:中断服务程序(仅异常处理);
readme.txt:功能、环境与使用说明;
MDK-ARM/、EWARM/:Keil 与 IAR 工程。
关键配置 时钟:DAC_ConfigClkPrescaler(DAC12,120) 使 DAC_CLK 约 1 MHz,DAC_SetHighFrequencyMode(DAC12,DAC_HIGH_FREQ_MODE_BELOW_160M);
引脚:PA4 模拟模式作为 DAC1_OUT;
DAC:软件触发、DAC_WaveGeneration_None、DAC_OutputBuffer=ENABLE(校准要求缓冲器使能)、DAC_CaliEnable(DAC1,ENABLE);
校准:循环 32 次 DAC_SetUserTrimming(DAC1,index),每次延时 100 us 并检查 DAC_FLAG_CALCOMPLETE。
程序与数据路径 main 调用 RCC_Configuration、log_init、GPIO_Configuration,然后调用 Start_UserTrimming(&Trim_Value);
Start_UserTrimming 内部配置并使能 DAC1、开启校准,随后在循环里逐个尝试修调值;
一旦 DAC_GetFlagSts(DAC1,DAC_FLAG_CALCOMPLETE) 置位就返回 SUCCESS 并回写修调值,否则循环结束后返回 ERROR。
主要 API DAC_StructInit, DAC_Init, DAC_CaliEnable, DAC_Enable, DAC_SetUserTrimming, DAC_GetFlagSts
验证方法 下载运行后通过串口日志查看结果:成功时打印修调值,失败时打印修调无效信息,可据此判断校准是否完成。
使用提示 硬件平台为 N32H497ZGL7_EVB;
开发环境为 KEIL MDK-ARM 5.34 或 IAR EWARM 8.50.1;
校准必须在输出缓冲器使能的条件下进行;
实测得到的修调值可在正式应用启动时用 DAC_SetUserTrimming 写入。
核心代码解读与移植

示例对 DAC1 的缓冲器做一次偏移校准,并返回可用的用户修调值。

数据路径: RCC_Configuration 配置 GPIO 与 DAC 时钟 → GPIO_Configuration 把 PA4 设为模拟输出 → Start_UserTrimming 使能缓冲器与校准并循环尝试修调值 → main 打印校准结果

1. 配置系统时钟。 RCC_Configuration 使能 GPIO 与 DAC12 时钟,并把 DAC_CLK 分频到约 1 MHz。

src/main.csrc/main.c · RCC_Configuration
void RCC_Configuration(void)
{
    /* Enable GPIOA, GPIOB, GPIOC clocks */
    RCC_EnableAHB1PeriphClk(RCC_AHB_PERIPHEN_GPIOA | RCC_AHB_PERIPHEN_GPIOB | RCC_AHB_PERIPHEN_GPIOC, ENABLE);
src/main.csrc/main.c · RCC_Configuration
    /* Enable DAC1 DAC2 clocks */
    RCC_EnableAPB1PeriphClk(RCC_APB1_PERIPHEN_DAC12 ,ENABLE);
    /* Config DAC12 prescaler factor,DAC_CLK = 1M*/ 
    DAC_ConfigClkPrescaler(DAC12,120);

    DAC_SetHighFrequencyMode(DAC12,DAC_HIGH_FREQ_MODE_BELOW_160M);
}

校准只用到 DAC12 与 GPIO 时钟,移植时可裁剪未使用的端口时钟。

2. 配置模拟输出引脚。 GPIO_Configuration 把 PA4 配置为模拟模式作为 DAC1_OUT。

src/main.csrc/main.c · GPIO_Configuration
void GPIO_Configuration(void)
{
    GPIO_InitType GPIO_InitStructure;
    // DAC1_OUT 
    GPIO_InitStruct(&GPIO_InitStructure);
    GPIO_InitStructure.Pin        = GPIO_PIN_4 ;
    GPIO_InitStructure.GPIO_Mode  = GPIO_MODE_ANALOG;
    GPIO_InitPeripheral(GPIOA, &GPIO_InitStructure);
}

校准过程不产生外部输出,PA4 的模拟配置只是保持与其他示例一致。

3. 配置 DAC 并启动校准。 Start_UserTrimming 使能输出缓冲、开启校准与 DAC1,然后逐个尝试修调值直到校准完成。

src/main.csrc/main.c · Start_UserTrimming
ErrorStatus Start_UserTrimming(uint8_t *NewTrimValue)
{
    uint8_t index  =0;
    DAC_InitType DAC_InitStructure;

    DAC_StructInit(&DAC_InitStructure);
    /* DAC1 Configuration */
    DAC_InitStructure.DAC_Trigger                       = DAC_Trigger_Software;
    DAC_InitStructure.DAC_WaveGeneration                = DAC_WaveGeneration_None;
    DAC_InitStructure.DAC_OutputBuffer                  = ENABLE;
    DAC_InitStructure.DAC_ConnectOnChipPeripheral       = DISABLE;
    DAC_InitStructure.DAC_ConnectExternalPin            = ENABLE;
    DAC_InitStructure.DAC_TriggerEnable                 = ENABLE;
    DAC_Init(DAC1, &DAC_InitStructure);
    /* Enable DAC1 Calibration  */
    DAC_CaliEnable(DAC1,ENABLE) ;
    /* Enable DAC1  */
    DAC_Enable(DAC1, ENABLE);

    for(index = 0;index<32;index++)
    {
        DAC_SetUserTrimming(DAC1,index) ;
        systick_delay_us(100);
        if(DAC_GetFlagSts(DAC1,DAC_FLAG_CALCOMPLETE) != RESET)
        {
             *NewTrimValue = index;
             return SUCCESS;
        }
    }
     return ERROR;
}

校准要求输出缓冲使能;DAC_SetUserTrimming 写入候选值后需等待约 100 us 再查 CALCOMPLETE,命中即返回对应修调值。

4. 打印校准结果。 main 调用 Start_UserTrimming 后按返回值通过串口打印成功或失败信息。

src/main.csrc/main.c · main
    /*Start User Trimming ------------------------------------------------------*/
    status = Start_UserTrimming(&Trim_Value);
    
    if(status == SUCCESS)
    {
       log_info("User trimming passed, the triming value = 0x%x\r\n",Trim_Value);
    }
    else
    {
       log_info("User trimming failed,the triming invalid\r\n");
    }

量产时可把得到的修调值固化到应用里,开机后用 DAC_SetUserTrimming 直接写入,省去每次上电的校准循环。

对应源码: src/main.c

5.6.4 注意与排障

场景 检查与建议 来源
触发源选择 DAC 使能状态下禁止修改 Tx(y)SEL[4:0];
需要切换触发源时应先关闭对应 DAC,改好后再重新使能。
用户手册
高频接口模式 总线时钟高于 80 MHz 时必须配置 DACxy_HFSEL[1:0],否则接口时序不满足要求。 用户手册
同时内外输出 同时使能内部输出(INOUTxEN)与外部引脚输出(EXOUTxEN)时,必须同时使能输出缓冲器(Bx(y)EN = 1)。 用户手册
使能等待 使能 DAC 后需等待唤醒时间 tWAKEUP 再使用输出,否则转换结果不稳定。 用户手册
DMA 下溢 DMA 下溢错误标志 DMAUDR 通过写 1 清除。 用户手册
缓冲器校准 校准前先置 CALxEN 并保持缓冲器使能(BxEN = 1),等待约 100 us 后检查 CALFLAGx;
校准得到的修调码通过 OTRIMx[4:0] 写入。
用户手册
输出与参考电压 DAC 输出电压为 VREF+ 乘以 DATO/4095,参考电压来自 VREF+ 引脚或内置 VREFBUF;
满量程精度直接取决于该参考电压。
用户手册
国民技术开发套件文档中心

按芯片系列在线查阅国民技术 MCU 开发套件的芯片资料、SDK、驱动 API 与 Demo 示例说明。

© 2026 国民技术股份有限公司 版权所有粤ICP备11069485号本站使用不含 Cookie 的匿名访问统计