DAC相关

DAC简介
DAC为数字/模拟转换模块,故名思议,它的作用就是把输入的数字编码,转换成对应的模拟电压输出,它的功能与ADC相反。 在常见的数字信号系统中,大部分传感器信号被化成电压信号,而ADC把电压模拟信号转换成易于计算机存储、处理的数字编码, 由计算机处理完成后,再由DAC输出电压模拟信号,该电压模拟信号常常用来驱动某些执行器件,使人类易于感知。如音频信号的采集及还原就是这样一个过程。

STM32具有片上DAC外设,它的分辨率可配置为8位或12位的数字输入信号,具有两个DAC输出通道,这两个通道互不影响, 每个通道都可以使用DMA功能,都具有出错检测能力,可外部触发。
DAC功能框图
在这里插入图片描述
整个DAC模块围绕框图下方的“数字至模拟转换器x”展开,它的左边分别是参考电源的引脚:VDDA、 VSSA及Vref+, 其中STM32的DAC规定了它的参考电压:math:V_{ref +}输入范围为2.4——3.3V。 “数字至模拟转换器x”的输入为DAC的数据寄存器“DORx”的数字编码,经过它转换得的模拟信号由图中右侧的“DAC_OUTx”输出。 而数据寄存器“DORx”又受“控制逻辑”支配,它可以控制数据寄存器加入一些伪噪声信号或配置产生三角波信号。图中的左上角为DAC的触发源, DAC根据触发源的信号来进行DAC转换,其作用就相当于DAC转换器的开关,它可以配置的触发源为外部中断源触发、定时器触发或软件控制触发。 如本章实验中需要控制正弦波的频率,就需要定时器定时触发DAC进行数据转换。
参考电压
与ADC外设类似,DAC也使用VREF+引脚作为参考电压, 在设计原理图的时候一般把VSSA接地,把VREF+和VDDA 接3.3V, 可得到DAC的输出电压范围为:0~3.3V。
如果想让输出的电压范围变宽,可以在外部加一个电压调理电路,把0~3.3V的DAC输出抬升到特定的范围即可。
数模转换及输出通道
框图中的“数字至模拟转换器x”是核心部件,整个DAC外设都围绕它而展开。它以左边的VREF+作为参考电源, 以DAC的数据寄存器“DORx”的数字编码作为输入,经过它转换得的模拟信号由右侧的“DAC_OUTx”通道输出。其中各个部件中的“x”是指设备的标号, 在STM32中具有2个这样的DAC部件,每个DAC有1个对应的输出通道连接到特定的引脚,即:PA4-通道1,PA5-通道2,为避免干扰,使用DAC功能时, DAC通道引脚需要被配置成模拟输入功能(AIN)。
触发源及DHRx寄存器
在使用DAC时,不能直接对上述DORx寄存器写入数据,任何输出到DAC通道x的数据都必须写入到DHRx寄存器中(其中包含DHR8Rx、DHR12Lx等, 根据数据对齐方向和分辨率的情况写入到对应的寄存器中)。
数据被写入到DHRx寄存器后,DAC会根据触发配置进行处理,若使用硬件触发,则DHRx中的数据会在3个APB1时钟周期后传输至DORx, DORx随之输出相应的模拟电压到输出通道;若DAC设置为外部事件触发,可以使用定时器(TIMx_TRGO)、 EXTI_9信号或软件触发(SWTRIGx)这几种方式控制数据DAC转换的时机,例如使用定时器触发,配合不同时刻的DHRx数据,可实现DAC输出正弦波的功能。
配置

typedef struct {
    /*DAC触发方式 */
    uint32_t DAC_Trigger;

    /*是否自动输出噪声或三角波 */
    uint32_t DAC_WaveGeneration;

    /*选择噪声生成器的低通滤波或三角波的幅值 */
    uint32_t DAC_LFSRUnmask_TriangleAmplitude;

    /*选择是否使能输出缓冲器 */
    uint32_t DAC_OutputBuffer;

} DAC_InitTypeDef;

