| 
 
| 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
 
 
 | 
 |