STM32笔记之PWM输出,调节频率及占空比

 以STM32F103C8T6使用TIM1的CH1,CH4同时输出两路PWM为例:

引脚 定时器 通道
PA8 TIM1 CH1
PA11 TIM1 CH4

步骤:

    GPIO_InitTypeDef GPIO_InitStruct;                 //GPIO初始化结构体
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;   //定时器初始化结构体
	TIM_OCInitTypeDef TIM_OCInitStruct;				  //定时器通道初始化结构体

1.开启时钟:同时打开GPIOA,TIM1,复用时钟。

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_TIM1 | RCC_APB2Periph_AFIO,ENABLE);//开启时钟

2. 初始化GPIOA:

     GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AF_PP;       		     // 初始化GPIO--PA8、PA11为复用推挽输出
     GPIO_InitStruct.GPIO_Pin=GPIO_Pin_8 | GPIO_Pin_11;
     GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
     GPIO_Init(GPIOA,&GPIO_InitStruct);                          //GPIO初始化

3.初始化定时器:

    TIM_TimeBaseStructInit(&TIM_TimeBaseInitStruct);            //用其默认值填充每个TIM_TimeBaseInitStruct成员
    TIM_TimeBaseInitStruct.TIM_ClockDivision=TIM_CKD_DIV1;      //分频因子
    TIM_TimeBaseInitStruct.TIM_CounterMode=TIM_CounterMode_Up;  //向上计数模式
    TIM_TimeBaseInitStruct.TIM_Period=Per;                      //自动重装载值
    TIM_TimeBaseInitStruct.TIM_Prescaler=Psc;	                //预分频值
    TIM_TimeBaseInit(TIM1,&TIM_TimeBaseInitStruct);             //完成定时器初始化

 4.初始化定时器通道:

    TIM_OCInitStruct.TIM_OCMode=TIM_OCMode_PWM1;     		 //初始化输出比较
    TIM_OCInitStruct.TIM_OCPolarity=TIM_OCPolarity_High;
    TIM_OCInitStruct.TIM_OutputState=TIM_OutputState_Enable;
    TIM_OCInitStruct.TIM_Pulse=0;
    TIM_OC1Init(TIM1,&TIM_OCInitStruct);                    //定时器通道1初始化
    TIM_OC4Init(TIM1,&TIM_OCInitStruct);                    //定时器通道4初始化
    	
    TIM_OC1PreloadConfig(TIM1,TIM_OCPreload_Enable);// OC1预装载寄存器使能//CH1 TIM1
    TIM_OC4PreloadConfig(TIM1,TIM_OCPreload_Enable);// OC4预装载寄存器使能//CH4 TIM1

5.完成初始化:

	TIM_ARRPreloadConfig(TIM1,ENABLE); //允许或禁止在定时器工作时向ARR(自动重装载值)的缓冲器中写入新值,以便在更新事件发生时载入覆盖以前的值,此处为允许
	TIM_CtrlPWMOutputs(TIM1,ENABLE);// 高级定时器专属!!!(通用定时器不用此函数)--MOE主输出使能 //高级定时器TIM1:必须有这个函数才能输出PWM: TIM_CtrlPWMOutputs(TIM1,ENABLE);
	TIM_Cmd(TIM1,ENABLE);           //定时器使能

完整的PWM初始化函数:

