stm32 定时器 PWM 更改频率

TIM_Period  溢出计数值,(如有中断)达到这个值就中断  arr

TIM_Prescaler 预分频 psc

调节占空比 TIMx_SetCompare(1,0-arr);         //TIM x为定时器数字如TIM2、TIM3,参数1位通道,参数2为ccr 此致时间内与电平翻转 比如默认0-arr都为高电平,如setcompare的值为arr/2,就是0-arr/2 为低电平  arr/2-arr为高电平  占空比 50%。

时钟频率为 72M

公式:

时钟频率(system clk) / 预分频(psc) /想要的pwm频率 = arr(重装值)

例子 : 72M / 1 / 2000HZ  = 36000

arr和psc在设置的时候都要减一,因为在硬件上会自动加一,就是 psc = 0 , arr = 35999

TIM_TimeBaseStructure.TIM_Period = (1000-1); //设置在下一个更新事件装入 活动活动的自动重装载寄存器周期的值计数到1000为1ms

TIM_TimeBaseStructure.TIM_Prescaler =(72-1); //设置用来作为TIMx时钟频率除数的预分频值  1M的计数频率

                     arr   * psc  /  时钟频率 = 定时时间

定时时间T = 1000 * 72 / 72000 000 = 1ms

TIM_Prescaler = 72 – 1; t = 72 / 72000 000 = 1us,即TIMx->CNT每1us加一次

TIM_Period = 1000;当TIMx->CNT计数值达到1000us(也就是一开始计算的定时时间1ms),进入中断服务函数,msHcCount将自动加一

调节频率:
1.通过更改预分频器的值,改变计数器的频率的方式改变PWM波的频率
在STM32F103中有封装好的调节预分频器的函数 TIM_PrescalerConfig();直接调用即可。

      

溢出计数值(arr  值域0-65536)=72MHz/想得到的频率

按照72M的预分频,频率 (范围约等于)= 1100HZ  - 72MHZ

例子:

volatile uint32 pulse_width = 0;
volatile uint32	direction = 0;

void PWM_Init(u16 arr,u16 psc)
{
	GPIO_InitTypeDef  GPIO_InitStructure;
	TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
	TIM_OCInitTypeDef TIM_OCInitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;
	
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOA,ENABLE);

	
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3;        
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;                    //IO口复用推挽输出
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;                  //IO口速度
	GPIO_Init(GPIOA, &GPIO_InitStructure);	//USART输出IO口
	
	TIM_DeInit(TIM2);
	
	TIM_TimeBaseStructure.TIM_Period = arr; //定时周期
	TIM_TimeBaseStructure.TIM_Prescaler =psc; //预分频1,36M
	TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //时钟分频因子
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //向上计数模式
	TIM_TimeBaseInit(TIM2,&TIM_TimeBaseStructure);
	
	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //输出PWM模式
	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //使能输出
	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;//输出极性
	TIM_OCInitStructure.TIM_Pulse = 50;
	
	TIM_OC1Init(TIM2,&TIM_OCInitStructure);
	TIM_OC2Init(TIM2,&TIM_OCInitStructure);
	TIM_OC3Init(TIM2,&TIM_OCInitStructure);
	TIM_OC4Init(TIM2,&TIM_OCInitStructure);
	
	TIM_OC1PreloadConfig(TIM2,TIM_OCPreload_Enable);
	TIM_OC2PreloadConfig(TIM2,TIM_OCPreload_Enable);
	TIM_OC3PreloadConfig(TIM2,TIM_OCPreload_Enable);
	TIM_OC4PreloadConfig(TIM2,TIM_OCPreload_Enable);

//可以选择有中断或无中断
//	TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE );
//		
//	NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; 
//	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; 
//	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;  
//	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
//	NVIC_Init(&NVIC_InitStructure);  


	//TIM_ARRPreloadConfig(TIM2,ENABLE);
	TIM_Cmd(TIM2,ENABLE);
}

