我是靠谱客的博主 甜甜发卡,最近开发中收集的这篇文章主要介绍STM32单片机PWM输出学习,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

STM32单片机PWM输出学习

PWM原理:
PWM表示脉冲宽度调制,它是一系列脉冲,这些脉冲将以方波的形式出现。也就是说,在任何给定的时间点,波型要么是高电平或者是低电平。对于PWM信号我们需要关注两个与之相关的重要参数,一个是PWM占空比,另一个是PWM信号的频率。
在这里插入图片描述占空比 =接通时间 / (接通时间 + 断开时间)

也就是说,通过控制从0%到100%的占空比,我们可以控制PWM信号的“接通时间”,从而控制信号的宽度。由于我们可以通过调节脉冲信号的宽度控制接通时间,所以将这种控制方式称为“脉冲宽度调制”。

频率 = 1 / 总持续时间
总持续时间 = 接通时间 + 断开时间

PWM信号的频率决定了PWM完成一个信号周期的速度。周期是指PWM信号完成一个接通和关闭的时间。

【单片机STM32】通用定时器的PWM输出原理

在这里插入图片描述 在PWM输出模式下,除了CNT(计数器当前值)、ARR(自动重装载值)之外,还多了一个值CCRx(捕获/比较寄存器值)。

当CNT小于CCRx时,TIMx_CHx通道输出低电平;
当CNT等于或大于CCRx时,TIMx_CHx通道输出高电平。

PWM的通道概览 未写完

PWM输出的模式区别
通过设置寄存器TIMx_CCMR1的OC1M[2:0]位来确定PWM的输出模式:

PWM模式1:在向上计数时,一旦TIMx_CNT<TIMx_CCR1时通道1为有效电平,否则为无效电平;在向下计数时,一旦TIMx_CNT>TIMx_CCR1时通道1为无效电平(OC1REF=0),否则为有效电平(OC1REF=1)。
PWM模式2:在向上计数时,一旦TIMx_CNT<TIMx_CCR1时通道1为无效电平,否则为有效电平;在向下计数时,一旦TIMx_CNT>TIMx_CCR1时通道1为有效电平,否则为无效电平。

注意:PWM的模式只是区别什么时候是有效电平,但并没有确定是高电平有效还是低电平有效。这需要结合CCER寄存器的CCxP位的值来确定。

***PWM的计数模式***向上或向下计数

自动加载的预加载寄存器

PWM相关配置寄存器
捕获/比较模式寄存器1(TIMx_CCMR1)

捕获/比较使能寄存器(TIMx_CCER)

PWM相关配置库函数

1个输出初始化函数

void TIM_OC1Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);
void TIM_OC2Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);
void TIM_OC3Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);
void TIM_OC4Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);

作用:在四个通道中选择一个,初始化PWM输出模式、比较输出极性、比较输出使能、比较值CCRx的值。

1个参数设置函数

void TIM_SetCompare1(TIM_TypeDef* TIMx, uint16_t Compare1);
void TIM_SetCompare2(TIM_TypeDef* TIMx, uint16_t Compare2);
void TIM_SetCompare3(TIM_TypeDef* TIMx, uint16_t Compare3);
void TIM_SetCompare4(TIM_TypeDef* TIMx, uint16_t Compare4);

作用:在四个通道中选择一个,设置比较值。通常在初始化函数中已经设置了比较值,此函数用于除初始化之外的修改。

2个使能函数

void TIM_OC1PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload);
void TIM_OC2PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload);
void TIM_OC3PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload);
void TIM_OC4PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload);
void TIM_ARRPreloadConfig(TIM_TypeDef* TIMx, FunctionalState NewState);

作用:前者在四个通道中选择一个,使能输出比较预装载,后者使能自动重装载的预装载寄存器允许位。

PWM的一般步骤

  1. 使能定时器和相关IO口时钟。调用函数:RCC_APB1PeriphClockCmd();RCC_APB2PeriphClockCmd();

  2. 初始化IO口为复用功能输出。调用函数:GPIO_Init();

  3. 这里我们是要把PB5用作定时器的PWM输出引脚,所以要重映射配置,所以需要开启AFIO时钟。同时设置重映射。调用函数:RCC_APB2PeriphClockCmd();GPIO_PinRemapConfig();

  4. 初始化定时器。调用函数:ARR,PSC等:TIM_TimeBaseInit();

  5. 初始化输出比较参数。调用函数:TIM_OC2Init();

  6. 使能预装载寄存器。调用函数:TIM_OC2PreloadConfig();

  7. 使能定时器。调用函数:TIM_Cmd();

  8. 不断改变比较值CCRx,达到不同的占空比效果。调用函数:TIM_SetCompare2()。

下面按照这个一般步骤来进行一个简单的PWM输出程序:

//PWM输出初始化
//arr:自动重装值
//psc:时钟预分频数
//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
	
 
}
 int main(void)
 {		
 	u16 led0pwmval=0;
	u8 dir=1;	
	delay_init();	    	 //延时函数初始化	  
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); 	 //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
	uart_init(115200);	 //串口初始化为115200
 	LED_Init();			     //LED端口初始化
 	TIM3_PWM_Init(899,0);	 //不分频。PWM频率=72000000/900=80Khz
   	while(1)
	{
 		delay_ms(10);	 
		if(dir)led0pwmval++;
		else led0pwmval--;
 
 		if(led0pwmval>300)dir=0;
		if(led0pwmval==0)dir=1;										 
		TIM_SetCompare2(TIM3,led0pwmval);		   
	}	 
 }

NOTE:
关键参数设置:
初始化时钟参数结构体中:

TIM_TimeBaseStructure.TIM_Period = arr
自动重装载寄存器的值arr

TIM_TimeBaseStructure.TIM_Prescaler =psc
分频系数

输出的PWM频率 Hz在这里插入图片描述72M为STM32最高晶振频率

PWM输出舒适化函数
TIM_OCInitStructure.TIM_Pulse =arr * Duty (Pluse脉宽)

PWM占空比 = Duty(≤100%)

最后

以上就是甜甜发卡为你收集整理的STM32单片机PWM输出学习的全部内容,希望文章能够帮你解决STM32单片机PWM输出学习所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(42)

评论列表共有 0 条评论

立即
投稿
返回
顶部