STM32的PWM和DAC的练习

摘要:

本文用PWM输出波形控制IO口实现呼吸灯,并通过DAC输出2KHz的正弦波和编辑音频输出的功能。

一. PWM练习


1. PWM简介

PWM是 Pulse Width Modulation 的缩写,中文意思就是脉冲宽度调制,简称脉宽调制。它是利用微处理器的数字输出来对模拟电路进行控 制的一种非常有效的技术,其控制简单、灵活和动态响应好等优点而成 为电力电子技术最广泛应用的控制方式。

其原理图如下:

STM32F1除了基本定时器TIM6和TIM7,其他定时器都可以产生PWM输出 。其中高级定时器 TIM1 和 TIM8 可以同时产生多达 7 路的 PWM 输出 。而通用定时器也能同时产生多达 4路的 PWM 输出,这些在定时器中断 章节中已经介绍过。 PWM的输出其实就是对外输出脉宽可调(即占空比调节)的方波信号 ,信号频率是由自动重装寄存器 ARR 的值决定,占空比由比较寄存器 CCR 的值决定。PWM输出比较模式总共有8种,具体由寄存器 CCMRx 的位 OCxM[2:0] 配置。我们这里只讲解最常用的两种PWM输出模式:PWM1和PWM2,其他几 种模式可以参考《STM32F10x中文参考手册》13、14、15定时器章节。

更多知识可以参考stm32 PWM输出实验

2. PWM输出配置

1)配置使能端口时钟,设置引脚复用器映射

2)初始化定时器参数,包含自动重装值,分频系数,计数方式等

初始化PWM输出参数,包含输出极性,使能等

2

3)开定时器

4)之后在主函数中控制占空比:

这时while(1)里循环得代码,作用就是led0pwmval占空比逐渐增大,也就是越来越亮。在

delay_ms(10);	 
if(dir)led0pwmval++;
else led0pwmval--;
if(led0pwmval>300)dir=0;
if(led0pwmval==0)dir=1;										 
TIM_SetCompare2(TIM3,led0pwmval);	

3. 主要代码

void TIM3_Int_Init(u16 arr,u16 psc)
{
    
    
  TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
	NVIC_InitTypeDef NVIC_InitStructure;

	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //时钟使能

	TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值	 计数到5000为500ms
	TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值  10Khz的计数频率  
	TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式
	TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位
 
	TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE ); //使能指定的TIM3中断,允许更新中断

	NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;  //TIM3中断
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;  //先占优先级0级
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;  //从优先级3级
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
	NVIC_Init(&NVIC_InitStructure);  //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器

	TIM_Cmd(TIM3, ENABLE);  //使能TIMx外设
							 
}
//定时器3中断服务程序
void TIM3_IRQHandler(void)   //TIM3中断
{
    
    
	if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) //检查指定的TIM中断发生与否:TIM 中断源 
		{
    
    
		TIM_ClearITPendingBit(TIM3, TIM_IT_Update  );  //清除TIMx的中断待处理位:TIM 中断源 
		LED1=!LED1;
		}
}
//TIM3 PWM部分初始化 
//PWM输出初始化
//arr:自动重装值
//psc:时钟预分频数
void TIM3_PWM_Init(u16 arr,u16 psc)
{
    
      
	GPIO_InitTypeDef GPIO_InitStructure;
	TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
	TIM_OCInitTypeDef  TIM_OCInitStructure;
	

	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);	//使能定时器3时钟
 	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB  | RCC_APB2Periph_AFIO, ENABLE);  //使能GPIO外设和AFIO复用功能模块时钟
	
	GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3, ENABLE); //Timer3部分重映射  TIM3_CH2->PB5    
 
   //设置该引脚为复用输出功能,输出TIM3 CH2的PWM脉冲波形	GPIOB.5
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //TIM_CH2
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  //复用推挽输出
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化GPIO
 
   //初始化TIM3
	TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值
	TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值 
	TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式
	TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位
	
	//初始化TIM3 Channel2 PWM模式	 
	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //选择定时器模式:TIM脉冲宽度调制模式2
 	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性:TIM输出比较极性高
	TIM_OC2Init(TIM3, &TIM_OCInitStructure);  //根据T指定的参数初始化外设TIM3 OC2

	TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable);  //使能TIM3在CCR2上的预装载寄存器
 
	TIM_Cmd(TIM3, ENABLE);  //使能TIM3
	

}

