pwm输入捕获

PWM输入是输入捕获的一个特殊应用,输入捕获就是当链接到定时器的引脚上产生电平变化时对应的捕获装置会当即将当前计数值复制到另外一个寄存器中。你能够开启捕获中断而后在中断处理函数中读出保存的计数值。

与输入捕获不一样的是PWM输入模式会将同一个输入信号(TI1或TI2)链接到两个捕获装置(IC1和IC2)。这两个捕获装置一个捕获上升沿一个捕获降低沿。TI1FP一、TI2FP2它们中的一个被选择为触发输入且从模式控制器被配置为复位模式。函数

PWM输入捕获原理和时序图:
post

 

1)   当第一次上升沿到达时IC1捕获TIMx_CCR1的值为当前计数值4,IC2不会捕获TIMx_CCR2保持不变,计数器复位从0开始计数。
2) 第一个降低沿到达时IC2捕获TIMx_CCR2的值为2表示脉冲宽度。当上升再次到达时TIMx_CCR1的值就表示脉冲周期了(注意:第一次上升沿捕获的是个随机值)。
2)    原理也讲过了,那么下面就是实战了
1、操做步骤:
①将个人源码从论坛里面下载下来
②用杜邦线将PB7和PC6链接起来
③将编译完成的hex文件下载到开发板
④打开串口调试助手波特率选9600
⑤按下开发板的复位键,OK那么你就能看到串口的打印信息。
⑥用杜邦线依次将PB7和PC七、PB7和PC八、PB7和PC9链接起来,看串口打印不一样占空比和相同周期的信息。
2、主程序讲解:
①TIM3_PWM_Init(1000-1,72-1);   //1KHz的周期
这个计算相信大部分人应该没有问题原子哥也作过详细的讲解那么我在重复一遍
CPU主频是72MHZ 这里将72MHZ主频72分频,那么就为1MHZ,因此计数器每加1那么就是表明增长1US,我这里设置的是999,由于0-999正好是1000us,因此我设置的周期是1000us 也就是1KHZ
②TIM_SetCompare1(TIM3,200);
这个函数式设置PWM通道的占空比,由于周期是1000us因此我这里设置的是20%的占空比,这个计算我就算教小白吧  占空比 = 200/1000 我这里设置的是通道1也就是PC6的占空比。下面三个我就不讲了。
③TIM4_PWMINPUT_INIT(0xffff,72-1);
这个函数是PWM输入模式初始化,这个我设置的最大计数是0xffff,由于是16位的计数器固然最大也只能这么大了,后面的参数是设置捕捉频率的,我这里还设置为1MHz,这样为了好看实验现象。
④While(1){}
主程序那三个打印语句我就不讲了,这个都不会,那么你就该补补了。
3、四路PWM程序讲解:
①void TIM3_PWM_Init(u16 arr,u16 psc)
这个函数我不讲不少由于原子哥已经将的很清楚了,我就将几个注意的地方和你们说一下,
GPIO_PinRemapConfig(GPIO_FullRemap_TIM3, ENABLE); 这个函数式定时器的全映射,将
TIM3定时器的引脚映射到了PC6 C7 C8 C9上了。
4、PWM输入捕捉程序讲解:
①void TIM4_PWMINPUT_INIT(u16 arr,u16 psc)
这个函数我在源码里面已经注释的很清楚了,有几个点须要你们注意
②TIM_SelectInputTrigger(TIM4, TIM_TS_TI2FP2);    
这个是选择有效的输入端 ,我这里TIM_TS_TI2FP2选择的PB7,注意:只有TI1FP1和TI2FP2连到了从模式控制器,因此PWM输入模式只能使用TIMx_CH1 /TIMx_CH2信号。 
③TIM_SelectSlaveMode(TIM4, TIM_SlaveMode_Reset);  
这个是配置为PWM输入主从复位模式,就是每次输入端有效电平变化的时候定时器计数器就会硬件上置0
中断函数讲解
至于TIM4的中断函数很简单我就很少讲什么了,主要就是将捕捉到的周期和占空比记录下来。
 
注意:我提醒你们一下,我如今这个捕捉的周期的范围是1-65535us,若是你要捕捉的周期超出这个怎么办,我给你们一点建议①将捕获精度下降,也就是讲捕获频率降下来②这个就是用原子哥那种溢出计数的方法,可是这个有意思的是主从复位模式,每次复位也会产生更新中断,那么若是不加设置的话,可能这种方法是行不通的。可是我已经解决了,看手册介绍,解决的。哈哈,你们有兴趣的话,能够去试着解决,本身作的饭才是最香的。实在是想用第二种方法,可是又解决不了的,就能够回复,可是我想着仍是本身解决的好。


