[研电赛技术支持] GD32 DAC DMA使用方法

[复制链接]
201|0
小海师 发表于 2025-10-9 15:25 | 显示全部楼层 |阅读模式
1、DAC硬件引脚

2740068e763537217d.png

引脚只能是PA4和PA5,并且要配置为模拟方式GPIO_MODE_ANALOG;

5059668e7634c43c46.png

这里要注意参考电压的值,我在用最小系统板测试时VREFP引脚悬空了,导致DAC引脚一直没有输出。

2、DMA通道

8060468e76345a6340.png

3、DAC 触发

5450368e7633f61922.png

可以看出只有几个特定定时器可以触发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);
    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, &para);
    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、实测波形

9563468e76328cc8f8.jpg

程序中配置定时器为100kHZ,每个正弦波100个点,理论计算正弦波的频率为1kHZ,示波器实测波形也正是1kHZ。
————————————————
版权声明:本文为CSDN博主「freemote」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/freemote/article/details/151373457

您需要登录后才可以回帖 登录 | 注册

本版积分规则

89

主题

272

帖子

1

粉丝
快速回复 在线客服 返回列表 返回顶部