//可以选择有中断或无中断
void TIM2_IRQHandler(void)
{
	if(TIM_GetITStatus(TIM2,TIM_IT_Update) != RESET)
	{
		TIM_ClearITPendingBit(TIM2,TIM_IT_Update);
		
		if(pulse_width == 0)
			direction = 0;
		else if(pulse_width == 100)
			direction = 1;

		if(direction == 0)
			pulse_width++;
		else
			pulse_width--;
		TIM_SetCompare1(TIM2, pulse_width);
		
	}

}

//频率 5k,10k,20k,50k,100k
unsigned short fres[5] = {14399,7199,3599,1439,719};

int main()                                                                          
{   

		ledinit();

		PWM_Init(99,7199);

		while(1)
		{

		for(i=0;i<5;i++)
		{
        //这里的 tim_cmd disable 和 enable 可以不加,没影响  delay_ms也是
   		TIM_Cmd(TIM2,DISABLE);
        delay_ms(5);
		TIM_PrescalerConfig(TIM2,fres[i],TIM_PSCReloadMode_Immediate);
        TIM_SetCounter(TIM2,0);
		TIM_Cmd(TIM2,ENABLE);
		delay_ms(50);
		}
			
		}
}

 

2通过普通定时器的中断去更新gpio的输出方式改变PWM波的频率,微调setcount 的值可以平缓过渡频率
例子:

void ledinit()
{
	GPIO_InitTypeDef GPIO_InitStructure;
	RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB , ENABLE); 						 					 
	GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_12;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 
	GPIO_Init(GPIOB, &GPIO_InitStructure);
	GPIO_SetBits(GPIOB , GPIO_Pin_12);
	
}

void MY_TIM3_Init(u16 arr,u16 psc){

	NVIC_InitTypeDef NVIC_InitStructure;
    TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;


    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);


    TIM_TimeBaseStructure.TIM_Period = arr;
    TIM_TimeBaseStructure.TIM_Prescaler = psc;


    TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //????
    TIM_TimeBaseInit(TIM3,&TIM_TimeBaseStructure);
		
	TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE );
	NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn; 
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;  
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;  
	NVIC_Init(&NVIC_InitStructure);  

    TIM_Cmd(TIM3,ENABLE);
}

void TIM3_IRQHandler(void)
{
	if(TIM_GetITStatus(TIM3,TIM_IT_Update) != RESET)
	{
		TIM_ClearITPendingBit(TIM3,TIM_IT_Update);
		ledcount++;
		if(ledcount > setcount)
		{
			ledcount = 0;
			ledstate = ~ledstate;
			if(ledstate > 0)
			{
				GPIO_SetBits(GPIOB , GPIO_Pin_12);
			}
			else
			{
				GPIO_ResetBits(GPIOB , GPIO_Pin_12);
			}
			
			
		}

		
	}
}

volatile uint32 ledcount = 0;
volatile uint32 setcount = 1;

int main()                                                                          
{  
    MY_TIM3_Init(9,7199);
    ledinit();


		while(1)
		{
			setcount++;
			if(setcount > 100)
			{
					setcount = 1;
			}
			delay_ms(100);
        }
}

2通过更改arr值改变PWM波的频率
例子:

void PWM_Init(u16 arr,u16 psc)
{
	GPIO_InitTypeDef  GPIO_InitStructure;
	TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
	TIM_OCInitTypeDef TIM_OCInitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;
	
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOA,ENABLE);

	
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3;        
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;                    //IO口复用推挽输出
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;                  //IO口速度
	GPIO_Init(GPIOA, &GPIO_InitStructure);	//USART输出IO口
	
	TIM_DeInit(TIM2);
	
	TIM_TimeBaseStructure.TIM_Period = arr; //定时周期
	TIM_TimeBaseStructure.TIM_Prescaler =psc; //预分频1,36M
	TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //时钟分频因子
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //向上计数模式
	TIM_TimeBaseInit(TIM2,&TIM_TimeBaseStructure);
	
	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //输出PWM模式
	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //使能输出
	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;//输出极性
	TIM_OCInitStructure.TIM_Pulse = (int)(arr+1)/2;;
	
	

	
	TIM_OC1Init(TIM2,&TIM_OCInitStructure);