/**********************************************************
** 函数名:PWM_Init_TIM1
** 功能描述: 定时器初始化函数
** 入口参数:预分频值,自动重装载值
** 输入参数: Psc(预分频值),Arr(自动重装载值)
** 输出参数: 无
***********************************************************/
void PWM_Init_TIM1(u16 Psc,u16 Arr) 
{
	GPIO_InitTypeDef GPIO_InitStruct;                    //GPIO初始化
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;      //定时器初始化
	TIM_OCInitTypeDef TIM_OCInitStruct;				    //定时器通道初始化
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_TIM1 | RCC_APB2Periph_AFIO,ENABLE);//开启时钟
	
	GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AF_PP;      // 初始化GPIO--PA8、PA11为复用推挽输出
	GPIO_InitStruct.GPIO_Pin=GPIO_Pin_8 | GPIO_Pin_11;
	GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&GPIO_InitStruct);                          //GPIO初始化
	
	TIM_TimeBaseStructInit(&TIM_TimeBaseInitStruct);            //用其默认值填充每个TIM_TimeBaseInitStruct成员
	TIM_TimeBaseInitStruct.TIM_ClockDivision=TIM_CKD_DIV1;      //分频因子
	TIM_TimeBaseInitStruct.TIM_CounterMode=TIM_CounterMode_Up;  //向上计数模式
	TIM_TimeBaseInitStruct.TIM_Period=Arr;                      //自动重装载值
	TIM_TimeBaseInitStruct.TIM_Prescaler=Psc;				    //预分频值
	TIM_TimeBaseInit(TIM1,&TIM_TimeBaseInitStruct);             //完成定时器初始化
	
	TIM_OCInitStruct.TIM_OCMode=TIM_OCMode_PWM1;     			 // 初始化输出比较
	TIM_OCInitStruct.TIM_OCPolarity=TIM_OCPolarity_High;
	TIM_OCInitStruct.TIM_OutputState=TIM_OutputState_Enable;
	TIM_OCInitStruct.TIM_Pulse=0;
	TIM_OC1Init(TIM1,&TIM_OCInitStruct);//定时器通道1初始化
	TIM_OC4Init(TIM1,&TIM_OCInitStruct);//定时器通道4初始化
	
	TIM_OC1PreloadConfig(TIM1,TIM_OCPreload_Enable);// OC1预装载寄存器使能//CH1 TIM1
	TIM_OC4PreloadConfig(TIM1,TIM_OCPreload_Enable);// OC4预装载寄存器使能//CH4 TIM1
	
	TIM_ARRPreloadConfig(TIM1,ENABLE); //允许或禁止在定时器工作时向ARR(自动重装载值)的缓冲器中写入新值,以便在更新事件发生时载入覆盖以前的值,此处为允许
	TIM_CtrlPWMOutputs(TIM1,ENABLE); //高级定时器专属!!!--MOE主输出使能 //高级定时器TIM1:必须有这个函数才能输出PWM: TIM_CtrlPWMOutputs(TIM1,ENABL);
	TIM_Cmd(TIM1,ENABLE);           //定时器使能
	
	//TIM_SetCompare1(TIM1,500);//设置TIMx捕获比较1寄存器值  此处为TIM1通道1
	//TIM_SetCompare4(TIM1,500);//设置TIMx捕获比较4寄存器值  此处为TIM1通道4
}

修改输出PWM的频率和占空比

1.频率:

PWM的频率 = 时钟频率  / (自动重装载值 + 1) * (预分频值 + 1)

STM32F103C8T6最大时钟频率为72MHZ = 72 000 000 HZ 

通过修改Psc和Arr可以输出不同频率的PWM输出

    PWM_Init_TIM1(0,7199); // PWM频率 f = 72000000/(7199+1)*(0+1) = 10KHZ
                           // PWM周期 T = 1/f = 1/10000 = 0.0001S = 0.1ms

2.占空比:

使用函数

TIM_SetComparex(TIM_TypeDef* TIMx, uint16_t Comparex)

/**
  * @brief  Sets the TIMx Capture Compare1 Register value
  * @param  TIMx: where x can be 1 to 17 except 6 and 7 to select the TIM peripheral.
  * @param  Compare1: specifies the Capture Compare1 register new value.
  * @retval None
  */
void TIM_SetCompare1(TIM_TypeDef* TIMx, uint16_t Compare1)
{
  /* Check the parameters */
  assert_param(IS_TIM_LIST8_PERIPH(TIMx));
  /* Set the Capture Compare1 Register value */
  TIMx->CCR1 = Compare1;
}

 Compare1(CH1)是用于与TIMx比较的数,相当于用TIMx的一个周期的时间减去这个Compare1,使得TIMx的周期从后面开始的Compare1的时间为TIMx的前部分时间的反向。即若前部分时间为高电平,则Compare1段所在时间为低电平。若前部分时间为低电平,则Compare1段所在时间为高电平。(可通过配置PWM模式及CCER修改,参考正点原子PWM输出实验)

图片源自正点原子

PWM占空比 = CCRx/ARR    或   PWM占空比 =( ARR-CCRx)/ARR

    PWM_Init_TIM1(0,7199); // PWM频率 f = 72000000/(7199+1)*(0+1) = 10KHZ
                        // PWM周期 T = 1/f = 1/10000 = 0.0001S = 0.1ms

    TIM_SetCompare1(TIM1,3599);//设置TIMx捕获比较1寄存器值  此处为TIM1通道1 占空比为50%
    TIM_SetCompare4(TIM1,3599);//设置TIMx捕获比较4寄存器值  此处为TIM1通道4 占空比为50%


版权声明:本文为CSDN博主「快醒醒该睡了」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_51636477/article/details/121088952

 以STM32F103C8T6使用TIM1的CH1,CH4同时输出两路PWM为例:

引脚 定时器 通道
PA8 TIM1 CH1
PA11 TIM1 CH4

