PWM DAC实验

PWM DAC 简介

有时候,STM32F4 自带的 2 路 DAC 可能不够用,需要多路 DAC,外扩 DAC 成本又会 高不少。此时,我们可以利用 STM32F4 的 PWM+简单的 RC 滤波来实现 DAC 输出,从而节省成本。 在精度要求不是很高的时候,PWM+RC 滤波的 DAC 输出方式,是一种非常廉 价的解决方案。

PWM 本质上其实就是是一种周期一定,而高低电平占空比可调的方波。

PWM 波形可以用分段函数表示:

 其中:T 是单片机中计数脉冲的基本周期,也就是 STM32F4 定时器的计数频率的倒数。 N 是 PWM 波一个周期的计数脉冲个数,也就是 STM32F4 的 ARR-1 的值。n 是 PWM 波一 个周期中高电平的计数脉冲个数,也就是 STM32F4 的 CCRx 的值。VH 和 VL 分别是 PWM 波的高低电平电压值,k 为谐波次数,t 为时间。我们将①式展开成傅里叶级数,得到公式 ②:

从②式可以看出,式中第 1 个方括弧为直流分量,第 2 项为 1 次谐波分量,第 3 项为大 于 1 次的高次谐波分量。式②中的直流分量与 n 成线性关系,并随着 n 从 0 到 N,直流分量 从 VL 到 VL+VH 之间变化。这正是电压输出的 DAC 所需要的。因此,如果能把式②中除 直流分量外的谐波过滤掉,则可以得到从 PWM 波到电压输出 DAC 的转换,即:PWM 波 可以通过一个低通滤波器进行解调。 

式②中的第 2 项的幅度和相角与 n 有关,频率为 1/(NT), 其实就是 PWM 的输出频率。该频率是设计低通滤波器的依据。如果能把 1 次谐波很好过滤 掉,则高次谐波就应该基本不存在了。 通过上面的了解,可以得到 PWM DAC 的分辨率,计算公式如下:

分辨率=log2(N)

这里假设 n 的最小变化为 1,当 N=256 的时候,分辨率就是 8 位。而 STM32F4 的定时器大部分都是 16 位的(TIM2 和 TIM5 是 32 位),可以很容易得到更高的分辨率,分辨率越高,速度就越慢。不过在本实验要设计的 DAC 分辨率为 8 位。 在 8 位分辨条件下,我们一般要求 1 次谐波对输出电压的影响不要超过 1 个位的精度, 也就是 3.3/256=0.01289V。假设 VH 为 3.3V,VL 为 0V,那么一次谐波的最大值是 2*3.3/ π=2.1V,这就要求我们的 RC 滤波电路提供至少-20lg(2.1/0.01289)=-44dB 的衰减。 STM32F4 的定时器最快的计数频率是 168Mhz,某些定时器只能到 84M,以 84M 频率为例,8 为分辨率的时候,PWM 频率为 84M/256=328.125Khz。如果是 1 阶 RC 滤波,则要求截止频率 2.07Khz,如果为 2 阶 RC 滤波,则要求截止频率为 26.14Khz。

探索者 STM32F4 开发板的 PWM DAC 输出采用二阶 RC 滤波。

 二阶 RC 滤波截止频率计算公式为: f=1/2πRC 以上公式要求 R28*C37=R29*C38=RC。根据这个公式,计算出截止频 率为:33.8Khz 超过了 26.14Khz,这个和前面提到的要求有点出入,原因是该电路我们还需要用作 PWM DAC 音频输出,而音频信号带宽是 22.05Khz,为了让音频信号能够通过该低通滤波,同时为了标准化参数选取,所以确定了这样的参数。实测精度在 0.5LSB 左右。

硬件设计

我们使用 STM32F4 的 TIM9_CH2(PA3)输出 PWM,经过二阶 RC 滤波后,转换 为直流输出,实现 PWM DAC。同上一章一样,我们通过 ADC1 的通道 5(PA5)读取 PWM DAC 的输出,并在 LCD 模块上显示相关数值,通过按键和 USMART 控制 PWM DAC 的输 出值。我们需要用到 ADC 采集 DAC 的输出电压,所以需要在硬件上将 PWM DAC 和 ADC 短接起来

从上图可知 PWM_DAC 的连接关系,但是这里有个特别需要注意的地方:因为 PWM_DAC 和 USART2_RX 共用了 PA3 引脚,所以在做本例程的时候,必须拔了 P9 上面 PA3(RX)的跳线帽(左侧跳线帽),否则会影响 PWM 转换结果。 在硬件上,我们还需要用跳线帽短接多功能端口的 PDC 和 ADC。 

 

程序

PWM初始化

void TIM9_CH2_PWM_Init(u16 arr,u16 psc)
{
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;

RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM9,ENABLE);  
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); 

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3; 
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; 
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(GPIOA,&GPIO_InitStructure); 

GPIO_PinAFConfig(GPIOA,GPIO_PinSource3,GPIO_AF_TIM9);

TIM_TimeBaseStructure.TIM_Prescaler=psc; 
TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up; 
TIM_TimeBaseStructure.TIM_Period=arr; 
TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1; 
TIM_TimeBaseInit(TIM9,&TIM_TimeBaseStructure);


TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; 
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; 
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OCInitStructure.TIM_Pulse=0;
TIM_OC2Init(TIM9, &TIM_OCInitStructure);
 
TIM_OC2PreloadConfig(TIM9, TIM_OCPreload_Enable); 
TIM_ARRPreloadConfig(TIM9,ENABLE);
TIM_Cmd(TIM9, ENABLE);
}

该初始化函数与PWM输出实验几乎一模一样,只有定时器和通道不同。

main函数

int main(void)
{ 
	u16 adcx;
	float temp;
 	u8 t=0;	 
	u16 pwmval=0;
	u8 key; 
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2
	delay_init(168);    //初始化延时函数
	uart_init(115200);	//初始化串口波特率为115200	
	LED_Init();					//初始化LED 
	Adc_Init(); 				//adc初始化
	KEY_Init(); 				//按键初始化
	TIM9_CH2_PWM_Init(255,0);	
    TIM_SetCompare2(TIM9,pwmval);	//初始值     	      
	while(1)
	{
		t++;
		key=KEY_Scan(0);			  
		if(key==4)
		{		 
			if(pwmval<250)pwmval+=10;
			TIM_SetCompare2(TIM9,pwmval);	
		}else if(key==2)	
		{
			if(pwmval>10)pwmval-=10;
			else pwmval=0;
			TIM_SetCompare2(TIM9,pwmval);	
		}	 
		if(t==10||key==2||key==4) 		
		{	  
 			adcx=TIM_GetCapture2(TIM9);;
			printf("PWM DAC:%d\t",adcx);     	
			temp=(float)adcx*(3.3/256);;			    
 			printf("PWM DAC_V:%.2f\t",temp);     	
 			adcx=Get_Adc_Average(ADC_Channel_5,20); 	  
			temp=(float)adcx*(3.3/4096);			      
 			printf("ADC_V:%.2f\r\n",temp);     	
			t=0;
			LED0=!LED0;	   
		}	    
		delay_ms(10); 
	}
}

运行视频

PWM DAC实验

  • 2
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值