说了这么多,有的人可能会提出疑问?那你给咱们讲这些理论,你本身到底实现了没有?俗话说的好,有图有真相,没图说啥?那么好的上真相,不过是有偏差的,可是我认为这个偏差在接受范围内。
spa



---------------------------------------------------源码-------------------------------------------------------------------------------调试

                  PWM。chtm

#include "pwm.h"blog

 

 

/*功能名称IM3_PWM_Init(u16 arr,u16 psc)事件

    描述      TIM3产生四路PWMip

*/开发

 

void TIM3_PWM_Init(u16 arr,u16 psc)源码

    GPIO_InitTypeDefGPIO_InitStructure;

    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;

    TIM_OCInitTypeDef  TIM_OCInitStructure;

   

 

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC  | RCC_APB2Periph_AFIO, ENABLE);  //使能GPIO外设和AFIO复用功能模块时钟使能

   

 GPIO_PinRemapConfig(GPIO_FullRemap_TIM3, ENABLE); //Timer3全映射GPIOC-> 6,7,8,9                                                                         //用于TIM3CH2输出的PWM经过该LED显示

 

   //设置该引脚为复用输出功能,输出TIM3 CH1 CH2 CH3 CH4PWM脉冲波形

    GPIO_InitStructure.GPIO_Pin=GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9; //初始化GPIO

    GPIO_InitStructure.GPIO_Mode= GPIO_Mode_AF_PP;  //复用推挽输出

    GPIO_InitStructure.GPIO_Speed= GPIO_Speed_50MHz;

    GPIO_Init(GPIOC,&GPIO_InitStructure);

 

    TIM_TimeBaseStructure.TIM_Period= arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值

    TIM_TimeBaseStructure.TIM_Prescaler=psc; //设置用来做为TIMx时钟频率除数的预分频值 不分频

    TIM_TimeBaseStructure.TIM_ClockDivision= 0; //设置时钟分割:TDTS = Tck_tim

    TIM_TimeBaseStructure.TIM_CounterMode= TIM_CounterMode_Up;  //TIM向上计数模式

    TIM_TimeBaseInit(TIM3,&TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位

   

     

    TIM_OCInitStructure.TIM_OCMode= TIM_OCMode_PWM1; //选择定时器模式:TIM脉冲宽度调制模式1

    TIM_OCInitStructure.TIM_OutputState= TIM_OutputState_Enable; //比较输出使能

    TIM_OCInitStructure.TIM_Pulse= 0; //设置待装入捕获比较寄存器的脉冲值

    TIM_OCInitStructure.TIM_OCPolarity= TIM_OCPolarity_High; //输出极性:TIM输出比较极性高

   

    TIM_OC1Init(TIM3,&TIM_OCInitStructure);  //根据TIM_OCInitStruct中指定的参数初始化外设TIMx

    TIM_OC1PreloadConfig(TIM3,TIM_OCPreload_Enable);  //使能TIMxCCR1上的预装载寄存器

   

   

    TIM_OC2Init(TIM3,&TIM_OCInitStructure);  //根据TIM_OCInitStruct中指定的参数初始化外设TIMx

    TIM_OC2PreloadConfig(TIM3,TIM_OCPreload_Enable);  //使能TIMxCCR2上的预装载寄存器

   

    TIM_OC3Init(TIM3,&TIM_OCInitStructure);  //根据TIM_OCInitStruct中指定的参数初始化外设TIMx

    TIM_OC3PreloadConfig(TIM3,TIM_OCPreload_Enable);  //使能TIMxCCR3上的预装载寄存器

   

    TIM_OC4Init(TIM3,&TIM_OCInitStructure);  //根据TIM_OCInitStruct中指定的参数初始化外设TIMx

    TIM_OC4PreloadConfig(TIM3,TIM_OCPreload_Enable);  //使能TIMxCCR4上的预装载寄存器

   

    TIM_ARRPreloadConfig(TIM3,ENABLE); //使能TIMxARR上的预装载寄存器

   

 

    TIM_Cmd(TIM3,ENABLE);  //使能TIMx外设

 

 

}

 

 

 

/*功能名称IM4_PWMINPUT_INIT(u16 arr,u16psc)

  描述      PWM输入初始化*/

 

 

 

 

 

void TIM4_PWMINPUT_INIT(u16 arr,u16 psc)