步骤:

    GPIO_InitTypeDef GPIO_InitStruct;                 //GPIO初始化结构体
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;   //定时器初始化结构体
	TIM_OCInitTypeDef TIM_OCInitStruct;				  //定时器通道初始化结构体

1.开启时钟:同时打开GPIOA,TIM1,复用时钟。

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_TIM1 | RCC_APB2Periph_AFIO,ENABLE);//开启时钟

2. 初始化GPIOA:

     GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AF_PP;       		     // 初始化GPIO--PA8、PA11为复用推挽输出
     GPIO_InitStruct.GPIO_Pin=GPIO_Pin_8 | GPIO_Pin_11;
     GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
     GPIO_Init(GPIOA,&GPIO_InitStruct);                          //GPIO初始化

3.初始化定时器:

    TIM_TimeBaseStructInit(&TIM_TimeBaseInitStruct);            //用其默认值填充每个TIM_TimeBaseInitStruct成员
    TIM_TimeBaseInitStruct.TIM_ClockDivision=TIM_CKD_DIV1;      //分频因子
    TIM_TimeBaseInitStruct.TIM_CounterMode=TIM_CounterMode_Up;  //向上计数模式
    TIM_TimeBaseInitStruct.TIM_Period=Per;                      //自动重装载值
    TIM_TimeBaseInitStruct.TIM_Prescaler=Psc;	                //预分频值
    TIM_TimeBaseInit(TIM1,&TIM_TimeBaseInitStruct);             //完成定时器初始化

 4.初始化定时器通道:

    TIM_OCInitStruct.TIM_OCMode=TIM_OCMode_PWM1;     		 //初始化输出比较
    TIM_OCInitStruct.TIM_OCPolarity=TIM_OCPolarity_High;
    TIM_OCInitStruct.TIM_OutputState=TIM_OutputState_Enable;
    TIM_OCInitStruct.TIM_Pulse=0;
    TIM_OC1Init(TIM1,&TIM_OCInitStruct);                    //定时器通道1初始化
    TIM_OC4Init(TIM1,&TIM_OCInitStruct);                    //定时器通道4初始化
    	
    TIM_OC1PreloadConfig(TIM1,TIM_OCPreload_Enable);// OC1预装载寄存器使能//CH1 TIM1
    TIM_OC4PreloadConfig(TIM1,TIM_OCPreload_Enable);// OC4预装载寄存器使能//CH4 TIM1

5.完成初始化:

	TIM_ARRPreloadConfig(TIM1,ENABLE); //允许或禁止在定时器工作时向ARR(自动重装载值)的缓冲器中写入新值,以便在更新事件发生时载入覆盖以前的值,此处为允许
	TIM_CtrlPWMOutputs(TIM1,ENABLE);// 高级定时器专属!!!(通用定时器不用此函数)--MOE主输出使能 //高级定时器TIM1:必须有这个函数才能输出PWM: TIM_CtrlPWMOutputs(TIM1,ENABLE);
	TIM_Cmd(TIM1,ENABLE);           //定时器使能

完整的PWM初始化函数:

