1、DAC硬件引脚 
 
 
 
 
引脚只能是PA4和PA5,并且要配置为模拟方式GPIO_MODE_ANALOG; 
 
 
 
 
这里要注意参考电压的值,我在用最小系统板测试时VREFP引脚悬空了,导致DAC引脚一直没有输出。 
 
2、DMA通道 
 
 
 
 
3、DAC 触发 
 
 
 
 
可以看出只有几个特定定时器可以触发DAC。 
 
4、DAC DMA请求 
在外部触发使能的情况下,通过设置 DAC_CTL0 寄存器的 DDMAENx 位来使能 DMA 请求。 当有外部硬件触发的时候(不是软件触发),则产生一个 DMA 请求。 
 
5、关键实现代码 
static uint16_t dac_sin_buf[4096]; /* dac数据缓冲区 */ 
 
/*  产生正弦波函序列 */ 
void dac_creat_sin_buf(uint16_t maxval, uint16_t samples, uint16_t *outbuff) { 
    uint8_t i; 
    float   inc     = (2 * 3.1415962) / samples; /* 计算增量(一个周期DAC_SIN_BUF个点) */ 
    float   outdata = 0; 
 
    for (i = 0; i < samples; i++) { 
        outdata = maxval * (1 + sin(inc * i)); /* 计算以dots个点为周期的每个点的值,放大maxval倍,并偏移到正数区域 */ 
        if (outdata > 4095) outdata = 4095;    /* 上限限定 */ 
        outbuff = outdata; 
    } 
} 
 
/*  dac初始化  */ 
void gd32_dac_init(void) { 
    rcu_periph_clock_enable(RCU_DAC); 
 
    dac_deinit(); 
 
    dac_wave_mode_config(DAC0, DAC_WAVE_DISABLE); 
 
    dac_output_buffer_disable(DAC0); 
    dac_data_set(DAC0, DAC_ALIGN_12B_R, 0); 
 
    dac_dma_enable(DAC0); 
 
    dac_trigger_enable(DAC0); 
    dac_trigger_source_config(DAC0, DAC_TRIGGER_T1_TRGO); 
    dac_enable(DAC0); 
} 
 
/*  dac dma初始化  */ 
void gd32_dac_dma_init(void){ 
    dma_single_data_parameter_struct dma_init_struct; 
 
    rcu_periph_clock_enable(RCU_DMA0); 
 
    dma_deinit(DMA0, DMA_CH5); 
    dma_init_struct.direction = DMA_MEMORY_TO_PERIPH; 
    dma_init_struct.memory0_addr = (uint32_t)dac_sin_buf; 
    dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE; 
    dma_init_struct.number = 100; 
    dma_init_struct.periph_addr = (uint32_t)(&DAC0_R12DH); 
    dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE; 
    dma_init_struct.periph_memory_width = DMA_PERIPH_WIDTH_16BIT; 
    dma_init_struct.priority = DMA_PRIORITY_ULTRA_HIGH; 
    dma_init_struct.circular_mode=DMA_CIRCULAR_MODE_ENABLE; 
 
    dma_single_data_mode_init(DMA0, DMA_CH5, &dma_init_struct); 
 
    dma_channel_subperipheral_select(DMA0, DMA_CH5, DMA_SUBPERI7); 
 
    dma_channel_enable(DMA0, DMA_CH5);   
} 
 
/*  定时器初始化  */ 
void gd32_time_init(void){ 
    timer_parameter_struct para; 
 
    rcu_periph_clock_enable(RCU_TIMER1); 
 
    timer_deinit(dev); 
    /* 参数 */ 
    timer_struct_para_init(¶); 
    para.alignedmode       = TIMER_COUNTER_EDGE; 
    para.counterdirection  = TIMER_COUNTER_UP; 
    para.clockdivision     = TIMER_CKDIV_DIV1; 
    para.repetitioncounter = 0U; 
    para.prescaler         = (500 - 1) & 0x0ffff; 
    para.period            = (2 - 1) & 0x0ffff; 
 
    /* 配置 */ 
    timer_init(TIMER1, ¶); 
    timer_update_event_enable(TIMER1); 
    timer_auto_reload_shadow_enable(TIMER1); 
 
    timer_master_output_trigger_source_select(TIMER1, TIMER_TRI_OUT_SRC_UPDATE);  //关键 
 
    timer_enable(TIMER1); 
} 
 
/*  正弦波测试  */ 
void dac_wave_test(void) { 
    rcu_periph_clock_enable(RCU_GPIOA); 
    gpio_mode_set(GPIOA, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO_PIN_4); 
 
    dac_creat_sin_buf(2048, 100, dac_sin_buf); 
 
    gd32_dac_init(DAC0); 
 
    gd32_dac_dma_init(); 
 
    gd32_time_init(); // 100kHZ 
} 
 
 
 
6、实测波形 
 
 
 
 
程序中配置定时器为100kHZ,每个正弦波100个点,理论计算正弦波的频率为1kHZ,示波器实测波形也正是1kHZ。 
———————————————— 
版权声明:本文为CSDN博主「freemote」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 
原文链接:https://blog.csdn.net/freemote/article/details/151373457 
 
 |   
     
  
 |