//	TIM_OC2Init(TIM2,&TIM_OCInitStructure);
//	TIM_OC3Init(TIM2,&TIM_OCInitStructure);
//	TIM_OC4Init(TIM2,&TIM_OCInitStructure);
	
	TIM_OC1PreloadConfig(TIM2,TIM_OCPreload_Enable);
//	TIM_OC2PreloadConfig(TIM2,TIM_OCPreload_Enable);
//	TIM_OC3PreloadConfig(TIM2,TIM_OCPreload_Enable);
//	TIM_OC4PreloadConfig(TIM2,TIM_OCPreload_Enable);


//	TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE );
//		
//	NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; 
//	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; 
//	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;  
//	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
//	NVIC_Init(&NVIC_InitStructure);  


	TIM_ARRPreloadConfig(TIM2,ENABLE);
	TIM_Cmd(TIM2,ENABLE);
}



//PWM_Init(35999,0);				//2k, 4k,   8,    16k,   32k,     64k    144k   480k
unsigned short sfresarr[8] = {35999,17999,8999, 4499,  2249   ,  1124   ,499   ,149 };

int main()
{
	SystemInit();
    PWM_Init(35999,0);
	while(1)
	{
		TIM_Cmd(TIM2,DISABLE);
		TIM_ARRPreloadConfig(TIM2,DISABLE);
		delay_ms(20);
		TIM_SetCompare1(TIM2, sfresarr[i+1]);
		TIM_SetAutoreload(TIM2, sfresarr[7]);
		TIM_ARRPreloadConfig(TIM2,ENABLE);
        TIM_SetCounter(TIM2,0);
		TIM_Cmd(TIM2,ENABLE);
		delay_ms(500);
    }
}

关于在keil软件仿真如何看io口电平变化问题补充

        首先在keil的程序界面点魔法棒

        将仿真设置成软件仿真,先点击DEBUG栏,选中use simulator 然后点ok

         然后点击debug调试

         点击示波器调出示波器界面

         点击Setup设置要查看的IO口,然后2新建端口,3里面输入PORTA.2(这里表示GPIOA的2号引脚)。其他IO设置也是类似。设置好后点击空白地方,就完成了。

 

         设置查看IO的输出显示类型,1选中GPIO,2设置Display Type,选为Bit类型,3然后Close就完成了。直接运行仿真就能看到波形输出了。

-------------------------------------------------更新2022.10.10--------------------------------------------------------

关于源码,其实大家只要新建一个keil工程,将上面的代码复制到main.c中基本就直接能跑了,缺点定义啥的可以自己补一下。

由于评论区有很多人求源码,源码久远找不到了,有个大致类似的代码,可以将上面的例子复制进去删掉重复的就能运行了。需要的自取

频率控制源码 github

  • 70
    点赞
  • 357
    收藏
    觉得还不错? 一键收藏
  • 15
    评论
STM32定时器中,要修改PWM频率,可以通过以下步骤进行操作: 1. 首先,需要对定时器进行初始化,并配置好预分频器(PSC)和自动重载寄存器(ARR),以确定定时器的周期频率。这可以通过调用TIM_TimeBaseInitTypeDef结构体中的相关函数来实现。\[1\] 2. 接下来,需要配置输出比较模式(TIM_OCMode)和脉冲宽度(TIM_Pulse),以确定PWM的占空比。这可以通过调用TIM_OCInitTypeDef结构体中的相关函数来实现。\[2\] 3. 修改PWM频率时,可以通过修改预分频器(PSC)的值来实现。较小的PSC值将导致更高的频率,较大的PSC值将导致较低的频率。因此,可以根据需要调整PSC的值来修改PWM频率。\[1\] 需要注意的是,修改PWM频率可能会影响其他定时器功能的正常运行,因此在修改之前需要仔细考虑和测试。另外,具体的代码实现可能会因为使用的STM32系列和开发环境的不同而有所差异,建议参考相关的开发文档和示例代码进行具体操作。 #### 引用[.reference_title] - *1* [STM32定时器输出pwm波](https://blog.csdn.net/m0_51637032/article/details/123716976)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* *3* [STM32 高级定时器 输出PWM波](https://blog.csdn.net/qq_62573253/article/details/126335766)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值