/**********************************************************
** 函数名:PWM_Init_TIM1
** 功能描述: 定时器初始化函数
** 入口参数:预分频值,自动重装载值
** 输入参数: Psc(预分频值),Arr(自动重装载值)
** 输出参数: 无
***********************************************************/
void PWM_Init_TIM1(u16 Psc,u16 Arr) 
{
	GPIO_InitTypeDef GPIO_InitStruct;                    //GPIO初始化
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;      //定时器初始化
	TIM_OCInitTypeDef TIM_OCInitStruct;				    //定时器通道初始化
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_TIM1 | RCC_APB2Periph_AFIO,ENABLE);//开启时钟
	
	GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AF_PP;      // 初始化GPIO--PA8、PA11为复用推挽输出
	GPIO_InitStruct.GPIO_Pin=GPIO_Pin_8 | GPIO_Pin_11;
	GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&GPIO_InitStruct);                          //GPIO初始化
	
	TIM_TimeBaseStructInit(&TIM_TimeBaseInitStruct);            //用其默认值填充每个TIM_TimeBaseInitStruct成员
	TIM_TimeBaseInitStruct.TIM_ClockDivision=TIM_CKD_DIV1;      //分频因子
	TIM_TimeBaseInitStruct.TIM_CounterMode=TIM_CounterMode_Up;  //向上计数模式
	TIM_TimeBaseInitStruct.TIM_Period=Arr;                      //自动重装载值
	TIM_TimeBaseInitStruct.TIM_Prescaler=Psc;				    //预分频值
	TIM_TimeBaseInit(TIM1,&TIM_TimeBaseInitStruct);             //完成定时器初始化
	
	TIM_OCInitStruct.TIM_OCMode=TIM_OCMode_PWM1;     			 // 初始化输出比较
	TIM_OCInitStruct.TIM_OCPolarity=TIM_OCPolarity_High;
	TIM_OCInitStruct.TIM_OutputState=TIM_OutputState_Enable;
	TIM_OCInitStruct.TIM_Pulse=0;
	TIM_OC1Init(TIM1,&TIM_OCInitStruct);//定时器通道1初始化
	TIM_OC4Init(TIM1,&TIM_OCInitStruct);//定时器通道4初始化
	
	TIM_OC1PreloadConfig(TIM1,TIM_OCPreload_Enable);// OC1预装载寄存器使能//CH1 TIM1
	TIM_OC4PreloadConfig(TIM1,TIM_OCPreload_Enable);// OC4预装载寄存器使能//CH4 TIM1
	
	TIM_ARRPreloadConfig(TIM1,ENABLE); //允许或禁止在定时器工作时向ARR(自动重装载值)的缓冲器中写入新值,以便在更新事件发生时载入覆盖以前的值,此处为允许
	TIM_CtrlPWMOutputs(TIM1,ENABLE); //高级定时器专属!!!--MOE主输出使能 //高级定时器TIM1:必须有这个函数才能输出PWM: TIM_CtrlPWMOutputs(TIM1,ENABL);
	TIM_Cmd(TIM1,ENABLE);           //定时器使能
	
	//TIM_SetCompare1(TIM1,500);//设置TIMx捕获比较1寄存器值  此处为TIM1通道1
	//TIM_SetCompare4(TIM1,500);//设置TIMx捕获比较4寄存器值  此处为TIM1通道4
}

修改输出PWM的频率和占空比

1.频率:

PWM的频率 = 时钟频率  / (自动重装载值 + 1) * (预分频值 + 1)

STM32F103C8T6最大时钟频率为72MHZ = 72 000 000 HZ 

通过修改Psc和Arr可以输出不同频率的PWM输出

    PWM_Init_TIM1(0,7199); // PWM频率 f = 72000000/(7199+1)*(0+1) = 10KHZ
                           // PWM周期 T = 1/f = 1/10000 = 0.0001S = 0.1ms

2.占空比:

使用函数

TIM_SetComparex(TIM_TypeDef* TIMx, uint16_t Comparex)

/**
  * @brief  Sets the TIMx Capture Compare1 Register value
  * @param  TIMx: where x can be 1 to 17 except 6 and 7 to select the TIM peripheral.
  * @param  Compare1: specifies the Capture Compare1 register new value.
  * @retval None
  */
void TIM_SetCompare1(TIM_TypeDef* TIMx, uint16_t Compare1)
{
  /* Check the parameters */
  assert_param(IS_TIM_LIST8_PERIPH(TIMx));
  /* Set the Capture Compare1 Register value */
  TIMx->CCR1 = Compare1;
}

 Compare1(CH1)是用于与TIMx比较的数,相当于用TIMx的一个周期的时间减去这个Compare1,使得TIMx的周期从后面开始的Compare1的时间为TIMx的前部分时间的反向。即若前部分时间为高电平,则Compare1段所在时间为低电平。若前部分时间为低电平,则Compare1段所在时间为高电平。(可通过配置PWM模式及CCER修改,参考正点原子PWM输出实验)

图片源自正点原子

PWM占空比 = CCRx/ARR    或   PWM占空比 =( ARR-CCRx)/ARR

    PWM_Init_TIM1(0,7199); // PWM频率 f = 72000000/(7199+1)*(0+1) = 10KHZ
                        // PWM周期 T = 1/f = 1/10000 = 0.0001S = 0.1ms

    TIM_SetCompare1(TIM1,3599);//设置TIMx捕获比较1寄存器值  此处为TIM1通道1 占空比为50%
    TIM_SetCompare4(TIM1,3599);//设置TIMx捕获比较4寄存器值  此处为TIM1通道4 占空比为50%


版权声明:本文为CSDN博主「快醒醒该睡了」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_51636477/article/details/121088952

生成海报
点赞 0

快醒醒该睡了

我还没有学会写个人说明!

暂无评论

发表评论

相关推荐

ESP32S2+ES8388移植过程及问题

电路图如下, 有点小瑕疵ES8388_VMID PIN10/19/20电容没有忘加,查资料应该不影响语言输出,可能噪音大,如果能导致不输出请告诉我一下。 ESP32S2管脚映射 这里主

stm32f373利用esp8266连接onenet平台

学习目标: 1.注册onenet平台 2.esp8266引脚连接 3.stm32373代码移植编写 提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 一、注册onene