4.演示效果

a. 模拟示波器显示

选择魔术棒–Debug–配置如下

示波器配置如下:

显示效果:

b. 示波器显示

c. 实物效果

二. DAC练习


1. DAC简介

  • DAC为数字/模拟转换模块,故名思议,它的作用就是把输入的数字编码,转换成对应的模拟电压输出,它的功能与ADC相反。在常见的数字信号系统中,大部分传感器信号被化成电压信号,而ADC把电压模拟信号转换成易于计算机存储、处理的数字编码,由计算机处理完成后,再由DAC输出电压模拟信号,该电压模拟信号常常用来驱动某些执行器件,使人类易于感知。如音频信号的采集及还原就是这样一个过程。
  • STM32具有片上DAC外设,它的分辯率可配置为8位或12位的数字输入信号,具有两个DAC输出通道,这两个通道互不影响,每个通道都可以使用DMA功能,都具有出错检测能力,可外部触发。
  • DAC模块图如下:

整个DAC模块围绕框图下方的**“数字至模拟转换器x”**展开,它的左边分别是参考电源的引脚:VDDA、VSSA及Vref+,其中STM32的DAC规定了它的参考电压Vref+输入范围为2.4–3.3V。“数字至模拟转换器x”的输入为DAC的数据寄存器“DORx”的数字编码,经过它转换得的模拟信号由图中右侧的“ DAC OUTX”输出。而数据寄存器“DORx“又受“控制逻辑”支配,它可以控制数据寄存器加入一些伪噪声信号或配置产生三角波信号。图中的左上角为DAC的触发源,DAC根据触发源的信号来进行DAC转换,其作用就相当于DAC转换器的开关,它可以配置的触发源为外部中断源触发、定时器触发或软件控制触发。如本章实验中需要控制正弦波的频率,就需要定时器定时触发DAC进行数据转换。

2.要点分析并实现2KHz正弦波的输出

  • DAC_Trigger 用于配置DAC的触发方式

  • DAC_WaveGeneration为是否启动输出噪声或者三角波

  • DAC_LFSRUnmask_TriangleAmpliude 为选择噪声生成器的低通滤波或三角波的幅值

  • DAC_OutputBuffer 选择是否使能输出缓存器

    更多步骤请参考《【野火®】零死角玩转STM32—F103-MINI》

    根据公式:

设置如下

这样即可输出2Khz的正弦波

结果如下:

接入蜂鸣器,听有单音。

4. 设计输出音频信号

算法逻辑类似与输出正弦波信号的思路一致,不同的是要更改采样的数值。

step1:打开Adobe Audition打开自己喜欢的音乐,设置:

  • 采样率8000
  • 单声道
  • 16位
  • 大约采集2-3s

step2:存储为.wav文件

.wav文件通过软件Uedit32打开

step3:格式转换

全选内容,右键–用16进制复制所选视图,复制到记事本–粘贴回去–右键–选择范围

step4:复制到notepad++进行填充

关于notepad++前文提到过用法,

按列块插入0x, 每列重复操作

step5:修改数组

step6:烧入观察波形

三. 总结

这次实验,尝试了解了DAC和PWM,这两个模块在时机中应用十分广泛,比如在一些比赛中可以用PWM波控制舵机和点击,用ADC,DAC进行采集信息等。收获许多

参考

[1] 使用STM32控制无源蜂鸣器发声播放音乐(STM32_07)

[2] stm32 PMW输出实验

[3] 详解基于STM32的keil4 MDK 软件仿真输出IO口的波形图!

猜你喜欢

转载自blog.csdn.net/lee_goi/article/details/111998475