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