PWM波的理解

PWM波的理解

PWM波我们可以简单的理解为输出一个普通的矩形波
在这里插入图片描述
C51单片机中通过I/O口直接输出,我们可以很简单的直接得到一个PWM波;输出一个高电平然后延迟一段时间,再输出一个低电平延迟一段时间,将其进行循环便可得到一个简易的PWM波,占空比可通过高电平与低电平延时时间的对应比例改变,代码如下:

//输出一个周期为50ms的PWM波
whlie(1)
{
	size = 0.6; //占空比为50%
	P0^0 = 0; //输出低电平
	//delay(1)为10ms
	delay(5*(1-size)); 
	P0^0 = 1; //输出高电平
	delay(5*size); 
}

C51单片机中通过定时器产生一个PWM波(其实就是将delay延迟改为计数器延时,频率可更快,也更加精准)

//输出一个周期为5ms的PWM波
void tim1init()//定时器1初始化
{
	TMOD=0X10;	//t1 方式1
	TH1=0XFC;
	TL1=0X18;//定时1ms
	TR1=1;	 //打开t1定时器
}
void main()
{
	size = 0.5; //占空比为60%
	int i = 0;
	while(1)
	{
		if(TF == 1)
		{
			TF = 0;//重装载计数器
			i = i+1;
			if(i == 5)
				i=0;
		}
		if(i < size*5)
			P0^0 = 1; //输出高电平
		else
			P0^0 = 0; //输出低电平
	}
}

相对于以上C51单片机的代码来讲,stm32单片机有一全套关于PWM波输出的库函数,相对比较可视化,但也比较复杂。(也是我们本次主要讲的重点)
首先我们先了解一下stm32单片机是怎样形成PWM波输出的
其实跟我们上面C51单片机的原理相差无几,通过设定一个CCRX值与计数值进行比较;通过设定CCER来控制有效电平为高电平还是低电平,通过设定CCMRX寄存器来控制计数值比CCRX值大为有效电平还是比CCRX值小为有效电平。(从下面的图可以很明显看出,设置溢出值ARR可以调整输出频率,设置CCRX值可以调整占空比)也可以很清晰看出该种PWM波频率更加快
在这里插入图片描述
控制PWM波的所有寄存器以及相对应的作用
在这里插入图片描述
由于stm32单片机有一全套的库函数可供调用,故关于PWM的库函数配置过程如下:(以下用定时器14为例)

  1. 使能定时器14和相关I/O口时钟
    使能定时器14时钟:RCC_APB1PeriphClockCmd();
    使能GPIOF时钟:RCC_AHB1PeriphClockCmd();

  2. 初始化I/O口为复用功能输出

    GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF;
    GPIO_Init();

  3. GPIOF复用映射到定时器14
    GPIO_PinAFConfig(GPIOF,GPIO_PinSource9,GPIO_AF_TIM14);

  4. 初始化定时器:ARR//溢出数;PSC//分频系数
    TIM_TimeBaseInit();

  5. 初始化PWM输出比较参数
    TIM_OC1Init();

  6. 使能TIM14在CCR1上的预装载寄存器
    TIM_OC1PreloadConfig(TIM14, TIM_OCPreload_Enable);

  7. ARPE使能
    TIM_Cmd(TIM14, ENABLE);

  8. 使能TIM14
    TIM_Cmd(TIM14, ENABLE);

  9. 改变CCRX值达到不同的占空比效果
    TIM_SetCompare1();

以下为输出PWM波于LED灯实现亮度不断变化的效果的代码

void TIM14_PWM_Init(u32 arr,u32 psc)
{		 					 
	//此部分需手动修改IO口设置
	
	GPIO_InitTypeDef GPIO_InitStructure;
	TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
	TIM_OCInitTypeDef  TIM_OCInitStructure;
	
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM14,ENABLE);  	//TIM14时钟使能    
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE); 	//使能PORTF时钟	
	
	GPIO_PinAFConfig(GPIOF,GPIO_PinSource9,GPIO_AF_TIM14); //GPIOF9复用为定时器14
	
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;           //GPIOF9
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;        //复用功能
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;	//速度100MHz
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;      //推挽复用输出
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;        //上拉
	GPIO_Init(GPIOF,&GPIO_InitStructure);              //初始化PF9
	  
	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(TIM14,&TIM_TimeBaseStructure);//初始化定时器14
	
	//初始化TIM14 Channel1 PWM模式	 
	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //选择定时器模式:TIM脉冲宽度调制模式2
 	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low; //输出极性:TIM输出比较极性低
	TIM_OC1Init(TIM14, &TIM_OCInitStructure);  //根据T指定的参数初始化外设TIM1 4OC1

	TIM_OC1PreloadConfig(TIM14, TIM_OCPreload_Enable);  //使能TIM14在CCR1上的预装载寄存器
    TIM_ARRPreloadConfig(TIM14,ENABLE);//ARPE使能 
	TIM_Cmd(TIM14, ENABLE);  //使能TIM14								  
}  
int main(void)
{ 
	u16 led0pwmval=0;    
	u8 dir=1;
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2
	delay_init(168);  //初始化延时函数
	uart_init(115200);//初始化串口波特率为115200
 	TIM14_PWM_Init(500-1,84-1);	//84M/84=1Mhz的计数频率,重装载值500,所以PWM频率为 1M/500=2Khz.     
   while(1) //实现比较值从0-300递增,到300后从300-0递减,循环
	{
 		delay_ms(10);	 
		if(dir)led0pwmval++;//dir==1 led0pwmval递增
		else led0pwmval--;	//dir==0 led0pwmval递减 
 		if(led0pwmval>300)dir=0;//led0pwmval到达300后,方向为递减
		if(led0pwmval==0)dir=1;	//led0pwmval递减到0后,方向改为递增
 
		TIM_SetCompare1(TIM14,led0pwmval);	//修改比较值,修改占空比
	}
}

通过比较很清晰知道,stm32单片机库函数实现的PWM波的周期为一个溢出周期,而以上两种方法为多个周期,可知stm32单片机库函数实现的PWM波的频率可远高于以上两种方法(其实C51单片机也可以在计数器中断函数进行设置值进行比较从而输出频率高的PWM波,但是书写起来极其麻烦)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值