{

 

    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;

    NVIC_InitTypeDefNVIC_InitStructure;

    TIM_ICInitTypeDef  TIM4_ICInitStructure;

    GPIO_InitTypeDefGPIO_InitStructure;

 

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4,ENABLE);     //Open TIM4 clock

 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);  //open gpioB clock

 

    GPIO_InitStructure.GPIO_Pin= GPIO_Pin_7;                              //GPIO??

 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;

 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

 GPIO_Init(GPIOB, &GPIO_InitStructure);

 

    TIM_TimeBaseStructure.TIM_Period= arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值 

    TIM_TimeBaseStructure.TIM_Prescaler=psc; //设置用来做为TIMx时钟频率除数的预分频值 

    TIM_TimeBaseStructure.TIM_ClockDivision= 0; //设置时钟分割:TDTS = Tck_tim

    TIM_TimeBaseStructure.TIM_CounterMode= TIM_CounterMode_Up;  //TIM向上计数模式

    TIM_TimeBaseInit(TIM4,&TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位

 

   

    /*配置中断优先级*/

    NVIC_InitStructure.NVIC_IRQChannel= TIM4_IRQn;                    

 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;

  NVIC_InitStructure.NVIC_IRQChannelSubPriority= 1;

 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

 NVIC_Init(&NVIC_InitStructure);

 

    TIM4_ICInitStructure.TIM_Channel= TIM_Channel_2;                  

 TIM4_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;      

 TIM4_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;  

 TIM4_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;

    TIM4_ICInitStructure.TIM_ICFilter= 0x0;

 

    TIM_PWMIConfig(TIM4,&TIM4_ICInitStructure);     //PWM输入配置           

 TIM_SelectInputTrigger(TIM4, TIM_TS_TI2FP2);     //选择有效输入端       

 TIM_SelectSlaveMode(TIM4, TIM_SlaveMode_Reset);  //配置为主从复位模式

 TIM_SelectMasterSlaveMode(TIM4, TIM_MasterSlaveMode_Enable);                                      

  TIM_ITConfig(TIM4,TIM_IT_CC2|TIM_IT_Update, ENABLE);         //中断配置

    TIM_ClearITPendingBit(TIM4,TIM_IT_CC2|TIM_IT_Update); //清除中断标志位

    TIM_Cmd(TIM4,ENABLE);   

}

 

u16 period = 0;

u16 duty  = 0;

u8 CollectFlag = 1;

 

void TIM4_IRQHandler(void)

{

 

    if(CollectFlag){

    if(TIM_GetITStatus(TIM4, TIM_IT_CC2) != RESET)//捕获1发生捕获事件

        {  

            duty= TIM_GetCapture1(TIM4);               //采集占空比       

          period    =   TIM_GetCapture2(TIM4);     //采集周期

        }

       

        CollectFlag= 0;

    }  

        TIM_ClearITPendingBit(TIM4,TIM_IT_CC2|TIM_IT_Update); //清除中断标志位

}

-----------------------------------------------main.c----------------------------------------------------------

#include "delay.h"

#include "sys.h"

#include "usart.h"

#include "exti.h"

#include "wdg.h"

#include "pwm.h"

 

 

extern void TIM3_PWM_Init(u16 arr,u16 psc);

extern void TIM4_PWMINPUT_INIT(u16 arr,u16 psc);

 

extern u16 period;

extern u16 duty ;

extern u8 CollectFlag ;

//Mini STM32开发板范例代码8

 

//技术论坛:www.openedv.com 

 int main(void)

 {

   

    SystemInit();

    delay_init(72);             //延时初始化

    NVIC_Configuration();  //中断配置

    uart_init(9600);                //串口初始化

    TIM3_PWM_Init(1000-1,72-1);   //1KHZ周期

    TIM_SetCompare1(TIM3,200);      //设置占空比

    TIM_SetCompare2(TIM3,400);      //设置占空比

    TIM_SetCompare3(TIM3,600);      //设置占空比

    TIM_SetCompare4(TIM3,800);      //设置占空比

    TIM4_PWMINPUT_INIT(0xffff,72-1);   //pwm输入初始化以1M的频率捕捉

 

//  PWM_Init(900,0);    //不分频。PWM频率=72000/900=8Khz

        while(1)

    {

            delay_ms(100);

         if(!CollectFlag)

            {

                printf("duty    = %d%%\r\n",duty*100/period);              //打印占空比

                printf("cycle  = %dKHz\r\n",1000/period);//打印周期另外一种叫法

                printf("period  = %dus\r\n",period);    //打印周期

                CollectFlag= 1;

            }

    }  

 

 }

------------------------------------------------------------------------------------------------------------------------------------------------------------------ 

分享PWM输入模式捕捉4路PWM波形的周期和占空比 源码+原理讲解+程序讲解 http://www.openedv.com/posts/list/23218.htm

TIM_OCMode_Timing是在比较成功后不在对应输出管脚上产生输出。

TIM_OCMode_Toggle是在比较成功后翻转对应输出管脚上的电平。

TIM_OCMode_Timing是在比较成功后不在对应输出管脚上产生输出,可是产生中断。