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