(1) DAC_Trigger
用于配置DAC的触发模式,当DAC产生相应的触发事件时,才会把DHRx寄存器的值转移到DORx寄存器中进行转换。 本结构体成员可以选择的触发模式如下:硬件触发模式(DAC_Trigger_None),DHRx寄存器内的数据会在3个APB1时钟周期内自动转换至DORx进行转换; 定时器触发模式(DAC_Trigger_T2/4/5/6/7/8_TRGO),使用定时器2、4、5、6、7、8控制DHRx寄存器的数据按时间转移到DORx中进行转换, 利用这种方式可以输出特定的波形;EXTI_9触发方式(DAC_Trigger_Ext_IT9),当产生EXTI_9事件时(如GPIO中断事件),触发转换; 软件触发模式DAC_Trigger_Software,在本模式下,向DAC_SWTRIGR寄存器写入配置即可触发信号进行转换。
(2) DAC_WaveGeneration
本成员用于设置是否使用DAC输出伪噪声或三角波(DAC_WaveGeneration_None/Noise/Triangle),使用伪噪声和三角波输出时, DAC都会把LFSR寄存器的值叠加到DHRx数值上,产生伪噪声和三角波,若希望产生自定义的输出时,直接配置为DAC_WaveGeneration_None即可。
(3) DAC_LFSRUnmask_TriangleAmplitude
本成员通过控制DAC_CR的MAMP2位设置LFSR寄存器位的数据,即当使用伪噪声或三角波输出时要叠加到DHRx的值,非噪声或三角波输出模式下, 本配置无效。使用伪噪声输出时LFSR=0xAAA,MAMP2寄存器位可以屏蔽LFSR的某些位, 这时把本结构体成员赋值为DAC_LFSRUnmask_Bit0~DAC_LFSRUnmask_Bit11_0等宏即可;使用三角波输出时,本结构体设置三角波的最大幅值, 可选择为DAC_TriangleAmplitude_1~ DAC_TriangleAmplitude_4096等宏,见图 DAC输出三角波 , DAC在DHRx值的基础上升,幅值达到MAMPx设置的最大幅度时下降,形成三角波的输出。
(4) DAC_OutputBuffer
用于控制是否使能DAC的输出缓冲(DAC_OutputBuffer_Enable/Disable), 使能了DAC的输出缓冲后可以减小输出阻抗,适合直接驱动一些外部负载。

代码部分

void Dac1_Init(void)
{  
  GPIO_InitTypeDef  GPIO_InitStructure;
	DAC_InitTypeDef DAC_InitType;
	
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);//使能GPIOA时钟
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE);//使能DAC时钟
	   
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;//模拟输入
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN;//下拉
  GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化

	DAC_InitType.DAC_Trigger=DAC_Trigger_None;	//不使用触发功能 TEN1=0
	DAC_InitType.DAC_WaveGeneration=DAC_WaveGeneration_None;//不使用波形发生
	DAC_InitType.DAC_LFSRUnmask_TriangleAmplitude=DAC_LFSRUnmask_Bit0;//屏蔽、幅值设置
	DAC_InitType.DAC_OutputBuffer=DAC_OutputBuffer_Disable ;	//DAC1输出缓存关闭 BOFF1=1
  DAC_Init(DAC_Channel_1,&DAC_InitType);	 //初始化DAC通道1

	DAC_Cmd(DAC_Channel_1, ENABLE);  //使能DAC通道1
  
  DAC_SetChannel1Data(DAC_Align_12b_R, 0);  //12位右对齐数据格式设置DAC值
}
//设置通道1输出电压
//vol:0~3300,代表0~3.3V
void Dac1_Set_Vol(u16 vol)
{
	double temp=vol;
	temp/=1000;
	temp=temp*4096/3.3;
	DAC_SetChannel1Data(DAC_Align_12b_R,temp);//12位右对齐数据格式设置DAC值
}
//部分main
DAC_SetChannel1Data(DAC_Align_12b_R,dacval);//初始值为0	
	while(1)
	{
		t++;
		key=KEY_Scan(0);			  
		if(key==WKUP_PRES)
		{		 
			if(dacval<4000)dacval+=200;
			DAC_SetChannel1Data(DAC_Align_12b_R, dacval);//设置DAC值
		}else if(key==2)	
		{
			if(dacval>200)dacval-=200;
			else dacval=0;
			DAC_SetChannel1Data(DAC_Align_12b_R, dacval);//设置DAC值
		}	 
		if(t==10||key==KEY1_PRES||key==WKUP_PRES) 	//WKUP/KEY1按下了,或者定时时间到了
		{	  
 			adcx=DAC_GetDataOutputValue(DAC_Channel_1);//读取前面设置DAC的值
			LCD_ShowxNum(94,150,adcx,4,16,0);     	   //显示DAC寄存器值
			temp=(float)adcx*(3.3/4096);			         //得到DAC电压值
			adcx=temp;
 			LCD_ShowxNum(94,170,temp,1,16,0);     	   //显示电压值整数部分
 			temp-=adcx;
			temp*=1000;
			LCD_ShowxNum(110,170,temp,3,16,0X80); 	   //显示电压值的小数部分
 			adcx=Get_Adc_Average(ADC_Channel_5,10);		//得到ADC转换值	  
			temp=(float)adcx*(3.3/4096);			        //得到ADC电压值
			adcx=temp;
 			LCD_ShowxNum(94,190,temp,1,16,0);     	  //显示电压值整数部分
 			temp-=adcx;
			temp*=1000;
			LCD_ShowxNum(110,190,temp,3,16,0X80); 	  //显示电压值的小数部分
			LED0=!LED0;	   
			t=0;
		}	    
		delay_ms(10);	 
	}	
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值