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);
    }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章