GD32F103的DAC1

GD32F103的DAC1采用定时器1触发,DMA传输,将数据转换为电压输出到PA5引脚。

GD32F103的DAC为12位DA转换器,可以将12位的数据转换为电压,从外部引脚上输出;
DAC_OUT0映射到PA4,DAC_OUT1映射到PA5;

DACx引脚上的模拟输出电压:
DACoutput =DAC_DO *  Vref+/4096

DAC触发:
DTSELx[2:0]=000,触发源为TIMER5_TRGO,属于内部片上信号;
DTSELx[2:0]=001,互联型产品的触发源为TIMER2_TRGO;非互联型产品的触发源为TIMER7_TRGO,属于内部片上信号;
DTSELx[2:0]=010,触发源为TIMER6_TRGO,属于内部片上信号;
DTSELx[2:0]=011,触发源为TIMER4_TRGO,属于内部片上信号;
DTSELx[2:0]=100,触发源为TIMER1_TRGO,属于内部片上信号;
DTSELx[2:0]=101,触发源为TIMER3_TRGO,属于内部片上信号;
DTSELx[2:0]=110,触发源为EXTI9,属于外部信号触发;
DTSELx[2:0]=111,触发源为SWTRIG,属于软件触发;

DAC数据格式
根据选择的配置模式,数据按照下文所述写入指定的寄存器:
8位数据右对齐:用户须将数据写入寄存器DACx_R8DH [7:0]位
12位数据左对齐:用户须将数据写入寄存器DACx_L12DH[15:4]位
12位数据右对齐:用户须将数据写入寄存器DACx_R12DH[11:0]位

DAC0的DAC_CH0映射到DMA1通道2;
DAC1的DAC_CH1映射到DMA1通道3;

 

 

#include "DAC1.h"
#include "stdio.h"  //getchar(),putchar(),scanf(),printf(),puts(),gets(),sprintf()

/*
GD32F103的DAC为12位DA转换器,可以将12位的数据转换为电压,从外部引脚上输出;
DAC_OUT0映射到PA4,DAC_OUT1映射到PA5;

DACx引脚上的模拟输出电压:
DACoutput =DAC_DO *  Vref+/4096

DAC触发:
DTSELx[2:0]=000,触发源为TIMER5_TRGO,属于内部片上信号;
DTSELx[2:0]=001,互联型产品的触发源为TIMER2_TRGO;非互联型产品的触发源为TIMER7_TRGO,属于内部片上信号;
DTSELx[2:0]=010,触发源为TIMER6_TRGO,属于内部片上信号;
DTSELx[2:0]=011,触发源为TIMER4_TRGO,属于内部片上信号;
DTSELx[2:0]=100,触发源为TIMER1_TRGO,属于内部片上信号;
DTSELx[2:0]=101,触发源为TIMER3_TRGO,属于内部片上信号;
DTSELx[2:0]=110,触发源为EXTI9,属于外部信号触发;
DTSELx[2:0]=111,触发源为SWTRIG,属于软件触发;

DAC数据格式
根据选择的配置模式,数据按照下文所述写入指定的寄存器:
8位数据右对齐:用户须将数据写入寄存器DACx_R8DH [7:0]位
12位数据左对齐:用户须将数据写入寄存器DACx_L12DH[15:4]位
12位数据右对齐:用户须将数据写入寄存器DACx_R12DH[11:0]位

DAC0的DAC_CH0映射到DMA1通道2;
DAC1的DAC_CH1映射到DMA1通道3;
*/

#define  DAC1_Buff_Size 32
uint16_t DAC1_Buff[DAC1_Buff_Size]=\
{2048,128,256,384,512,640,768,896,\
1024,1152,1280,1408,1536,1664,1792,1920,\
2048,2176,2304,2432,2560,2688,2816,2944,\
3072,3200,3328,3456,3584,3712,3840,3968};

void DAC1_Receive_DMA1_DMA_CH3_config(void);
void DAC1_Init(void);
void Timer1_Initializtion(uint16_t arr,uint16_t psc);

void DAC1_Receive_DMA1_DMA_CH3_config(void)
{
	dma_parameter_struct dma_init_struct;

	rcu_periph_clock_enable(RCU_DMA1);//使能DMA1时钟

	dma_deinit(DMA1,DMA_CH3);//复位DAM1的通道3

	dma_init_struct.direction = DMA_MEMORY_TO_PERIPHERAL;//DMA传送方向:从内存到外设
	dma_init_struct.memory_addr = (uint32_t)(&DAC1_Buff[0]);   //源数据首地址为:DAC1_Buff[]
	dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE;//源数据块地址递增
  dma_init_struct.memory_width = DMA_MEMORY_WIDTH_16BIT;//源数据块的数据宽度为16位
	dma_init_struct.number = DAC1_Buff_Size;//源数据块的数据长度

	dma_init_struct.periph_addr = ((uint32_t)(&DAC1_R12DH));//目的数据首地址为:DAC数据寄存器
	dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE;//目的数据块地址不递增
	dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_16BIT;//目的据块的数据宽度为8位

	dma_init_struct.priority = DMA_PRIORITY_ULTRA_HIGH;//超高的优先级
	dma_init(DMA1,DMA_CH3,&dma_init_struct);//使用dma_init_struct数据结构初始化DMA1通道3

	dma_circulation_enable(DMA1,DMA_CH3);//使能"DMA1通道3循环工作模式"
//	dma_circulation_disable(DMA1,DMA_CH3);//不使能"DMA1通道3循环工作模式"
	dma_memory_to_memory_disable(DMA1,DMA_CH3);//不使能"DMA1通道3内存到内存传输模式"

  dma_channel_enable(DMA1,DMA_CH3);

	dac_dma_enable(DAC1);
	//使能DMA和DAC之间的传输,enable DAC DMA function
	//这个必须要
}

