STM32F103ZET6 PWM输出

STM32 定时器3输出通道引脚
STM32F103ZET6 PWM输出_第1张图片

【 1. PWM工作过程 】

STM32F103ZET6 PWM输出_第2张图片
STM32F103ZET6 PWM输出_第3张图片
PWM周期由ARR决定,CCRx决定占空比

【 2. 内部逻辑 】

STM32F103ZET6 PWM输出_第4张图片
CCR1:捕获比较(值)寄存器(x=1,2,3,4):设置比较值。
CCMR1: OC1M[2:0]位:
对于PWM方式下,用于设置PWM模式1【110】或者PWM模式2【111】
CCER:CC1P位:输入/捕获1输出极性。0:高电平为有效电平,1:低电平为有效电平。
CCER:CC1E位:输入/捕获1输出使能。0:关闭,1:打开。

【 3. PWM模式 】

STM32F103ZET6 PWM输出_第5张图片

PWM模式1 & PWM模式2

寄存器TIMx_CCMR1的OC1M[2:0]位来分析:
STM32F103ZET6 PWM输出_第6张图片
STM32F103ZET6 PWM输出_第7张图片

【 4. 自动重载的预装载寄存器 】

STM32F103ZET6 PWM输出_第8张图片
void TIM_ARRPreloadConfig(TIM_TypeDef* TIMx, FunctionalState NewState);
当预重装载值改变后,ARPE=1,ARR立即生效。。。APRE=0,ARR下个比较周期生效。

【 5. 相关函数 】

①PWM初始化
void TIM_OCxInit(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);
②设置比较值函数
void TIM_SetCompareX(TIM_TypeDef* TIMx, uint16_t Compare2);
③使能输出比较预装载
void TIM_OC2PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload);
④使能自动重装载的预装载寄存器允许位
void TIM_ARRPreloadConfig(TIM_TypeDef* TIMx, FunctionalState NewState);

【 6. 配置过程 】

① 使能定时器3和相关IO口时钟。
使能定时器3时钟:RCC_APB1PeriphClockCmd();
使能GPIOB时钟:RCC_APB2PeriphClockCmd();
② 初始化IO口为复用功能输出。函数:GPIO_Init();
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
这里我们是要把PB5用作定时器的PWM输出引脚,所以要重映射配置,
所以需要开启AFIO时钟。同时设置重映射。
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3, ENABLE);
④ 初始化定时器:ARR,PSC等:TIM_TimeBaseInit();
⑤ 初始化输出比较参数:TIM_OC2Init();
⑥ 使能预装载寄存器: TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable);
⑦ 使能定时器。TIM_Cmd();
⑧ 不断改变比较值CCRx,达到不同的占空比效果:TIM_SetCompare2();

【 7. 范例 】

呈现呼吸灯的效果
PWM.h

void MYPWM_Init(u16 arr,u16 psc)
{
	GPIO_InitTypeDef MYPWMstructure;
	TIM_TimeBaseInitTypeDef MYTIM_PWMstructure;
	TIM_OCInitTypeDef MYOCPWMstructure;
	
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);   //使能定时器3的时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);   //使能GPIOB时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE); //使能AFIO时钟
    GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3, ENABLE); //开启重映射
	
	MYPWMstructure.GPIO_Mode=GPIO_Mode_AF_PP; //推挽复用输出
	MYPWMstructure.GPIO_Pin=GPIO_Pin_5;   //选择引脚
	MYPWMstructure.GPIO_Speed=GPIO_Speed_50MHz; //速度
	GPIO_Init(GPIOB,&MYPWMstructure);      //初始化GPIO
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE); //使能AFIO时钟
    GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3, ENABLE); //开启重映射
	
	
	MYTIM_PWMstructure.TIM_ClockDivision=0;//设置时钟分割:TDTS = Tck_tim
	MYTIM_PWMstructure.TIM_CounterMode=TIM_CounterMode_Up;//配置向上计数模式
	MYTIM_PWMstructure.TIM_Period=arr; //自动装载值
	MYTIM_PWMstructure.TIM_Prescaler=psc;//预分频系数
	TIM_TimeBaseInit(TIM3,&MYTIM_PWMstructure);    //初始化定时器
	
	MYOCPWMstructure.TIM_OCMode=TIM_OCMode_PWM2; //配置PWM模式2
	MYOCPWMstructure.TIM_OCPolarity=TIM_OCPolarity_High; //有效电平为高电平
	MYOCPWMstructure.TIM_OutputState=TIM_OutputState_Enable; //使能
	TIM_OC2Init(TIM3,&MYOCPWMstructure);  //初始化输出比较参数
	
	TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable); // 使能预装载寄存器
    TIM_Cmd(TIM3,ENABLE); //使能定时器
	
}

main.c

int main(void)
 {	
	u16 mycomp=0;  //比较值
	u8 flag=1;   //标志位。flag=1比较值自加,flag=0比较值自减
	delay_init();
	LED_Init();		  	//初始化与LED连接的硬件接口
	MYPWM_Init(899,0); //配置装载值799,不分频,则PWM频率=72K/(899+1)=80
	 while(1)
	{
		delay_ms(10);	 
		if(flag)  mycomp++;    //mycomp从0开始加到301,再减到0,再开始加到301,不断循环
		else      mycomp--;
		
		if(mycomp>300) flag=0;  //限幅
		if(mycomp==0) flag=1;
		TIM_SetCompare2(TIM3,mycomp);  //比较值不断改变导致占空比变化
 }
}
 

你可能感兴趣的:(STM32)