之前学东西总是模模糊糊,前几天看了pwm,虽然知道怎么配置,但是如果让我自己去写一个pwm的程序,我却不知如何下手。
不知道如何配置他的频率和占空比。今天痛定思痛,决定彻底搞懂pwm。
百度给 的答案是:
pwm的频率是指每秒钟信号从高电平到低电平再回到高电平的次数,占空比是高电平持续时间和低电平持续时间之间的比例。
pwm的频率越高,其对输出的响应就会越快,频率越低输出响应越慢。
首先pwm要知道他的频率,频率该如何设定呢?
看了这一位博主的文章让我名表了很多:http://blog.csdn.net/huang_jinjin/article/details/7292166?locationNum=6&fps=1
他的最后有这一段话,不分频的话,时钟是72mhz,就是每秒计数72m,而TIM_Period就是定义了pwm的一个周期记的次数,比如说是2000,就是经过2000/72m这个时间是一个周期,
那么频率就是周期的倒数,这个pwm的频率就是72m/2000(hz),这样就确定了频率。
那么TIMx_ARR寄存器的值是怎样来确定pwm的频率的呢?TIM_Period(即是TIMx_ARR寄存器的值) 的大小实际上表示的是需要经
过TIM_Period 次计数后才会发生一次更新或中断。接下来需要设置时钟预分频
数TIM_Prescaler,这里有一个公式,我们举例来说明:例如时钟频率=72MHZ/(时
钟预分频+1)。(假设72MHZ为系统运行的频率,这里的时钟频率即是产生这个pwm的时钟的频率)说明当前设置的这个TIM_Prescaler,直接决定定时器的时钟频率。
通俗点说,就是一秒钟能计数多少次。比如算出来的时钟频率是2000,也就是
一秒钟会计数2000 次,而此时如果TIM_Period 设置为4000,即4000 次计数后就会中断一次。由于时钟频率是一秒钟计数2000 次,因此只要2 秒钟,就会中
断一次。
还有一个需要注意的,就是我们一般采用向上计数模式。
接下来,就是占空比的配置了,注意下面这一句话:
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //选择定时器模式
已经选择定时器为pwm1,所以下面直接给TIMx_CCRx赋值就可以了。在pwm1模式下,IMx_CCRx的值越大,占空比就越大。
TIMx_CCRx寄存器,确定PWM的占空比。TIMx_CCR1—TIMx_CCR4确定定时器的CH1—CH4四路PWM的占空比。直接给该寄存器赋0—65535值即可确定占空比。占空比计算方法:TIMx_CCRx的值除以ARR寄存器的值即为占空比,因为占空比在0—100%之间,所以一般TIMx_CCRx寄存器值不能超过ARR寄存器的值,否则可能会引起PWM的频率或占空比的准确性。
好了,下面就是我自己写的并理解的程序了,只是简单的输出占空比
#include "stm32f10x.h" void gpio_init(void);///tim3的ch1,在pa6上面 void TIM2_init(void); int main(void) { gpio_init(); TIM2_init(); while(1); } void gpio_init() { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA , ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_Init(GPIOA, &GPIO_InitStructure); TIM2_init(); } void TIM2_init() { TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_OCInitTypeDef TIM_OCInitStructure; RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //PWM频率 = 72000000 / 4 / 1000 = 18Khz TIM_TimeBaseStructure.TIM_Period = 1000 - 1; //PWM计数上限 TIM_TimeBaseStructure.TIM_Prescaler = 4 - 1; //设置用来作为TIM2时钟频率除数的预分频值,4分频 TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIMx向上计数模式 TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根据TIM_TimeBaseStructure中指定的参数初始化外设TIM2 TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //选择定时器模式 TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能 TIM_OCInitStructure.TIM_Pulse = 200; //设置待装入捕获比较寄存器的脉冲值 TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性:TIM输出比较极性高 TIM_OC1Init(TIM3, &TIM_OCInitStructure); TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Enable); //使能TIM2在CCR1上的预装载寄存器 TIM_ARRPreloadConfig(TIM3, ENABLE); //使能TIM2在ARR上的预装载寄存器 TIM_Cmd(TIM3, ENABLE); //使能TIM2外设 }
固定的pwm波,实验证实,这里不需要中断函数,定时器会自动重装数值,32真是强大在这里啊。定时器自带BGM.