void DAC1_Init(void)
{
	rcu_periph_clock_enable(RCU_GPIOA);//使能GPIOA时钟
	rcu_periph_clock_enable(RCU_DAC);  //使能DAC时钟

	gpio_init(GPIOA,GPIO_MODE_AIN,GPIO_OSPEED_50MHZ,GPIO_PIN_5);
	//将GPIOA5设置为模拟输出口,最大输出速度为50MHz

	dac_deinit();//复位DAC

	dac_trigger_source_config(DAC1,DAC_TRIGGER_T1_TRGO);
	//设置触发源:定时器1触发
	dac_trigger_enable(DAC1);//打开DAC1触发功能
//  dac_trigger_disable(DAC1);//关闭DAC1触发功能

	dac_wave_mode_config(DAC1,DAC_WAVE_DISABLE);//DAC_WAVE_DISABLE表示不使用波形发生器

	dac_output_buffer_disable(DAC1);
	//不允许"直接将DAC1数据寄存器的值转换为电压输出"
	//需要通过触发源触发,才可以输出电压值
//	dac_output_buffer_enable(DAC1);
	//不用通过触发源触发,直接将DAC1数据寄存器的值转换为电压输出

  dac_enable(DAC1);//使能DAC1

  DAC1_Receive_DMA1_DMA_CH3_config();

  Timer1_Initializtion(50000,6480);//当arr=50000,psc=6480时,则为3000ms,误差为10us;
//  Timer1_Initializtion(19,0);//当arr=50000,psc=6480时,则为3000ms,误差为10us;
}

//函数功能:通用定时器1更新事件作为DAC1的触发源
//arr:自动重装值。
//psc:时钟预分频数
//Timer1_Initializtion(50000,6480);//当arr=50000,psc=6480时,则为3000ms,误差为10us;
//Timer1_Initializtion(50000,1080);//当arr=50000,psc=1080时,则为500ms,误差为10us;
void Timer1_Initializtion(uint16_t arr,uint16_t psc)
{
	timer_parameter_struct TimerParameterStruct;

	rcu_periph_clock_enable(RCU_TIMER1);
	nvic_irq_enable(TIMER1_IRQn, 2U, 0U);  //设置TIMER1_IRQn的中断优先级,抢占优先级为2,子优先级为0

	timer_deinit(TIMER1);//复位TIMER1

	TimerParameterStruct.period            = arr-1;//设置在下一个更新事件装入活动的自动重装载寄存器周期的值
	TimerParameterStruct.prescaler         = psc-1;//设置用来作为TIMx时钟频率除数的预分频值(APB2时钟分频值)
  TimerParameterStruct.clockdivision     = TIMER_CKDIV_DIV1;//设置时钟分母值为1
	//计算公式:arr*psc/108000000/1,当arr=250,psc=108时,则为0.25ms,误差为1us;
	TimerParameterStruct.counterdirection  = TIMER_COUNTER_UP;//设置计数方向为"向上计数"
	TimerParameterStruct.alignedmode       = TIMER_COUNTER_EDGE;//设置为无中央对齐计数模式(边沿对齐模式)
	timer_init(TIMER1, &TimerParameterStruct);

	timer_master_output_trigger_source_select(TIMER1,TIMER_TRI_OUT_SRC_UPDATE);
	//输出的更新事件作为触发器输出,update event as trigger output
	timer_update_event_enable(TIMER1);//定时器更新事件使能

	timer_counter_value_config(TIMER1,0);//设置TIMERx的计数器初始值为0
	//timer_counter_read(timer_periph);//读取TIMERx的计数器值

  timer_auto_reload_shadow_enable(TIMER1);//使能TIMERx自动重装载

	timer_flag_clear(TIMER1,TIMER_FLAG_UP);               //清除"TIMERx更新标志位"
	timer_interrupt_flag_clear(TIMER1,TIMER_INT_FLAG_UP); //清除"TIMERx更新中断标志位"
	timer_interrupt_enable(TIMER1,TIMER_INT_UP);          //使能"TIMERx更新"产生中断

  timer_internal_clock_config(TIMER1);//设置"内部时钟"作为定时器时钟
	//timer_slave_mode_select(timer_periph,TIMER_SLAVE_MODE_DISABLE);
	//设置"关闭从模式",如果TIMER计数器使能,则预分频器直接由内部时钟驱动

	timer_enable(TIMER1);//TIMERx计数器使能,开始工作
}

//函数功能:TIMER1更新中断服务程序
void TIMER1_IRQHandler(void)
{
	uint16_t d;

	if( timer_interrupt_flag_get(TIMER1,TIMER_INT_FLAG_UP) )// 读取更新中断标志位
	{
		d=dac_output_value_get(DAC1);//读取DAC1的值
		printf("\r\nd=%f v",3.3*( (float)d/4096 ));

		timer_flag_clear(TIMER1,TIMER_FLAG_UP);//清除"TIMER1更新标志位"
	}
  timer_interrupt_flag_clear(TIMER1,TIMER_INT_FLAG_UP); //清除"更新中断标志位"
}

 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值